diff --git a/DEPS b/DEPS
index 6cc50b7..832046d 100644
--- a/DEPS
+++ b/DEPS
@@ -23,7 +23,7 @@
 #  # in origin/master. The path for the dep should start with src/.
 #  roll-dep src/third_party/foo_package/src foo_package.git
 #  # You should now have a modified DEPS file; commit and upload as normal
-#  git commit -a
+#  git commit -aspv_he
 #  git cl upload
 
 gclient_gn_args_file = 'src/build/config/gclient_args.gni'
@@ -162,11 +162,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': 'dd0dff1c35d2944ca6fb542bcec7ebae88ca1680',
+  'skia_revision': '8391bac5c6f07fd01e78cc140b01119de73a749d',
   # 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': '8d5e881636d1d70012c592e9e1bb18ae07ecfc11',
+  'v8_revision': '46e424ecc720115690fc6a2649654aee0cbfe1da',
   # 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.
@@ -174,7 +174,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': '873079f1d3a2c2861679b41463f4b1b80dc9afa5',
+  'angle_revision': 'e34564bafe835562087de0a2fb3c8386e0f6b0dd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -281,11 +281,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': 'ad7f2c5c4c7f51360e9e079109a9217aa5ba5cc0',
+  'spv_tools_revision': '36c1c0e22fab67f8f30aa7877f7a372629ede8de',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_headers_revision': '123dc278f204f8e833e1a88d31c46d0edf81d4b2',
+  'spv_headers_revision': '601d738723ac381741311c6c98c36d6170be14a2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -853,7 +853,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '83d2cae04c5f4598f4e97765fa7db541210f4593',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4599045c795c98ef18e4204ee012adbc38e87c5f',
       'condition': 'checkout_linux',
   },
 
@@ -878,7 +878,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6f9a0238ce40b6af186aac520c3b87ffa9a8be3b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3f79763629b43de8cb139f857e386be25d0ba058',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1257,7 +1257,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '859cb8a7e03490dd3aedd66666bdcf74285be402',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '56f9ee6b49fcb135a7a016bc12ca78a33486688a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1487,7 +1487,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@dd281eec08fe4be70d8f61b78f431f474141fe18',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@377dbef2b5ab30cc79c84a6493619602fe3f6713',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index 5773086..abf1cca 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -40,14 +40,12 @@
 #include "content/public/browser/android/synchronous_compositor.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/common/service_names.mojom.h"
 #include "net/android/network_change_notifier_factory_android.h"
 #include "net/base/network_change_notifier.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
 #include "ui/gl/gl_surface.h"
@@ -137,10 +135,8 @@
 
 void AwBrowserMainParts::PostCreateThreads() {
   heap_profiling::Mode mode = heap_profiling::GetModeForStartup();
-  if (mode != heap_profiling::Mode::kNone) {
-    heap_profiling::Supervisor::GetInstance()->Start(
-        content::GetSystemConnector(), base::OnceClosure());
-  }
+  if (mode != heap_profiling::Mode::kNone)
+    heap_profiling::Supervisor::GetInstance()->Start(base::NullCallback());
 }
 
 }  // namespace android_webview
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index e2e57f4c..598dda0 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -61,9 +61,14 @@
 
 // Returns the padding between the app icon and the end of the ScrollableShelf.
 int GetAppIconEndPadding() {
-  if (Shell::Get()->tablet_mode_controller()->InTabletMode())
-    return 4;
-  return 0;
+  TabletModeController* tablet_mode_controller =
+      Shell::Get()->tablet_mode_controller();
+
+  // TabletModeController is destructed before ScrollableShelfView.
+  if (!tablet_mode_controller || !tablet_mode_controller->InTabletMode())
+    return 0;
+
+  return 4;
 }
 
 // Calculates the padding for overflow.
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 0309bd0..6441cf9d 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -347,7 +347,6 @@
   shelf_layout_manager_->PrepareForShutdown();
 
   Shell::Get()->focus_cycler()->RemoveWidget(status_area_widget_.get());
-  status_area_widget_.reset();
 
   Shell::Get()->focus_cycler()->RemoveWidget(navigation_widget_.get());
   Shell::Get()->focus_cycler()->RemoveWidget(hotseat_widget_.get());
@@ -359,6 +358,11 @@
   // Don't need to observe focus/activation during shutdown.
   Shell::Get()->focus_cycler()->RemoveWidget(this);
   SetFocusCycler(nullptr);
+
+  // The contents view of |hotseat_widget_| may rely on |status_area_widget_|.
+  // So do explicit destruction here.
+  hotseat_widget_.reset();
+  status_area_widget_.reset();
 }
 
 void ShelfWidget::CreateNavigationWidget(aura::Window* container) {
@@ -591,4 +595,4 @@
     views::Widget::OnGestureEvent(event);
 }
 
-}  // namespace ash
\ No newline at end of file
+}  // namespace ash
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index 7bda71b..abef77b 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -50,11 +50,17 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import org.chromium.base.annotations.VerifiesOnLollipop;
+
 import java.io.UnsupportedEncodingException;
 
 /**
  * Utility class to use new APIs that were added after KitKat (API level 19).
+ *
+ * Do not inline because we use many new APIs, and if they are inlined, they could cause dex
+ * validation errors on low Android versions.
  */
+@VerifiesOnLollipop
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public class ApiCompatibilityUtils {
     private ApiCompatibilityUtils() {
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h
index 0fd63e3..fb87dd4 100644
--- a/base/containers/checked_iterators.h
+++ b/base/containers/checked_iterators.h
@@ -7,6 +7,7 @@
 
 #include <iterator>
 #include <memory>
+#include <type_traits>
 
 #include "base/containers/util.h"
 #include "base/logging.h"
@@ -14,29 +15,46 @@
 namespace base {
 
 template <typename T>
-class CheckedRandomAccessConstIterator;
-
-template <typename T>
 class CheckedRandomAccessIterator {
  public:
   using difference_type = std::ptrdiff_t;
-  using value_type = typename std::iterator_traits<T*>::value_type;
+  using value_type = std::remove_cv_t<T>;
   using pointer = T*;
   using reference = T&;
   using iterator_category = std::random_access_iterator_tag;
 
-  friend class CheckedRandomAccessConstIterator<T>;
+  // Required for converting constructor below.
+  template <typename U>
+  friend class CheckedRandomAccessIterator;
 
   CheckedRandomAccessIterator() = default;
   CheckedRandomAccessIterator(T* start, const T* end)
       : CheckedRandomAccessIterator(start, start, end) {}
-  CheckedRandomAccessIterator(T* start, T* current, const T* end)
+  CheckedRandomAccessIterator(const T* start, T* current, const T* end)
       : start_(start), current_(current), end_(end) {
     CHECK(start <= current);
     CHECK(current <= end);
   }
   CheckedRandomAccessIterator(const CheckedRandomAccessIterator& other) =
       default;
+
+  // Converting constructor allowing conversions like CRAI<T> to CRAI<const T>,
+  // but disallowing CRAI<const T> to CRAI<T> or CRAI<Derived> to CRAI<Base>,
+  // which are unsafe. Furthermore, this is the same condition as used by the
+  // converting constructors of std::span<T> and std::unique_ptr<T[]>.
+  // See https://wg21.link/n4042 for details.
+  template <
+      typename U,
+      std::enable_if_t<std::is_convertible<U (*)[], T (*)[]>::value>* = nullptr>
+  CheckedRandomAccessIterator(const CheckedRandomAccessIterator<U>& other)
+      : start_(other.start_), current_(other.current_), end_(other.end_) {
+    // We explicitly don't delegate to the 3-argument constructor here. Its
+    // CHECKs would be redundant, since we expect |other| to maintain its own
+    // invariant. However, DCHECKs never hurt anybody. Presumably.
+    DCHECK(other.start_ <= other.current_);
+    DCHECK(other.current_ <= other.end_);
+  }
+
   ~CheckedRandomAccessIterator() = default;
 
   CheckedRandomAccessIterator& operator=(
@@ -179,176 +197,7 @@
 };
 
 template <typename T>
-class CheckedRandomAccessConstIterator {
- public:
-  using difference_type = std::ptrdiff_t;
-  using value_type = typename std::iterator_traits<T*>::value_type;
-  using pointer = const T*;
-  using reference = const T&;
-  using iterator_category = std::random_access_iterator_tag;
-
-  CheckedRandomAccessConstIterator() = default;
-  CheckedRandomAccessConstIterator(T* start, const T* end)
-      : CheckedRandomAccessConstIterator(start, start, end) {}
-  CheckedRandomAccessConstIterator(T* start, T* current, const T* end)
-      : start_(start), current_(current), end_(end) {
-    CHECK(start <= current);
-    CHECK(current <= end);
-  }
-  CheckedRandomAccessConstIterator(
-      const CheckedRandomAccessConstIterator& other) = default;
-  CheckedRandomAccessConstIterator(const CheckedRandomAccessIterator<T>& other)
-      : start_(other.start_), current_(other.current_), end_(other.end_) {
-    // We explicitly don't delegate to the 3-argument constructor here. Its
-    // CHECKs would be redundant, since we expect |other| to maintain its own
-    // invariant. However, DCHECKs never hurt anybody. Presumably.
-    DCHECK(other.start_ <= other.current_);
-    DCHECK(other.current_ <= other.end_);
-  }
-  ~CheckedRandomAccessConstIterator() = default;
-
-  CheckedRandomAccessConstIterator& operator=(
-      const CheckedRandomAccessConstIterator& other) = default;
-
-  CheckedRandomAccessConstIterator& operator=(
-      CheckedRandomAccessConstIterator& other) = default;
-
-  bool operator==(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ == other.current_;
-  }
-
-  bool operator!=(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ != other.current_;
-  }
-
-  bool operator<(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ < other.current_;
-  }
-
-  bool operator<=(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ <= other.current_;
-  }
-
-  bool operator>(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ > other.current_;
-  }
-
-  bool operator>=(const CheckedRandomAccessConstIterator& other) const {
-    CheckComparable(other);
-    return current_ >= other.current_;
-  }
-
-  CheckedRandomAccessConstIterator& operator++() {
-    CHECK(current_ != end_);
-    ++current_;
-    return *this;
-  }
-
-  CheckedRandomAccessConstIterator operator++(int) {
-    CheckedRandomAccessConstIterator old = *this;
-    ++*this;
-    return old;
-  }
-
-  CheckedRandomAccessConstIterator& operator--() {
-    CHECK(current_ != start_);
-    --current_;
-    return *this;
-  }
-
-  CheckedRandomAccessConstIterator& operator--(int) {
-    CheckedRandomAccessConstIterator old = *this;
-    --*this;
-    return old;
-  }
-
-  CheckedRandomAccessConstIterator& operator+=(difference_type rhs) {
-    if (rhs > 0) {
-      CHECK_LE(rhs, end_ - current_);
-    } else {
-      CHECK_LE(-rhs, current_ - start_);
-    }
-    current_ += rhs;
-    return *this;
-  }
-
-  CheckedRandomAccessConstIterator operator+(difference_type rhs) const {
-    CheckedRandomAccessConstIterator it = *this;
-    it += rhs;
-    return it;
-  }
-
-  CheckedRandomAccessConstIterator& operator-=(difference_type rhs) {
-    if (rhs < 0) {
-      CHECK_LE(rhs, end_ - current_);
-    } else {
-      CHECK_LE(-rhs, current_ - start_);
-    }
-    current_ -= rhs;
-    return *this;
-  }
-
-  CheckedRandomAccessConstIterator operator-(difference_type rhs) const {
-    CheckedRandomAccessConstIterator it = *this;
-    it -= rhs;
-    return it;
-  }
-
-  friend difference_type operator-(
-      const CheckedRandomAccessConstIterator& lhs,
-      const CheckedRandomAccessConstIterator& rhs) {
-    CHECK(lhs.start_ == rhs.start_);
-    CHECK(lhs.end_ == rhs.end_);
-    return lhs.current_ - rhs.current_;
-  }
-
-  reference operator*() const {
-    CHECK(current_ != end_);
-    return *current_;
-  }
-
-  pointer operator->() const {
-    CHECK(current_ != end_);
-    return current_;
-  }
-
-  reference operator[](difference_type rhs) const {
-    CHECK_GE(rhs, 0);
-    CHECK_LT(rhs, end_ - current_);
-    return current_[rhs];
-  }
-
-  static bool IsRangeMoveSafe(
-      const CheckedRandomAccessConstIterator& from_begin,
-      const CheckedRandomAccessConstIterator& from_end,
-      const CheckedRandomAccessConstIterator& to) WARN_UNUSED_RESULT {
-    if (from_end < from_begin)
-      return false;
-    const auto from_begin_uintptr = get_uintptr(from_begin.current_);
-    const auto from_end_uintptr = get_uintptr(from_end.current_);
-    const auto to_begin_uintptr = get_uintptr(to.current_);
-    const auto to_end_uintptr =
-        get_uintptr((to + std::distance(from_begin, from_end)).current_);
-
-    return to_begin_uintptr >= from_end_uintptr ||
-           to_end_uintptr <= from_begin_uintptr;
-  }
-
- private:
-  void CheckComparable(const CheckedRandomAccessConstIterator& other) const {
-    CHECK_EQ(start_, other.start_);
-    CHECK_EQ(end_, other.end_);
-  }
-
-  const T* start_ = nullptr;
-  const T* current_ = nullptr;
-  const T* end_ = nullptr;
-};
+using CheckedRandomAccessConstIterator = CheckedRandomAccessIterator<const T>;
 
 }  // namespace base
 
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc
index e2d437a..e726cb7 100644
--- a/base/containers/span_unittest.cc
+++ b/base/containers/span_unittest.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <memory>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "base/containers/checked_iterators.h"
@@ -1318,4 +1319,14 @@
   EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1));
 }
 
+TEST(SpanTest, IteratorConversions) {
+  static_assert(std::is_convertible<span<int>::iterator,
+                                    span<int>::const_iterator>::value,
+                "Error: iterator should be convertible to const_iterator");
+
+  static_assert(!std::is_convertible<span<int>::const_iterator,
+                                     span<int>::iterator>::value,
+                "Error: const_iterator should not be convertible to iterator");
+}
+
 }  // namespace base
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py
index c6efb549f..760d21c 100755
--- a/build/android/apk_operations.py
+++ b/build/android/apk_operations.py
@@ -227,17 +227,7 @@
         print(_Colorize(msg, colorama.Fore.YELLOW + colorama.Style.BRIGHT))
 
     InstallFakeModules(device)
-
-    # NOTE: For now, installation requires running 'bundletool install-apks'.
-    # TODO(digit): Add proper support for bundles to devil instead, then use it.
-    install_cmd_args = [
-        'install-apks', '--apks=' + bundle_apks, '--allow-downgrade',
-        '--adb=' + adb_wrapper.AdbWrapper.GetAdbPath(),
-        '--device-id=' + device.serial
-    ]
-    if modules:
-      install_cmd_args += ['--modules=' + ','.join(modules)]
-    bundletool.RunBundleTool(install_cmd_args)
+    device.Install(bundle_apks, modules=modules, allow_downgrade=True)
 
   # Basic checks for |modules| and |fake_modules|.
   # * |fake_modules| cannot include 'base'.
diff --git a/build/android/docs/coverage.md b/build/android/docs/coverage.md
index 6ea548a..35cd809 100644
--- a/build/android/docs/coverage.md
+++ b/build/android/docs/coverage.md
@@ -17,7 +17,7 @@
 
   ```gn
   target_os = "android"
-  jacoco_coverage = true
+  use_jacoco_coverage = true
   ```
 
    Now when building, pre-instrumented files will be created in the build directory.
diff --git a/build/android/gyp/jacoco_instr.py b/build/android/gyp/jacoco_instr.py
index 4deea439..2f927d1 100755
--- a/build/android/gyp/jacoco_instr.py
+++ b/build/android/gyp/jacoco_instr.py
@@ -6,7 +6,7 @@
 
 """Instruments classes and jar files.
 
-This script corresponds to the 'jacoco_instr' action in the java build process.
+This script corresponds to the 'jacoco_instr' action in the Java build process.
 Depending on whether jacoco_instrument is set, the 'jacoco_instr' action will
 call the instrument command which accepts a jar and instruments it using
 jacococli.jar.
@@ -21,6 +21,7 @@
 import shutil
 import sys
 import tempfile
+import zipfile
 
 from util import build_utils
 
@@ -53,6 +54,9 @@
       help='File containing newline-separated .java paths')
   parser.add_argument(
       '--jacococli-jar', required=True, help='Path to jacococli.jar.')
+  parser.add_argument(
+      '--files-to-instrument',
+      help='Path to a file containing which source files are affected.')
 
 
 def _GetSourceDirsFromSourceFiles(source_files):
@@ -101,8 +105,100 @@
     json.dump(data, f)
 
 
+def _GetAffectedClasses(jar_file, source_files):
+  """Gets affected classes by affected source files to a jar.
+
+  Args:
+    jar_file: The jar file to get all members.
+    source_files: The list of affected source files.
+
+  Returns:
+    A tuple of affected classes and unaffected members.
+  """
+  with zipfile.ZipFile(jar_file) as f:
+    members = f.namelist()
+
+  affected_classes = []
+  unaffected_members = []
+
+  for member in members:
+    if not member.endswith('.class'):
+      unaffected_members.append(member)
+      continue
+
+    is_affected = False
+    index = member.find('$')
+    if index == -1:
+      index = member.find('.class')
+    for source_file in source_files:
+      if source_file.endswith(member[:index] + '.java'):
+        affected_classes.append(member)
+        is_affected = True
+        break
+    if not is_affected:
+      unaffected_members.append(member)
+
+  return affected_classes, unaffected_members
+
+
+def _InstrumentWholeJar(instrument_cmd, input_path, output_path, temp_dir):
+  """Instruments input jar to output_path.
+
+  Args:
+    instrument_cmd: JaCoCo instrument command.
+    input_path: The input path to non-instrumented jar.
+    output_path: The output path to instrumented jar.
+    temp_dir: The temporary directory.
+  """
+  instrument_cmd.extend([input_path, '--dest', temp_dir])
+
+  build_utils.CheckOutput(instrument_cmd)
+
+  jars = os.listdir(temp_dir)
+  if len(jars) != 1:
+    raise Exception('Error: multiple output files: %s' % jars)
+
+  # Delete output_path first to avoid modifying input_path in the case where
+  # input_path is a hardlink to output_path. http://crbug.com/571642
+  if os.path.exists(output_path):
+    os.unlink(output_path)
+  shutil.move(os.path.join(temp_dir, jars[0]), output_path)
+
+
+def _InstrumentClassFiles(instrument_cmd, input_path, output_path, temp_dir,
+                          affected_source_files):
+  """Instruments affected class files from input jar.
+
+  Args:
+    instrument_cmd: JaCoCo instrument command.
+    input_path: The input path to non-instrumented jar.
+    output_path: The output path to instrumented jar.
+    temp_dir: The temporary directory.
+    affected_source_files: The affected source file paths to input jar.
+  """
+  affected_classes, unaffected_members = _GetAffectedClasses(
+      input_path, affected_source_files)
+
+  # Extract affected class files.
+  with zipfile.ZipFile(input_path) as f:
+    f.extractall(temp_dir, affected_classes)
+
+  instrumented_dir = os.path.join(temp_dir, 'instrumented')
+
+  # Instrument extracted class files.
+  instrument_cmd.extend([temp_dir, '--dest', instrumented_dir])
+  build_utils.CheckOutput(instrument_cmd)
+
+  # Extract unaffected members to instrumented_dir.
+  with zipfile.ZipFile(input_path) as f:
+    f.extractall(instrumented_dir, unaffected_members)
+
+  # Zip all files to output_path
+  build_utils.ZipDir(output_path, instrumented_dir)
+
+
 def _RunInstrumentCommand(parser):
-  """Instruments jar files using Jacoco.
+  """Instruments class or Jar files using JaCoCo.
 
   Args:
     parser: ArgumentParser object.
@@ -112,33 +208,30 @@
   """
   args = parser.parse_args()
 
-  temp_dir = tempfile.mkdtemp()
-  try:
-    cmd = [
-        'java', '-jar', args.jacococli_jar, 'instrument', args.input_path,
-        '--dest', temp_dir
-    ]
-
-    build_utils.CheckOutput(cmd)
-
-    jars = os.listdir(temp_dir)
-    if len(jars) != 1:
-      print('Error: multiple output files in: %s' % (temp_dir))
-      return 1
-
-    # Delete output_path first to avoid modifying input_path in the case where
-    # input_path is a hardlink to output_path. http://crbug.com/571642
-    if os.path.exists(args.output_path):
-      os.unlink(args.output_path)
-    shutil.move(os.path.join(temp_dir, jars[0]), args.output_path)
-  finally:
-    shutil.rmtree(temp_dir)
-
   source_files = []
   if args.java_sources_file:
     source_files.extend(build_utils.ReadSourcesList(args.java_sources_file))
-  source_dirs = _GetSourceDirsFromSourceFiles(source_files)
 
+  with build_utils.TempDir() as temp_dir:
+    instrument_cmd = ['java', '-jar', args.jacococli_jar, 'instrument']
+
+    if not args.files_to_instrument:
+      _InstrumentWholeJar(instrument_cmd, args.input_path, args.output_path,
+                          temp_dir)
+    else:
+      affected_files = build_utils.ReadSourcesList(args.files_to_instrument)
+      source_set = set(source_files)
+      affected_source_files = [f for f in affected_files if f in source_set]
+
+      # Copy input_path to output_path and return if no source file affected.
+      if not affected_source_files:
+        shutil.copyfile(args.input_path, args.output_path)
+        return 0
+      else:
+        _InstrumentClassFiles(instrument_cmd, args.input_path, args.output_path,
+                              temp_dir, affected_source_files)
+
+  source_dirs = _GetSourceDirsFromSourceFiles(source_files)
   # TODO(GYP): In GN, we are passed the list of sources, detecting source
   # directories, then walking them to re-establish the list of sources.
   # This can obviously be simplified!
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index 5d5d6dda..4f7b992 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -135,9 +135,6 @@
   options.extra_mapping_output_paths = build_utils.ParseGnList(
       options.extra_mapping_output_paths)
 
-  if options.apply_mapping:
-    options.apply_mapping = os.path.abspath(options.apply_mapping)
-
   return options
 
 
@@ -331,7 +328,7 @@
 }""" % options.min_api)
 
   if options.apply_mapping:
-    ret.append("-applymapping '%s'" % options.apply_mapping)
+    ret.append("-applymapping '%s'" % os.path.abspath(options.apply_mapping))
   if options.repackage_classes:
     ret.append("-repackageclasses '%s'" % options.repackage_classes)
 
@@ -413,7 +410,7 @@
 
   inputs = options.proguard_configs + options.input_paths + libraries
   if options.apply_mapping:
-    inputs += options.apply_mapping
+    inputs.append(options.apply_mapping)
 
   build_utils.WriteDepfile(
       options.depfile, options.output_path, inputs=inputs, add_pydeps=False)
diff --git a/build/android/list_class_verification_failures.py b/build/android/list_class_verification_failures.py
index cfcb2ac..da7d0a8 100755
--- a/build/android/list_class_verification_failures.py
+++ b/build/android/list_class_verification_failures.py
@@ -121,10 +121,11 @@
   """Runs oatdump on the device."""
   # Get the path to the odex file.
   odex_file = PathToDexForPlatformVersion(device, package_name)
-  device.RunShellCommand(['oatdump',
-                          '--oat-file=' + odex_file,
-                          '--output=' + out_file],
-                         timeout=120, shell=True, check_return=True)
+  device.RunShellCommand(
+      ['oatdump', '--oat-file=' + odex_file, '--output=' + out_file],
+      timeout=420,
+      shell=True,
+      check_return=True)
 
 
 class JavaClass(object):
@@ -211,7 +212,7 @@
       device.adb) as file_on_device:
     _AdbOatDumpForPackage(device, package, file_on_device.name)
     file_on_host = os.path.join(workdir, 'out.dump')
-    device.PullFile(file_on_device.name, file_on_host)
+    device.PullFile(file_on_device.name, file_on_host, timeout=220)
   proguard_mappings = (_ParseMappingFile(mapping) if mapping else None)
   with open(file_on_host, 'r') as f:
     java_classes = ListClassesAndVerificationStatus(f, proguard_mappings)
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index c1bfc87..6a606d6 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -182,10 +182,6 @@
     # Set to false to disable the Errorprone compiler
     use_errorprone_java_compiler = true
 
-    # Enables Jacoco Java code coverage. Instruments classes during build to
-    # produce .exec files during runtime
-    jacoco_coverage = false
-
     # Disables process isolation when building _incremental targets.
     # Required for Android M+ due to SELinux policies (stronger sandboxing).
     disable_incremental_isolated_processes = false
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index d294f207..64399ca4f 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -6,6 +6,7 @@
 # Some projects (e.g. V8) do not have non-build directories DEPS'ed in.
 import("//build/config/android/config.gni")
 import("//build/config/android/copy_ex.gni")
+import("//build/config/coverage/coverage.gni")
 import("//build/config/dcheck_always_on.gni")
 import("//build/config/python.gni")
 import("//build/config/sanitizers/sanitizers.gni")
@@ -697,7 +698,7 @@
       if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) {
         executable_args += [ "--enable-java-deobfuscation" ]
       }
-      if (jacoco_coverage) {
+      if (use_jacoco_coverage) {
         # Set a default coverage output directory (can be overridden by user
         # passing the same flag).
         _rebased_coverage_dir =
@@ -729,7 +730,7 @@
         "--robolectric-runtime-deps-dir",
         "@WrappedPath(${_rebased_robolectric_runtime_deps_dir})",
       ]
-      if (jacoco_coverage) {
+      if (use_jacoco_coverage) {
         # Set a default coverage output directory (can be overridden by user
         # passing the same flag).
         _rebased_coverage_dir =
@@ -1092,7 +1093,7 @@
       }
       args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)" ]
 
-      if (jacoco_coverage) {
+      if (use_jacoco_coverage) {
         args += [
           "--classpath",
           rebase_path("//third_party/jacoco/lib/jacocoagent.jar",
@@ -1434,6 +1435,8 @@
         rebase_path(invoker.java_sources_file, root_build_dir),
         "--jacococli-jar",
         rebase_path(_jacococli_jar, root_build_dir),
+        "--files-to-instrument",
+        rebase_path(coverage_instrumentation_input_file, root_build_dir),
       ]
     }
   }
@@ -3084,7 +3087,7 @@
   #    Chromium-specific unless it is in a 'chromium' sub-directory).
   #  jacoco_never_instrument: Optional. If provided, whether to forbid
   #    instrumentation with the Jacoco coverage processor. If not provided,
-  #    this is controlled by the global jacoco_coverage build arg variable
+  #    this is controlled by the global use_jacoco_coverage build arg variable
   #    and only used for non-test Chromium code.
   #  include_android_sdk: Optional. Whether or not the android SDK dep
   #    should be added to deps. Defaults to true for non-system libraries
@@ -3304,7 +3307,7 @@
 
     if (defined(_final_jar_path)) {
       _jacoco_instrument =
-          jacoco_coverage && _chromium_code && _java_files != [] &&
+          use_jacoco_coverage && _chromium_code && _java_files != [] &&
           !_is_java_binary && !_is_annotation_processor &&
           (!defined(invoker.testonly) || !invoker.testonly)
       if (defined(invoker.jacoco_never_instrument)) {
diff --git a/build/config/coverage/coverage.gni b/build/config/coverage/coverage.gni
index fe3af77..9586d8d 100644
--- a/build/config/coverage/coverage.gni
+++ b/build/config/coverage/coverage.gni
@@ -5,15 +5,20 @@
 import("//build/toolchain/toolchain.gni")
 
 # There are two ways to enable code coverage instrumentation:
-# 1. When |use_clang_coverage| is true and |coverage_instrumentation_input_file|
-#    is empty, all source files are instrumented.
-# 2. When |use_clang_coverage| is true and |coverage_instrumentation_input_file|
-#    is NOT empty and points to a text file on the file system, ONLY source
-#    files specified in the input file are instrumented.
+# 1. When |use_clang_coverage| or |use_jacoco_coverage| is true and
+#    |coverage_instrumentation_input_file| is empty, all source files or
+#    Java class files are instrumented.
+# 2. When |use_clang_coverage| or |use_jacoco_coverage| is true and
+#    |coverage_instrumentation_input_file| is NOT empty and points to
+#    a text file on the file system, ONLY source files specified in the
+#    input file or Java class files related to source files are instrumented.
 declare_args() {
   # Enable Clang's Source-based Code Coverage.
   use_clang_coverage = false
 
+  # Enables JaCoCo Java code coverage.
+  use_jacoco_coverage = false
+
   # The path to the coverage instrumentation input file should be a source root
   # absolute path (e.g. //out/Release/coverage_instrumentation_input.txt), and
   # the file consists of multiple lines where each line represents a path to a
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3912a82..d847d9e 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -142,17 +142,6 @@
   }
 }
 
-if (notouch_build) {
-  android_resources("chrome_touchless_java_resources") {
-    resource_dirs = [ "//chrome/android/touchless/java/res" ]
-    deps = [
-      ":chrome_app_java_resources",
-      "//chrome/android/touchless:touchless_strings_grd",
-    ]
-    custom_package = "org.chromium.chrome.touchless"
-  }
-}
-
 android_resources("chrome_download_java_resources") {
   resource_dirs = [ "//chrome/android/java/res_download" ]
   deps = [
@@ -289,9 +278,9 @@
     "//chrome/android/webapk/libs/runtime_library:webapk_service_aidl_java",
     "//chrome/browser/android/thin_webview:factory_java",
     "//chrome/browser/android/thin_webview:java",
+    "//chrome/browser/image_fetcher:java",
     "//chrome/browser/ui/android/widget:java",
     "//chrome/browser/util/android:java",
-    "//chrome/lib/image_fetcher/public/android:java",
     "//chrome/lib/lifecycle/public/android:java",
     "//chrome/lib/util/public/android:java",
     "//components/autofill/android:autofill_java",
@@ -475,9 +464,6 @@
   if (enable_feed_in_chrome) {
     deps += [ ":chrome_feed_java_resources" ]
   }
-  if (notouch_build) {
-    deps += [ ":chrome_touchless_java_resources" ]
-  }
 
   # Add the actual implementation where necessary so that downstream targets
   # can provide their own implementations.
@@ -548,7 +534,7 @@
     "//chrome/android/features/keyboard_accessory:jni_headers",
     "//chrome/android/features/media_router:jni_headers",
     "//chrome/android/public/profiles:jni_headers",
-    "//chrome/lib/image_fetcher/public/android:jni_headers",
+    "//chrome/browser/image_fetcher:jni_headers",
     "//chrome/lib/util/public/android:jni_headers",
   ]
 }
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index 9e474f15..f891ea6 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -34,8 +34,8 @@
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_public_java",
     "//chrome/android/public/profiles:java",
+    "//chrome/browser/image_fetcher:java",
     "//chrome/browser/ui/android/widget:java",
-    "//chrome/lib/image_fetcher/public/android:java",
     "//components/policy/android:policy_java",
     "//components/signin/core/browser/android:java",
     "//components/url_formatter/android:url_formatter_java",
@@ -212,7 +212,7 @@
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_util_java",
-    "//chrome/lib/image_fetcher/public/android:java",
+    "//chrome/browser/image_fetcher:java",
     "//chrome/test/android:chrome_java_test_support",
     "//components/autofill_assistant/browser:proto_java",
     "//content/public/android:content_java",
diff --git a/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
index dab25141..6350e1cd 100644
--- a/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
@@ -15,7 +15,8 @@
         android:layout_height="wrap_content"
         android:background="@color/modern_primary_color"
         android:visibility="gone"
-        android:scrollbars="none">
+        android:scrollbars="none"
+        android:paddingBottom="@dimen/tasks_view_items_vertical_spacing">
         <LinearLayout android:id="@+id/mv_tiles_layout"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
@@ -33,8 +34,8 @@
             android:layout_height="wrap_content"
             android:layout_weight="1.0"
             android:layout_gravity="center_vertical"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dp"
+            android:paddingTop="@dimen/tasks_view_items_vertical_spacing"
+            android:paddingBottom="@dimen/tasks_view_items_vertical_spacing"
             android:paddingStart="24dp"
             android:paddingEnd="16dp"
             android:textAlignment="viewStart"
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml
index e183dec..e9a43c8 100644
--- a/chrome/android/features/tab_ui/java/res/values/dimens.xml
+++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -32,4 +32,5 @@
     <dimen name="tab_carousel_height">192dp</dimen>
     <dimen name="tab_carousel_card_width">168dp</dimen>
     <dimen name="tab_carousel_start_margin">-3dp</dimen>
+    <dimen name="tasks_view_items_vertical_spacing">8dp</dimen>
 </resources>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java
index 550fdfe..b3e580b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java
@@ -144,7 +144,7 @@
 
         @Override
         public void onClick(View v) {
-            ReturnToChromeExperimentsUtil.willHandleLoadUrlFromLocationBar(
+            ReturnToChromeExperimentsUtil.willHandleLoadUrlFromStartSurface(
                     mTile.getUrl(), PageTransition.AUTO_BOOKMARK);
         }
 
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 0397e82..e673d140 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -376,30 +376,6 @@
             </intent-filter>
         </activity-alias>
 
-        {% if notouch_build == "true" %}
-        <activity-alias android:name="com.google.android.apps.chrome.DinoActivity"
-            android:targetActivity="org.chromium.chrome.browser.touchless.DinoActivity"
-            android:exported="true">
-            <intent-filter android:priority="-1">
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity-alias>
-
-        <activity android:name="org.chromium.chrome.browser.touchless.DinoActivity"
-          android:theme="@style/Theme.Chromium.Activity"
-            android:icon="@mipmap/dino"
-            android:label="@string/dino_game_title"
-            android:exported="false"
-            android:persistableMode="persistNever"
-            android:launchMode="singleTask"
-            android:taskAffinity=""
-            android:noHistory="true"
-            {{ self.chrome_activity_common() }}>
-          </activity>
-        {% endif %}
-
         <activity android:name="org.chromium.chrome.browser.LauncherShortcutActivity"
             android:theme="@android:style/Theme.NoDisplay"
             android:taskAffinity=""
@@ -547,9 +523,7 @@
         </activity>
         <!-- TODO(crbug.com/780674): retarget .Main back to CTA for non-modern APK -->
         <activity-alias android:name="com.google.android.apps.chrome.Main"
-            {% if notouch_build == "true" %}
-            android:targetActivity="org.chromium.chrome.browser.touchless.NoTouchActivity"
-            {% elif min_sdk_version|int < 21 %}
+            {% if min_sdk_version|int < 21 %}
             android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity"
             {% else %}
             android:targetActivity="org.chromium.chrome.browser.ChromeTabbedActivity"
@@ -589,16 +563,6 @@
             {{ self.chrome_activity_common() }}>
             {{ self.extra_web_rendering_activity_definitions() }}
         </activity>
-        {% if notouch_build == "true" %}
-        <activity android:name="org.chromium.chrome.browser.touchless.NoTouchActivity"
-            android:theme="@style/Theme.Chromium.Activity"
-            android:exported="false"
-            android:launchMode="singleTask"
-            {{ self.chrome_activity_common() }}
-            {{ self.supports_video_persistence() }} >
-            {{ self.extra_web_rendering_activity_definitions() }}
-        </activity>
-        {% endif %}
 
         <activity android:name="org.chromium.chrome.browser.sync.ui.PassphraseActivity"
             android:theme="@style/Theme.Chromium.Activity"
@@ -639,16 +603,8 @@
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"
             android:exported="false">
         </activity>
-        {% if notouch_build == "true" %}
-        <activity-alias android:name="org.chromium.chrome.browser.preferences.Preferences"
-            android:targetActivity="org.chromium.chrome.browser.touchless.TouchlessPreferences">
-        </activity-alias>
-        <activity android:name="org.chromium.chrome.browser.touchless.TouchlessPreferences"
-            android:theme="@style/Theme.Chromium.Preferences.Touchless"
-        {% else %}
         <activity android:name="org.chromium.chrome.browser.preferences.Preferences"
             android:theme="@style/Theme.Chromium.Preferences"
-        {% endif %}
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"
             android:label="@string/preferences"
             android:exported="false">
@@ -702,15 +658,6 @@
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
         </activity>
 
-        {% if notouch_build == "true" %}
-        <activity android:name="org.chromium.chrome.browser.download.TouchlessDownloadActivity"
-            android:theme="@style/Theme.Chromium.Activity.Fullscreen"
-            android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
-            android:exported="false"
-            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize">
-        </activity>
-        {% endif %}
-
         <!-- Activities for history. -->
         <activity android:name="org.chromium.chrome.browser.history.HistoryActivity"
             android:theme="@style/Theme.Chromium.Activity.Fullscreen"
diff --git a/chrome/android/java/res/drawable/ic_check_circle.xml b/chrome/android/java/res/drawable/ic_check_circle.xml
deleted file mode 100644
index b96da6f2..0000000
--- a/chrome/android/java/res/drawable/ic_check_circle.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        tools:targetApi="21"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/default_icon_color"
-        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM10,14.2l-2.6,-2.6L6,13l4,4 8,-8 -1.4,-1.4z"/>
-</vector>
diff --git a/chrome/android/java/src/PRESUBMIT.py b/chrome/android/java/src/PRESUBMIT.py
index bdd92fc0..b3125b8 100644
--- a/chrome/android/java/src/PRESUBMIT.py
+++ b/chrome/android/java/src/PRESUBMIT.py
@@ -100,14 +100,11 @@
   below.
 
   We recommend you use ModalDialogProperties to show a dialog whenever possible
-  to support VR mode and Touchless mode. You could only keep the AlertDialog if
-  you are certain that
-    1) Your new AlertDialog is not used in VR mode (e.g. pereference, FRE)
-    2) You have handled Touchless display if Touchless mode is relevant
+  to support VR mode. You could only keep the AlertDialog if you are certain
+  that your new AlertDialog is not used in VR mode (e.g. pereference, FRE)
 
   If you are in doubt, contact
   //src/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS
-  //src/chrome/android/touchless/OWNERS
   '''
   error_files = []
   result = _CheckReIgnoreComment(input_api, output_api, error_msg, blacklist,
@@ -160,14 +157,11 @@
   constructors, listed below.
 
   We recommend you use ModalDialogProperties to show a dialog whenever possible
-  to support VR mode and Touchless mode. You could only keep the AlertDialog if
-  you are certain that
-    1) Your new AlertDialog is not used in VR mode (e.g. pereference, FRE)
-    2) You have handled Touchless display if Touchless mode is relevant
+  to support VR mode. You could only keep the AlertDialog if you are certain
+  that your new AlertDialog is not used in VR mode (e.g. pereference, FRE)
 
   If you are in doubt, contact
   //src/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS
-  //src/chrome/android/touchless/OWNERS
   '''
   return _CheckReIgnoreComment(input_api, output_api, error_msg, blacklist,
                                NEW_COMPATIBLE_ALERTDIALOG_BUILDER_RE)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
index fb315694..e005af4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -4,15 +4,12 @@
 
 package org.chromium.chrome.browser;
 
-import android.app.Activity;
 import android.app.Notification;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.os.Bundle;
 import android.view.View;
-import android.view.inputmethod.InputConnection;
 
 import androidx.annotation.Nullable;
 
@@ -20,7 +17,6 @@
 import com.google.android.gms.common.GoogleApiAvailability;
 
 import org.chromium.base.Callback;
-import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -34,7 +30,6 @@
 import org.chromium.chrome.browser.feedback.FeedbackReporter;
 import org.chromium.chrome.browser.feedback.FeedbackSource;
 import org.chromium.chrome.browser.feedback.FeedbackSourceProvider;
-import org.chromium.chrome.browser.firstrun.FreIntentCreator;
 import org.chromium.chrome.browser.gsa.GSAHelper;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.historyreport.AppIndexingReporter;
@@ -57,9 +52,6 @@
 import org.chromium.chrome.browser.survey.SurveyController;
 import org.chromium.chrome.browser.tab.AuthenticatorNavigationInterceptor;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.touchless.TouchlessModelCoordinator;
-import org.chromium.chrome.browser.touchless.TouchlessUiCoordinator;
 import org.chromium.chrome.browser.ui.ImmersiveModeManager;
 import org.chromium.chrome.browser.usage_stats.DigitalWellbeingClient;
 import org.chromium.chrome.browser.webapps.GooglePlayWebApkInstallDelegate;
@@ -68,12 +60,9 @@
 import org.chromium.components.download.DownloadCollectionBridge;
 import org.chromium.components.signin.AccountManagerDelegate;
 import org.chromium.components.signin.SystemAccountManagerDelegate;
-import org.chromium.content_public.browser.RenderFrameHost;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.content_public.browser.WebContents;
 import org.chromium.policy.AppRestrictionsProvider;
 import org.chromium.policy.CombinedPolicyProvider;
-import org.chromium.services.service_manager.InterfaceRegistry;
 
 import java.util.Collections;
 import java.util.List;
@@ -109,19 +98,6 @@
     }
 
     /**
-     * Perform platform-specific command line initialization.
-     * @param instance CommandLine instance to be updated.
-     */
-    public void initCommandLine(CommandLine instance) {}
-
-    /**
-     * Inform platform of current display mode.
-     * @param displayMode the new display mode (see WebDisplayMode)
-     * @param activity the affected activity.
-     */
-    public void setDisplayModeForActivity(int displayMode, Activity activity) {}
-
-    /**
      * Creates a new {@link AccountManagerDelegate}.
      * @return the created {@link AccountManagerDelegate}.
      */
@@ -392,22 +368,6 @@
     }
 
     /**
-     * @param activity An activity for access to different features.
-     * @return A new {@link TouchlessModelCoordinator} instance.
-     */
-    public TouchlessModelCoordinator createTouchlessModelCoordinator(Activity activity) {
-        return null;
-    }
-
-    /**
-     * @param activity An activity for access to different features.
-     * @return A new {@link TouchlessUiCoordinator} instance.
-     */
-    public TouchlessUiCoordinator createTouchlessUiCoordinator(ChromeActivity activity) {
-        return TouchlessDelegate.getTouchlessUiCoordinator(activity);
-    }
-
-    /**
      * Checks the Google Play services availability on the this device.
      *
      * This is a workaround for the
@@ -433,55 +393,10 @@
     }
 
     /**
-     * Returns a new {@link FreIntentCreator} instance.
-     */
-    public FreIntentCreator createFreIntentCreator() {
-        return new FreIntentCreator();
-    }
-
-    /**
-     * @return true if the webAppIntent has been intercepted.
-     */
-    public boolean interceptWebAppIntent(Intent intent, ChromeActivity activity) {
-        return false;
-    }
-
-    /**
-     * @see InputConnection#performPrivateCommand(java.lang.String, android.os.Bundle)
-     * @param webcontents The WebContents receiving the private IME command.
-     */
-    public void performPrivateImeCommand(WebContents webContents, String action, Bundle data) {}
-
-    /**
-     * Called when the Search Context Menu Item is clicked.
-     */
-    public void onSearchContextMenuClick() {}
-
-    /**
-     * @param registry The Chrome interface registry for the RenderFrameHost.
-     * @param renderFrameHost The RenderFrameHost the Interface Registry is for.
-     */
-    public void registerChromeRenderFrameHostInterfaces(
-            InterfaceRegistry registry, RenderFrameHost renderFrameHost) {}
-
-    /**
-     * @param registry The Chrome interface registry for the WebContents.
-     * @param webContents The WebContents the Interface Registry is for.
-     */
-    public void registerChromeWebContentsInterfaces(
-            InterfaceRegistry registry, WebContents webContents) {}
-
-    /**
      * @param contentView The root content view for the containing activity.
      * @return A new {@link ImmersiveModeManager} or null if there isn't one.
      */
     public @Nullable ImmersiveModeManager createImmersiveModeManager(View contentView) {
         return null;
     }
-
-    /**
-     * Starts the observer for listening to system settings changes. Must be called on
-     * ChromeActivity initialization.
-     */
-    public void startSystemSettingsObserver() {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 6d21b21a..0293b86 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -23,7 +23,6 @@
 import android.os.SystemClock;
 import android.util.Pair;
 import android.util.TypedValue;
-import android.view.KeyEvent;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
@@ -144,7 +143,6 @@
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.toolbar.top.Toolbar;
 import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
-import org.chromium.chrome.browser.touchless.TouchlessUiCoordinator;
 import org.chromium.chrome.browser.translate.TranslateBridge;
 import org.chromium.chrome.browser.ui.RootUiCoordinator;
 import org.chromium.chrome.browser.ui.system.StatusBarColorController;
@@ -210,16 +208,13 @@
     /**
      * The different types of activities extending ChromeActivity.
      */
-    @IntDef({ActivityType.BASE, ActivityType.TABBED, ActivityType.CUSTOM_TAB, ActivityType.WEBAPP,
-            ActivityType.NO_TOUCH, ActivityType.DINO})
+    @IntDef({ActivityType.BASE, ActivityType.TABBED, ActivityType.CUSTOM_TAB, ActivityType.WEBAPP})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActivityType {
         int BASE = 0;
         int TABBED = 1;
         int CUSTOM_TAB = 2;
         int WEBAPP = 3;
-        int NO_TOUCH = 4;
-        int DINO = 5;
     }
 
     /**
@@ -338,11 +333,6 @@
      */
     private RootUiCoordinator mRootUiCoordinator;
 
-    /**
-     * Coordinates Touchless UI across ChromeActivity-derived classes.
-     */
-    private TouchlessUiCoordinator mTouchlessUiCoordinator;
-
     // TODO(972867): Pull MenuOrKeyboardActionController out of ChromeActivity.
     private List<MenuOrKeyboardActionController.MenuOrKeyboardActionHandler> mMenuActionHandlers =
             new ArrayList<>();
@@ -362,9 +352,6 @@
 
         mRootUiCoordinator = createRootUiCoordinator();
 
-        // See comments on #getTouchlessUiCoordinator for why we're doing this here.
-        getTouchlessUiCoordinator();
-
         VrModuleProvider.getDelegate().doPreInflationStartup(this, getSavedInstanceState());
 
         // Force a partner customizations refresh if it has yet to be initialized.  This can happen
@@ -1352,9 +1339,6 @@
      */
     @Override
     public SnackbarManager getSnackbarManager() {
-        if (getTouchlessUiCoordinator() != null) {
-            return getTouchlessUiCoordinator().getSnackbarManager();
-        }
         boolean useBottomSheetContainer = mBottomSheetController != null
                 && mBottomSheetController.getBottomSheet().isSheetOpen()
                 && !mBottomSheetController.getBottomSheet().isHiding();
@@ -1364,9 +1348,6 @@
 
     @Override
     protected ModalDialogManager createModalDialogManager() {
-        if (getTouchlessUiCoordinator() != null) {
-            return getTouchlessUiCoordinator().createModalDialogManager();
-        }
         return new ModalDialogManager(
                 new AppModalPresenter(this), ModalDialogManager.ModalDialogType.APP);
     }
@@ -1436,8 +1417,6 @@
         if (mDirectActionInitializer != null) {
             registerDirectActions();
         }
-
-        AppHooks.get().startSystemSettingsObserver();
     }
 
     /**
@@ -2500,8 +2479,6 @@
      * @return Whether this Activity supports the App Menu.
      */
     public boolean supportsAppMenu() {
-        if (FeatureUtilities.isNoTouchModeEnabled()) return false;
-
         // Derived classes that disable the toolbar should also have the Menu disabled without
         // having to explicitly disable the Menu as well.
         return getToolbarLayoutId() != NO_TOOLBAR_LAYOUT;
@@ -2515,31 +2492,6 @@
     }
 
     /**
-     * TODO(mthiesse): Figure out a way to clean this up. The problem is that the
-     * TouchlessUiCoordinator has an implementation of the ModalDialogManager, which is created in
-     * AsyncInitializationActivity#onCreateInternal, before any ChromeActivity init functions are
-     * called, and making AsyncInitializationActivity aware of the TouchlessUiCoordinator would be
-     * wrong. Hence, we create the UiCoordinator as soon as somebody tries to use it, but we also
-     * need to make sure it gets initialized early on regardless of whether somebody tries to use it
-     * as it monitors Lifecycles, etc.
-     */
-    public TouchlessUiCoordinator getTouchlessUiCoordinator() {
-        if (mTouchlessUiCoordinator == null && FeatureUtilities.isNoTouchModeEnabled()) {
-            mTouchlessUiCoordinator = AppHooks.get().createTouchlessUiCoordinator(this);
-        }
-        return mTouchlessUiCoordinator;
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        KeyEvent toPropagate = getTouchlessUiCoordinator() != null
-                ? getTouchlessUiCoordinator().processKeyEvent(event)
-                : event;
-
-        return toPropagate == null || super.dispatchKeyEvent(toPropagate);
-    }
-
-    /**
      * @return A lazily created {@link BottomSheetController}. The first time this method is called,
      *         a new controller is created.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
index b30ab66..5de260b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -18,7 +18,6 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.BuildConfig;
 import org.chromium.base.BuildInfo;
-import org.chromium.base.CommandLine;
 import org.chromium.base.CommandLineInitUtil;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.JNIUtils;
@@ -97,7 +96,6 @@
             // (see ChildProcessService.java).
             CommandLineInitUtil.initCommandLine(
                     COMMAND_LINE_FILE, ChromeApplication::shouldUseDebugFlags);
-            AppHooks.get().initCommandLine(CommandLine.getInstance());
 
             // Requires command-line flags.
             TraceEvent.maybeEnableEarlyTracing();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 2015811..4e6b39d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -144,7 +144,6 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarButtonInProductHelpController;
 import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
 import org.chromium.chrome.browser.ui.RootUiCoordinator;
 import org.chromium.chrome.browser.usage_stats.UsageStatsService;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
@@ -498,9 +497,7 @@
                            ChromeTabbedActivity.MAIN_LAUNCHER_ACTIVITY_NAME)) {
             // Keep in sync with the activities that the .Main alias points to in
             // AndroidManifest.xml.
-            if (FeatureUtilities.isNoTouchModeEnabled()) {
-                intent.setClass(appContext, TouchlessDelegate.getNoTouchActivityClass());
-            } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                 intent.setClass(appContext, ChromeLauncherActivity.class);
             } else {
                 intent.setClass(appContext, ChromeTabbedActivity.class);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index a2c54c03..134c5d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -472,7 +472,6 @@
 
         if (isIntentForMhtmlFileOrContent(intent) && tabOpenType == TabOpenType.OPEN_NEW_TAB
                 && referrerUrl == null && extraHeaders == null) {
-            // TODO(https://crbug.com/963233): should MHTML intent be handled on touchless someday?
             if (!OfflinePageUtils.isEnabled()) {
                 return false;
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
index 0dfed7ae..054490a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/KeyboardShortcuts.java
@@ -11,6 +11,7 @@
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
 
+import org.chromium.base.annotations.VerifiesOnN;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel;
@@ -103,13 +104,16 @@
      * appropriate group in this method so the user can see it when this method
      * is called.
      *
+     * Preventing inlining since this uses APIs only available on Android N, and this causes dex
+     * validation failures on earlier versions if inlined.
+     *
      * @param context We need an activity so we can call the strings from our
      *            resource.
      * @return a list of shortcuts organized into groups.
      */
     @TargetApi(Build.VERSION_CODES.N)
+    @VerifiesOnN
     public static List<KeyboardShortcutGroup> createShortcutGroup(Context context) {
-
         final int ctrlShift = KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON;
 
         List<KeyboardShortcutGroup> shortcutGroups = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index aaa06d2..9acd56b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -37,14 +37,12 @@
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.searchwidget.SearchActivity;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.webapps.ActivityAssigner;
 import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
 import org.chromium.ui.widget.Toast;
-import org.chromium.webapk.lib.client.WebApkValidator;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -68,9 +66,6 @@
 
     private static final String TAG = "ActivitiyDispatcher";
 
-    private static final String NO_TOUCH_ACTIVITY_NAME =
-            "org.chromium.chrome.browser.touchless.NoTouchActivity";
-
     /**
      * Timeout in ms for reading PartnerBrowserCustomizations provider. We do not trust third party
      * provider by default.
@@ -194,19 +189,6 @@
             return Action.FINISH_ACTIVITY;
         }
 
-        // Check if we should launch a WebApk to handle the intent.
-        // For NoTouchMode, prefer to launch PWAs instead of the browser on view intents.
-        if (!mIsCustomTabIntent && FeatureUtilities.isNoTouchModeEnabled() && url != null
-                && Intent.ACTION_VIEW.equals(mIntent.getAction())) {
-            String packageName = WebApkValidator.queryFirstWebApkPackage(
-                    ContextUtils.getApplicationContext(), url);
-            if (packageName != null) {
-                mActivity.startActivity(WebApkValidator.createWebApkIntentForUrlAndOptionalPackage(
-                        url, packageName));
-                return Action.FINISH_ACTIVITY;
-            }
-        }
-
         // Check if we should push the user through First Run.
         if (FirstRunFlowSequencer.launch(mActivity, mIntent, false /* requiresBroadcast */,
                     false /* preferLightweightFre */)) {
@@ -269,11 +251,6 @@
      */
     public static boolean isCustomTabIntent(Intent intent) {
         if (intent == null) return false;
-        // CCT is disabled in noTouch mode except for some Chrome-internal exceptions.
-        if (FeatureUtilities.isNoTouchModeEnabled()
-                && !IntentHandler.wasIntentSenderChrome(intent)) {
-            return false;
-        }
         if (CustomTabsIntent.shouldAlwaysUseBrowserUI(intent)
                 || !intent.hasExtra(CustomTabsIntent.EXTRA_SESSION)) {
             return false;
@@ -438,18 +415,9 @@
         maybePrefetchDnsInBackground();
 
         Intent newIntent = new Intent(mIntent);
-        String targetActivityClassName = null;
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // When in No Touch Mode we don't support tabs, and replace the TabbedActivity with the
-            // NoTouchActivity.
-            // We can't depend on NoTouchActivity directly as it's not always compiled in, so
-            // refer to it by string.
-            targetActivityClassName = NO_TOUCH_ACTIVITY_NAME;
-        } else {
-            targetActivityClassName = MultiWindowUtils.getInstance()
-                                              .getTabbedActivityForIntent(newIntent, mActivity)
-                                              .getName();
-        }
+        String targetActivityClassName = MultiWindowUtils.getInstance()
+                                                 .getTabbedActivityForIntent(newIntent, mActivity)
+                                                 .getName();
         newIntent.setClassName(
                 mActivity.getApplicationContext().getPackageName(), targetActivityClassName);
         newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 133ac879..6feb56c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -41,8 +41,6 @@
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabThemeColorHelper;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.webapps.WebappActivity;
 import org.chromium.chrome.browser.webapps.WebappAuthenticator;
 import org.chromium.chrome.browser.webapps.WebappDataStorage;
@@ -50,7 +48,6 @@
 import org.chromium.chrome.browser.webapps.WebappRegistry;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.content_public.common.ScreenOrientationConstants;
-import org.chromium.content_public.common.ScreenOrientationValues;
 import org.chromium.ui.widget.Toast;
 import org.chromium.webapk.lib.client.WebApkValidator;
 
@@ -200,16 +197,14 @@
             final String userTitle, final String name, final String shortName, final String iconUrl,
             final Bitmap icon, boolean isIconAdaptive, @WebDisplayMode final int displayMode,
             final int orientation, final int source, final long themeColor,
-            final long backgroundColor, final long callbackPointer,
-            final boolean isShortcutAsWebapp) {
+            final long backgroundColor, final long callbackPointer) {
         new AsyncTask<Intent>() {
             @Override
             protected Intent doInBackground() {
                 // Encoding {@link icon} as a string and computing the mac are expensive.
 
                 // Shortcuts as Webapps on O+ launch into a non-exported component for verification.
-                boolean usesMacForVerification =
-                        !isShortcutAsWebapp || Build.VERSION.SDK_INT < Build.VERSION_CODES.O;
+                boolean usesMacForVerification = Build.VERSION.SDK_INT < Build.VERSION_CODES.O;
 
                 // Encode the icon as a base64 string (Launcher drops Bitmaps in the Intent).
                 String encodedIcon = encodeBitmapAsString(icon);
@@ -255,17 +250,6 @@
     @CalledByNative
     public static void addShortcut(@Nullable Tab tab, String id, String url, String userTitle,
             Bitmap icon, boolean isIconAdaptive, int source, String iconUrl) {
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // There are no tabs in NoTouchMode, so we want to give shortcuts a more app-like
-            // experience.
-            long themeColor = (tab == null) ? MANIFEST_COLOR_INVALID_OR_MISSING
-                                            : TabThemeColorHelper.getColor(tab);
-            addWebapp(id, url, getScopeFromUrl(url), userTitle, userTitle, userTitle, iconUrl, icon,
-                    isIconAdaptive, WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT,
-                    source, themeColor, MANIFEST_COLOR_INVALID_OR_MISSING, 0 /* callbackPointer */,
-                    true /* isShortcutAsWebapp */);
-            return;
-        }
         Intent shortcutIntent = createShortcutIntent(url);
         shortcutIntent.putExtra(EXTRA_ID, id);
         shortcutIntent.putExtra(EXTRA_SOURCE, source);
@@ -309,12 +293,7 @@
      */
     private static void showAddedToHomescreenToast(final String title) {
         Context applicationContext = ContextUtils.getApplicationContext();
-        String toastText;
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            toastText = applicationContext.getString(R.string.added_to_apps, title);
-        } else {
-            toastText = applicationContext.getString(R.string.added_to_homescreen, title);
-        }
+        String toastText = applicationContext.getString(R.string.added_to_homescreen, title);
         showToast(toastText);
     }
 
@@ -740,7 +719,7 @@
     }
 
     private static boolean shouldShowToastWhenAddingShortcut() {
-        return !isRequestPinShortcutSupported() || FeatureUtilities.isNoTouchModeEnabled();
+        return !isRequestPinShortcutSupported();
     }
 
     private static boolean isRequestPinShortcutSupported() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/FontSizePrefs.java b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/FontSizePrefs.java
index 1398b02..6edfbc23 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/accessibility/FontSizePrefs.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/accessibility/FontSizePrefs.java
@@ -46,7 +46,6 @@
     private final ObserverList<FontSizePrefsObserver> mObserverList;
 
     private Float mSystemFontScaleForTests;
-    private boolean mTouchlessMode;
 
     /**
      * Interface for observing changes in font size-related preferences.
@@ -154,16 +153,6 @@
     }
 
     /**
-     * Enables touchless mode. This overrides user's preference and always enables force enable
-     * zoom.
-     */
-    public void enableTouchlessMode() {
-        mTouchlessMode = true;
-        FontSizePrefsJni.get().setForceEnableZoom(
-                mFontSizePrefsAndroidPtr, FontSizePrefs.this, true);
-    }
-
-    /**
      * Returns whether forceEnableZoom is enabled.
      */
     public boolean getForceEnableZoom() {
@@ -185,9 +174,6 @@
     }
 
     private void setForceEnableZoom(boolean enabled, boolean fromUser) {
-        // Force enable zoom is always enabled in touchless mode and it should not be changed.
-        if (mTouchlessMode) return;
-
         SharedPreferences.Editor sharedPreferencesEditor =
                 ContextUtils.getAppSharedPreferences().edit();
         sharedPreferencesEditor.putBoolean(PREF_USER_SET_FORCE_ENABLE_ZOOM, fromUser);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
index dce8467d..cbf25f30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ResourceId;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.components.autofill.AutofillDelegate;
 import org.chromium.components.autofill.AutofillPopup;
 import org.chromium.components.autofill.AutofillSuggestion;
@@ -42,8 +41,7 @@
             WindowAndroid windowAndroid) {
         mNativeAutofillPopup = nativeAutofillPopupViewAndroid;
         Activity activity = windowAndroid.getActivity().get();
-        if (activity == null || notEnoughScreenSpace(activity)
-                || FeatureUtilities.isNoTouchModeEnabled()) {
+        if (activity == null || notEnoughScreenSpace(activity)) {
             mAutofillPopup = null;
             mContext = null;
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
index 02e3ccc..481391a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -230,9 +230,10 @@
         // But with SurfaceControl, switching to a new SurfaceView evicts that content when
         // destroying the GLSurface in the GPU process. So we need to explicitly preserve them in
         // the GPU process during this transition.
-        if (switchToSurfaceView)
+        if (switchToSurfaceView) {
             CompositorViewJni.get().cacheBackBufferForCurrentSurface(
                     mNativeCompositorView, CompositorView.this);
+        }
 
         // Trigger the creation of a new SurfaceView. CompositorSurfaceManager will handle caching
         // the old one during the transition.
@@ -258,9 +259,12 @@
      */
     public void shutDown() {
         mCompositorSurfaceManager.shutDown();
-        if (mScreenStateReceiver != null) mScreenStateReceiver.shutDown();
-        if (mNativeCompositorView != 0)
+        if (mScreenStateReceiver != null) {
+            mScreenStateReceiver.shutDown();
+        }
+        if (mNativeCompositorView != 0) {
             CompositorViewJni.get().destroy(mNativeCompositorView, CompositorView.this);
+        }
         mNativeCompositorView = 0;
     }
 
@@ -341,6 +345,10 @@
     }
 
     private int getSurfacePixelFormat() {
+        if (mOverlayVideoEnabled || mAlwaysTranslucent) {
+            return PixelFormat.TRANSLUCENT;
+        }
+
         if (mIsSurfaceControlEnabled) {
             // In SurfaceControl mode, we can always use a translucent format since there is no
             // buffer associated to the SurfaceView, and the buffers passed to the SurfaceControl
@@ -352,8 +360,7 @@
             return canUseSurfaceControl() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
         }
 
-        return (mOverlayVideoEnabled || mAlwaysTranslucent) ? PixelFormat.TRANSLUCENT
-                                                            : PixelFormat.OPAQUE;
+        return PixelFormat.OPAQUE;
     }
 
     private boolean canUseSurfaceControl() {
@@ -362,10 +369,13 @@
 
     @Override
     public void surfaceRedrawNeededAsync(Runnable drawingFinished) {
-        if (mDrawingFinishedCallbacks == null) mDrawingFinishedCallbacks = new ArrayList<>();
+        if (mDrawingFinishedCallbacks == null) {
+            mDrawingFinishedCallbacks = new ArrayList<>();
+        }
         mDrawingFinishedCallbacks.add(drawingFinished);
-        if (mNativeCompositorView != 0)
+        if (mNativeCompositorView != 0) {
             CompositorViewJni.get().setNeedsComposite(mNativeCompositorView, CompositorView.this);
+        }
     }
 
     @Override
@@ -433,8 +443,9 @@
      * Request compositor view to render a frame.
      */
     public void requestRender() {
-        if (mNativeCompositorView != 0)
+        if (mNativeCompositorView != 0) {
             CompositorViewJni.get().setNeedsComposite(mNativeCompositorView, CompositorView.this);
+        }
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index b6bd553..be0ff55 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -32,6 +32,7 @@
 
 import org.chromium.base.SysUtils;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.compat.ApiHelperForN;
 import org.chromium.base.compat.ApiHelperForO;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.InsetObserverView;
@@ -203,7 +204,7 @@
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return null;
         View activeView = getContentView();
         if (activeView == null || !ViewCompat.isAttachedToWindow(activeView)) return null;
-        return activeView.onResolvePointerIcon(event, pointerIndex);
+        return ApiHelperForN.onResolvePointerIcon(activeView, event, pointerIndex);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
index 6fc5d24..49d2912 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.util.ColorUtils;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -112,9 +111,7 @@
         ToolbarManager manager = mToolbarManager.get();
         assert manager != null : "Toolbar manager not initialized";
 
-        manager.setCloseButtonDrawable(FeatureUtilities.isNoTouchModeEnabled()
-                ? null
-                : mIntentDataProvider.getCloseButtonDrawable());
+        manager.setCloseButtonDrawable(mIntentDataProvider.getCloseButtonDrawable());
         manager.setShowTitle(
                 mIntentDataProvider.getTitleVisibilityState() == CustomTabsIntent.SHOW_PAGE_TITLE);
         if (mConnection.shouldHideDomainForSession(mIntentDataProvider.getSession())) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ItemChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ItemChooserDialog.java
index a750cc7..88c1bab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ItemChooserDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/ItemChooserDialog.java
@@ -16,7 +16,6 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
-import android.widget.AdapterView;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.ListView;
@@ -28,7 +27,6 @@
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.widget.TextViewWithClickableSpans;
@@ -188,21 +186,8 @@
         mItemAdapter.setNotifyOnChange(true);
         mItemAdapter.setObserver(this);
 
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // TODO(crbug.com/982869): ideally we would port to using the modal dialog
-            // manager. Until then, we will treat clicking on the items as selecting them.
-            mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-                @Override
-                public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
-                    mItemAdapter.onItemClick(adapter, view, position, id);
-                    clickListener.onClick(null);
-                }
-            });
-            mConfirmButton.setVisibility(View.GONE);
-        } else {
-            mConfirmButton.setOnClickListener(clickListener);
-            mListView.setOnItemClickListener(mItemAdapter);
-        }
+        mConfirmButton.setOnClickListener(clickListener);
+        mListView.setOnItemClickListener(mItemAdapter);
 
         mListView.setAdapter(mItemAdapter);
         mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java
index 6dbe426..00b3965 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java
@@ -10,13 +10,13 @@
 import androidx.annotation.NonNull;
 
 import org.chromium.base.Callback;
+import org.chromium.base.Supplier;
 import org.chromium.base.metrics.CachedMetrics;
 
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
-import java.util.function.Supplier;
 
 /**
  * Reports available direct actions and executes them.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index 13b21ca..8d0563ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -1192,8 +1192,6 @@
      * @return Whether the file would be openable by the browser.
      */
     public static boolean isSupportedMimeType(String mimeType) {
-        // In NoTouch mode we don't support opening downloaded files in-browser.
-        if (FeatureUtilities.isNoTouchModeEnabled()) return false;
         return DownloadManagerServiceJni.get().isSupportedMimeType(mimeType);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
index 48cf0dba..16d74f4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
@@ -42,7 +42,6 @@
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.components.offline_items_collection.ContentId;
 import org.chromium.components.offline_items_collection.LegacyHelpers;
@@ -169,8 +168,9 @@
                                         context, cancelIntent, downloadUpdate.getNotificationId()),
                                 cancelActionType);
 
-                if (!downloadUpdate.getIsOffTheRecord())
+                if (!downloadUpdate.getIsOffTheRecord()) {
                     builder.setLargeIcon(downloadUpdate.getIcon());
+                }
 
                 if (!downloadUpdate.getIsDownloadPending()) {
                     boolean indeterminate = downloadUpdate.getProgress().isIndeterminate();
@@ -222,12 +222,9 @@
                                         context, cancelIntent, downloadUpdate.getNotificationId()),
                                 cancelActionType);
 
-                // On touchless devices, the only access point for downloads is the notification, so
-                // keep the notification persistent if not in the completed or failure state.
-                if (FeatureUtilities.isNoTouchModeEnabled()) builder.setOngoing(true);
-
-                if (!downloadUpdate.getIsOffTheRecord())
+                if (!downloadUpdate.getIsOffTheRecord()) {
                     builder.setLargeIcon(downloadUpdate.getIcon());
+                }
 
                 if (downloadUpdate.getIsTransient()) {
                     builder.setDeleteIntent(buildPendingIntentProvider(
@@ -291,8 +288,9 @@
 
                 // It's the job of the service to ensure that the default icon is provided when
                 // in incognito mode.
-                if (downloadUpdate.getIcon() != null)
+                if (downloadUpdate.getIcon() != null) {
                     builder.setLargeIcon(downloadUpdate.getIcon());
+                }
 
                 break;
             case DownloadNotificationService.DownloadStatus.FAILED:
@@ -325,26 +323,11 @@
         if (!downloadUpdate.getIsTransient() && downloadUpdate.getNotificationId() != -1
                 && downloadStatus != DownloadNotificationService.DownloadStatus.COMPLETED
                 && downloadStatus != DownloadNotificationService.DownloadStatus.FAILED) {
-            if (FeatureUtilities.isNoTouchModeEnabled()) {
-                assert downloadUpdate.getContentId() != null;
-                ComponentName component = new ComponentName(
-                        context.getPackageName(), TouchlessDownloadActivity.class.getName());
-                Intent intent = new Intent(ACTION_NOTIFICATION_CLICKED);
-                intent.setComponent(component);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-                intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_ID, downloadUpdate.getContentId().id);
-                intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE,
-                        downloadUpdate.getContentId().namespace);
-                builder.setContentIntent(PendingIntentProvider.getActivity(context,
-                        downloadUpdate.getNotificationId(), intent,
-                        PendingIntent.FLAG_UPDATE_CURRENT));
-            } else {
-                Intent downloadHomeIntent = buildActionIntent(context, ACTION_NOTIFICATION_CLICKED,
-                        null, downloadUpdate.getIsOffTheRecord());
-                builder.setContentIntent(PendingIntentProvider.getService(context,
-                        downloadUpdate.getNotificationId(), downloadHomeIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT));
-            }
+            Intent downloadHomeIntent = buildActionIntent(
+                    context, ACTION_NOTIFICATION_CLICKED, null, downloadUpdate.getIsOffTheRecord());
+            builder.setContentIntent(
+                    PendingIntentProvider.getService(context, downloadUpdate.getNotificationId(),
+                            downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
         }
 
         if (downloadUpdate.getIsOffTheRecord()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index f229e7ae..026501d8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -60,7 +60,6 @@
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.util.ChromeIntentUtil;
 import org.chromium.chrome.browser.util.ConversionUtils;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.download.DownloadState;
@@ -172,7 +171,6 @@
     @CalledByNative
     public static boolean showDownloadManager(@Nullable Activity activity, @Nullable Tab tab,
             @DownloadOpenSource int source, boolean showPrefetchedContent) {
-        if (FeatureUtilities.isNoTouchModeEnabled()) return false;
         // Figure out what tab was last being viewed by the user.
         if (activity == null) activity = ApplicationStatus.getLastTrackedFocusedActivity();
         Context appContext = ContextUtils.getApplicationContext();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java
index 2040c2a..bc30b95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryCardView.java
@@ -178,7 +178,6 @@
                         createInteractionDelegate(model);
                 view.setOnClickListener(interactionDelegate);
                 view.setOnCreateContextMenuListener(interactionDelegate);
-                ContextMenuManager.registerViewForTouchlessContextMenu(view, interactionDelegate);
                 view.setOnFocusChangeListener(interactionDelegate);
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
index faad62b..4239d5b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
@@ -33,7 +33,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.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.content_public.browser.NavigationController;
@@ -290,11 +289,10 @@
         });
 
         // We don't want to scroll to the 4th category if personalized
-        // or integrated with Most Likely, or if we're on a touchless device.
+        // or integrated with Most Likely.
         int variation = ExploreSitesBridge.getVariation();
         mInitialScrollPosition = variation == ExploreSitesVariation.PERSONALIZED
                         || ExploreSitesBridge.isIntegratedWithMostLikely(variation)
-                        || FeatureUtilities.isNoTouchModeEnabled()
                 ? INITIAL_SCROLL_POSITION_PERSONALIZED
                 : INITIAL_SCROLL_POSITION;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index 628a954..ae42874 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -16,7 +16,6 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.locale.LocaleManager;
@@ -282,7 +281,7 @@
 
         Log.d(TAG, "Redirecting user through FRE.");
         if ((fromIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-            FreIntentCreator intentCreator = AppHooks.get().createFreIntentCreator();
+            FreIntentCreator intentCreator = new FreIntentCreator();
             Intent freIntent = intentCreator.create(
                     caller, fromIntent, requiresBroadcast, preferLightweightFre);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
index 1b7b1ff6..5f3a7e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -40,7 +40,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.toolbar.ControlContainer;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.vr.VrModeObserver;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.components.embedder_support.view.ContentView;
@@ -472,8 +471,7 @@
                 // The toast tells user how to leave fullscreen by touching the screen. Since,
                 // there is no touchscreen when browsing in VR, the toast doesn't have any useful
                 // information.
-                return !isOverlayVideoMode() && !isInVr() && !bootsToVr()
-                        && !FeatureUtilities.isNoTouchModeEnabled();
+                return !isOverlayVideoMode() && !isInVr() && !bootsToVr();
             }
         };
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
index b7f8ee3..774f9e53 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AdsBlockedInfoBar.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.infobar;
 
-import android.content.res.Resources;
 import android.support.v7.widget.SwitchCompat;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
@@ -13,18 +12,9 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ResourceId;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.DialogListItemProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.chrome.browser.util.FeatureUtilities;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.widget.ButtonCompat;
 
@@ -107,7 +97,7 @@
         // If we aren't already showing the explanation, clicking the link should expand to show the
         // explanation. If we *are* already showing the explanation, clicking the link (which should
         // change to Learn more) should take us to the help page.
-        if (!mIsShowingExplanation && !FeatureUtilities.isNoTouchModeEnabled()) {
+        if (!mIsShowingExplanation) {
             mIsShowingExplanation = true;
             replaceView(createView());
         }
@@ -125,51 +115,4 @@
         mButton.setText(isChecked ? mReloadButtonText : mOKButtonText);
         mReloadIsToggled = isChecked;
     }
-
-    @Override
-    public boolean supportsTouchlessMode() {
-        return true;
-    }
-
-    @Override
-    public PropertyModel createModel() {
-        PropertyModel model = super.createModel();
-        Resources res = getContext().getResources();
-
-        model.set(ModalDialogProperties.TITLE, res.getString(R.string.blocked_ads_prompt_title));
-        model.set(ModalDialogProperties.MESSAGE, res.getString(R.string.intrusive_ads_information));
-
-        ModelList listItems = new ModelList();
-        listItems.add(new ListItem(ListItemType.DEFAULT,
-                new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                        .with(DialogListItemProperties.TEXT, res.getString(R.string.learn_more))
-                        .with(DialogListItemProperties.CLICK_LISTENER, (v) -> onLinkClicked())
-                        .with(DialogListItemProperties.ICON,
-                                ApiCompatibilityUtils.getDrawable(
-                                        res, R.drawable.ic_info_outline_grey))
-                        .build()));
-        // TODO(973601): We should have a better string for "always allow"; at least one that is
-        //               specific to this feature.
-        listItems.add(new ListItem(ListItemType.DEFAULT,
-                new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                        .with(DialogListItemProperties.TEXT,
-                                res.getString(R.string.always_allow_redirects))
-                        .with(DialogListItemProperties.CLICK_LISTENER,
-                                (v) -> {
-                                    mReloadIsToggled = true;
-                                    onButtonClicked(true);
-                                })
-                        .with(DialogListItemProperties.ICON,
-                                ApiCompatibilityUtils.getDrawable(res, R.drawable.ic_check_circle))
-                        .build()));
-
-        model.set(TouchlessDialogProperties.LIST_MODELS, listItems);
-
-        // The alt action matches cancel but with a different name.
-        model.get(TouchlessDialogProperties.ACTION_NAMES).alt = R.string.ok;
-        model.set(TouchlessDialogProperties.ALT_ACTION,
-                model.get(TouchlessDialogProperties.CANCEL_ACTION));
-
-        return model;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java
index 24be08d..b58ecab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ConfirmInfoBar.java
@@ -5,20 +5,11 @@
 package org.chromium.chrome.browser.infobar;
 
 import android.graphics.Bitmap;
-import android.text.TextUtils;
 
 import androidx.annotation.ColorRes;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ResourceId;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.DialogListItemProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyModel;
 
 /**
  * An infobar that presents the user with several buttons.
@@ -69,49 +60,6 @@
         onButtonClicked(action);
     }
 
-    @Override
-    public boolean supportsTouchlessMode() {
-        // Only allow whitelisted implementations of the confirm infobar.
-        @InfoBarIdentifier
-        int infobarId = getInfoBarIdentifier();
-        return infobarId == InfoBarIdentifier.POPUP_BLOCKED_INFOBAR_DELEGATE_MOBILE
-                || infobarId == InfoBarIdentifier.DANGEROUS_DOWNLOAD_INFOBAR_DELEGATE_ANDROID;
-    }
-
-    @Override
-    public PropertyModel createModel() {
-        PropertyModel model = super.createModel();
-
-        ModelList options = new ModelList();
-        if (!TextUtils.isEmpty(mPrimaryButtonText)) {
-            options.add(new ListItem(ListItemType.DEFAULT,
-                    new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                            .with(DialogListItemProperties.TEXT, mPrimaryButtonText)
-                            .with(DialogListItemProperties.CLICK_LISTENER,
-                                    (v) -> onButtonClicked(true))
-                            .with(DialogListItemProperties.ICON,
-                                    ApiCompatibilityUtils.getDrawable(getContext().getResources(),
-                                            R.drawable.ic_check_circle))
-                            .build()));
-        }
-
-        if (!TextUtils.isEmpty(mSecondaryButtonText)) {
-            options.add(new ListItem(ListItemType.DEFAULT,
-                    new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                            .with(DialogListItemProperties.TEXT, mSecondaryButtonText)
-                            .with(DialogListItemProperties.CLICK_LISTENER,
-                                    (v) -> onButtonClicked(false))
-                            .with(DialogListItemProperties.ICON,
-                                    ApiCompatibilityUtils.getDrawable(getContext().getResources(),
-                                            R.drawable.ic_cancel_circle))
-                            .build()));
-        }
-
-        model.set(TouchlessDialogProperties.LIST_MODELS, options);
-
-        return model;
-    }
-
     /**
      * Creates and begins the process for showing a ConfirmInfoBar.
      * @param enumeratedIconId ID corresponding to the icon that will be shown for the infobar.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
index 25a2bda..15768ca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
@@ -25,8 +25,6 @@
 import org.chromium.chrome.browser.download.DownloadOpenSource;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.components.download.DownloadCollectionBridge;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
 
 import java.io.File;
 
@@ -175,23 +173,4 @@
             layout.setMessage(getDownloadMessageText(context, template));
         }
     }
-
-    @Override
-    public boolean supportsTouchlessMode() {
-        return true;
-    }
-
-    @Override
-    public PropertyModel createModel() {
-        PropertyModel model = super.createModel();
-
-        String template = getContext().getString(R.string.duplicate_download_request_infobar_text);
-
-        model.set(ModalDialogProperties.TITLE,
-                getContext().getResources().getString(R.string.menu_download));
-        model.set(ModalDialogProperties.MESSAGE,
-                getDownloadMessageText(getContext(), template).toString());
-
-        return model;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
index ceb946cf..83756ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
@@ -6,24 +6,16 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.widget.TextView;
 
-import androidx.annotation.CallSuper;
 import androidx.annotation.ColorRes;
 import androidx.annotation.Nullable;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ActionNames;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.Priority;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /**
@@ -124,49 +116,6 @@
     }
 
     /**
-     * Create a property model for view systems that use this rather than a custom view.
-     * @return A new property model.
-     */
-    @CallSuper
-    protected PropertyModel createModel() {
-        Drawable icon;
-        if (mIconBitmap != null) {
-            icon = new BitmapDrawable(mIconBitmap);
-        } else {
-            icon = ApiCompatibilityUtils.getDrawable(getContext().getResources(), mIconDrawableId);
-        }
-
-        ActionNames names = new ActionNames();
-        names.cancel = R.string.cancel;
-        names.select = R.string.select;
-        names.alt = 0;
-        PropertyModel model =
-                new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS)
-                        .with(TouchlessDialogProperties.IS_FULLSCREEN, false)
-                        .with(TouchlessDialogProperties.PRIORITY, Priority.HIGH)
-                        .with(TouchlessDialogProperties.ACTION_NAMES, names)
-                        .with(TouchlessDialogProperties.CANCEL_ACTION,
-                                view -> onCloseButtonClicked())
-                        .with(TouchlessDialogProperties.ALT_ACTION, null)
-                        .with(ModalDialogProperties.TITLE,
-                                mMessage != null ? mMessage.toString() : "")
-                        .with(ModalDialogProperties.TITLE_ICON, icon)
-                        .with(ModalDialogProperties.CONTROLLER,
-                                new ModalDialogProperties.Controller() {
-                                    @Override
-                                    public void onClick(PropertyModel model, int buttonType) {}
-
-                                    @Override
-                                    public void onDismiss(PropertyModel model, int dismissalCause) {
-                                        mContainer.removeInfoBar(InfoBar.this);
-                                    }
-                                })
-                        .build();
-        mModel = model;
-        return model;
-    }
-
-    /**
      * @return The model for this infobar if one was created.
      */
     @Nullable
@@ -175,13 +124,6 @@
     }
 
     /**
-     * @return Whether this InfoBar is supported in touchless mode.
-     */
-    protected boolean supportsTouchlessMode() {
-        return false;
-    }
-
-    /**
      * If this returns true, the infobar contents will be replaced with a one-line layout.
      * When overriding this, also override {@link #getAccessibilityMessage}.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
index bb3372f0..78c436f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
@@ -21,15 +21,12 @@
 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.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetObserver;
 import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.KeyboardVisibilityDelegate.KeyboardVisibilityListener;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
 
 import java.util.ArrayList;
 
@@ -296,15 +293,6 @@
         infoBar.setContext(mInfoBarContainerView.getContext());
         infoBar.setInfoBarContainer(this);
 
-        // TODO(957153): In touchless we will be needlessly logging show/close events. We should
-        //               clean this up to avoid skewing the metrics.
-        if (FeatureUtilities.isNoTouchModeEnabled() && !infoBar.supportsTouchlessMode()) {
-            // Pose the closing of the infobar as the native container does not handle closing the
-            // infobar during the show process well (native will crash).
-            mTab.getView().post(() -> infoBar.onCloseButtonClicked());
-            return;
-        }
-
         // We notify observers immediately (before the animation starts).
         for (InfoBarContainerObserver observer : mObservers) {
             observer.onAddInfoBar(this, infoBar, mInfoBars.isEmpty());
@@ -317,12 +305,7 @@
         // to be available when they get the notification.
         mInfoBars.add(infoBar);
 
-        if (FeatureUtilities.isNoTouchModeEnabled() && infoBar.supportsTouchlessMode()) {
-            mTab.getActivity().getModalDialogManager().showDialog(
-                    infoBar.createModel(), ModalDialogType.APP);
-        } else {
-            mInfoBarContainerView.addInfoBar(infoBar);
-        }
+        mInfoBarContainerView.addInfoBar(infoBar);
     }
 
     /**
@@ -367,29 +350,18 @@
         assert !mDestroyed;
 
         if (!mInfoBars.remove(infoBar)) {
-            // In touchless mode, an infobar can be removed without technically being added. This
-            // is allowed to support whitelisted infobars (while easily blocking the rest).
-            if (FeatureUtilities.isNoTouchModeEnabled()) return;
             assert false : "Trying to remove an InfoBar that is not in this container.";
             return;
         }
 
-        if (infoBar.supportsTouchlessMode() && FeatureUtilities.isNoTouchModeEnabled()
-                && infoBar.getModel() != null) {
-            mTab.getActivity().getModalDialogManager().dismissDialog(
-                    infoBar.getModel(), DialogDismissalCause.UNKNOWN);
-        }
-
         // Notify observers immediately, before any animations begin.
         for (InfoBarContainerObserver observer : mObservers) {
             observer.onRemoveInfoBar(this, infoBar, mInfoBars.isEmpty());
         }
 
-        if (!FeatureUtilities.isNoTouchModeEnabled()) {
-            assert mInfoBarContainerView
-                    != null : "The container view is null when removing an InfoBar.";
-            mInfoBarContainerView.removeInfoBar(infoBar);
-        }
+        assert mInfoBarContainerView
+                != null : "The container view is null when removing an InfoBar.";
+        mInfoBarContainerView.removeInfoBar(infoBar);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
index 6a0b6a5c..f14799e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -353,9 +353,7 @@
 
     @Override
     public void onCloseButtonClicked() {
-        // TODO(https://crbug.com/965058): If the infobar was not properly initialized (in touchless
-        //                                 mode for example), mTabLayout will be null.
-        if (mTabLayout != null) mTabLayout.endScrollingAnimationIfPlaying();
+        mTabLayout.endScrollingAnimationIfPlaying();
         closeInfobar(true);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/jsdialog/JavascriptModalDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/jsdialog/JavascriptModalDialog.java
index 9f9b67a..d3fe649 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/jsdialog/JavascriptModalDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/jsdialog/JavascriptModalDialog.java
@@ -12,8 +12,6 @@
 import org.chromium.base.Log;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
@@ -61,38 +59,17 @@
 
         Resources resources = activity.getResources();
 
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            TouchlessDialogProperties.ActionNames names =
-                    new TouchlessDialogProperties.ActionNames();
-            names.cancel = mNegativeButtonTextId;
-            names.select = 0;
-            names.alt = mPositiveButtonTextId;
-            mDialogModel = new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS)
-                                   .with(TouchlessDialogProperties.IS_FULLSCREEN, false)
-                                   .with(TouchlessDialogProperties.PRIORITY,
-                                           TouchlessDialogProperties.Priority.HIGH)
-                                   .with(TouchlessDialogProperties.ACTION_NAMES, names)
-                                   .with(ModalDialogProperties.MESSAGE, mMessage)
-                                   .with(ModalDialogProperties.TITLE, mTitle)
-                                   .with(ModalDialogProperties.CUSTOM_VIEW, mDialogCustomView)
-                                   .with(ModalDialogProperties.CONTROLLER, this)
-                                   .with(ModalDialogProperties.CONTENT_DESCRIPTION, mMessage)
-                                   .build();
-            mDialogModel.set(TouchlessDialogProperties.ALT_ACTION,
-                    (v) -> onDismiss(mDialogModel, DialogDismissalCause.POSITIVE_BUTTON_CLICKED));
-        } else {
-            mDialogModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
-                                   .with(ModalDialogProperties.CONTROLLER, this)
-                                   .with(ModalDialogProperties.TITLE, mTitle)
-                                   .with(ModalDialogProperties.MESSAGE, mMessage)
-                                   .with(ModalDialogProperties.CUSTOM_VIEW, mDialogCustomView)
-                                   .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources,
-                                           mPositiveButtonTextId)
-                                   .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
-                                           mNegativeButtonTextId)
-                                   .with(ModalDialogProperties.TITLE_SCROLLABLE, true)
-                                   .build();
-        }
+        mDialogModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
+                               .with(ModalDialogProperties.CONTROLLER, this)
+                               .with(ModalDialogProperties.TITLE, mTitle)
+                               .with(ModalDialogProperties.MESSAGE, mMessage)
+                               .with(ModalDialogProperties.CUSTOM_VIEW, mDialogCustomView)
+                               .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources,
+                                       mPositiveButtonTextId)
+                               .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
+                                       mNegativeButtonTextId)
+                               .with(ModalDialogProperties.TITLE_SCROLLABLE, true)
+                               .build();
 
         mModalDialogManager = activity.getModalDialogManager();
         mModalDialogManager.showDialog(mDialogModel, dialogType);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
index 3c322e9..ce38dd5c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.browser.media;
 
-import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.PictureInPictureParams;
 import android.content.pm.ActivityInfo;
@@ -19,6 +19,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.Log;
+import org.chromium.base.annotations.VerifiesOnO;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -41,8 +42,11 @@
 
 /**
  * A controller for entering Android O Picture in Picture mode with fullscreen videos.
+ *
+ * Do not inline to prevent class verification errors on pre-O runtimes.
  */
-@SuppressLint({"NewApi"})
+@VerifiesOnO
+@TargetApi(Build.VERSION_CODES.O)
 public class PictureInPictureController {
     private static final String TAG = "VideoPersist";
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
index 81ac3c5..d7a8d70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java
@@ -6,7 +6,6 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.blink.mojom.Authenticator;
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.installedapp.InstalledAppProviderFactory;
 import org.chromium.chrome.browser.payments.PaymentRequestFactory;
 import org.chromium.chrome.browser.webauth.AuthenticatorFactory;
@@ -35,7 +34,6 @@
         public void registerInterfaces(InterfaceRegistry registry, final WebContents webContents) {
             registry.addInterface(
                     ShareService.MANAGER, new ShareServiceImplementationFactory(webContents));
-            AppHooks.get().registerChromeWebContentsInterfaces(registry, webContents);
         }
     }
 
@@ -49,7 +47,6 @@
             registry.addInterface(
                     InstalledAppProvider.MANAGER, new InstalledAppProviderFactory(renderFrameHost));
             registry.addInterface(Authenticator.MANAGER, new AuthenticatorFactory(renderFrameHost));
-            AppHooks.get().registerChromeRenderFrameHostInterfaces(registry, renderFrameHost);
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
index 7a03f33..121535e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
@@ -190,15 +190,6 @@
     }
 
     /**
-     * Preserves delegate's reference in View's tag so it can later be retrieved from focused view.
-     */
-    public static void registerViewForTouchlessContextMenu(View view, Delegate delegate) {
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            view.setTag(R.id.context_menu_delegate, delegate);
-        }
-    }
-
-    /**
      * Given currently focused view this function retrieves associated Delegate.
      */
     public static Delegate getDelegateFromFocusedView(View view) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index e5c2fe4..1125d54 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -28,8 +28,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
@@ -54,10 +52,6 @@
                 return new IncognitoNewTabPage(activity, new TabShim(tab));
             }
 
-            if (FeatureUtilities.isNoTouchModeEnabled()) {
-                return TouchlessDelegate.createTouchlessNewTabPage(activity, new TabShim(tab));
-            }
-
             if (ChromeFeatureList.isEnabled(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS)) {
                 return new FeedNewTabPage(activity, new TabShim(tab), tabModelSelector,
                         activityTabProvider, activityLifecycleDispatcher);
@@ -76,10 +70,6 @@
         }
 
         protected NativePage buildExploreSitesPage(ChromeActivity activity, Tab tab) {
-            if (FeatureUtilities.isNoTouchModeEnabled()) {
-                return TouchlessDelegate.createTouchlessExploreSitesPage(
-                        activity, new TabShim(tab));
-            }
             return new ExploreSitesPage(activity, new TabShim(tab));
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java
index b6ef796..3b4e52c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java
@@ -14,12 +14,10 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.offlinepages.RequestCoordinatorBridge;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.SheetState;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.mojom.WindowOpenDisposition;
@@ -56,16 +54,6 @@
 
         switch (windowOpenDisposition) {
             case WindowOpenDisposition.CURRENT_TAB:
-                if (FeatureUtilities.isNoTouchModeEnabled()) {
-                    // Allow PWAs to handle navigation.
-                    InterceptNavigationDelegateImpl delegate =
-                            InterceptNavigationDelegateImpl.get(mHost.getActiveTab());
-                    if (delegate != null
-                            && delegate.shouldIgnoreNewTab(loadUrlParams.getUrl(),
-                                    mTabModelSelector.isIncognitoSelected())) {
-                        break;
-                    }
-                }
                 mHost.loadUrl(loadUrlParams, mTabModelSelector.isIncognitoSelected());
                 loadingTab = mHost.getActiveTab();
                 break;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
index ccea493..22d10e44 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/CardViewHolder.java
@@ -58,7 +58,6 @@
                 (menu, view, menuInfo)
                         -> contextMenuManager.createContextMenu(
                                 menu, itemView, CardViewHolder.this));
-        ContextMenuManager.registerViewForTouchlessContextMenu(itemView, this);
 
         mUiConfig = uiConfig;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index ead15ebf4..e24d6888 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -225,11 +225,8 @@
                 mUiDelegate.getSuggestionsSource().areRemoteSuggestionsEnabled();
         boolean isArticleSectionVisible = mSections.getSection(KnownCategories.ARTICLES) != null;
 
-        // Always hide footer when in touchless mode since the learn more link will be shown in the
-        // context menu.
         mFooter.setVisible(!SuggestionsConfig.scrollToLoad()
-                && (areRemoteSuggestionsEnabled || isArticleSectionVisible)
-                && !SuggestionsConfig.isTouchless());
+                && (areRemoteSuggestionsEnabled || isArticleSectionVisible));
     }
 
     private boolean areArticlesLoading() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index 67b6230..d782b4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.signin.SigninManager;
-import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
 import org.chromium.chrome.browser.suggestions.SuggestionsOfflineModelObserver;
 import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
@@ -104,16 +103,9 @@
         boolean isExpandable = getCategory() == KnownCategories.ARTICLES;
         boolean isExpanded =
                 PrefServiceBridge.getInstance().getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE);
-        // No header when touchless. The header allows users to choose to collapse/hide suggestions,
-        // but when touchless collapsing the suggestions shouldn't be necessary. There is no omnibox
-        // to distract from.
-        if (!SuggestionsConfig.isTouchless()) {
-            mHeader = isExpandable ? new SectionHeader(info.getTitle(), isExpanded,
-                              this::updateSuggestionsVisibilityForExpandableHeader)
-                                   : new SectionHeader(info.getTitle());
-        } else {
-            mHeader = null;
-        }
+        mHeader = isExpandable ? new SectionHeader(info.getTitle(), isExpanded,
+                          this::updateSuggestionsVisibilityForExpandableHeader)
+                               : new SectionHeader(info.getTitle());
 
         if (isExpandable && SignInPromo.shouldCreatePromo()) {
             mSigninPromo = new SignInPromo(signinManager);
@@ -515,8 +507,7 @@
     }
 
     /**
-     * Sets the visibility of this section's header. Note this will not work when header is not
-     * added to view hierarchy as a result of {@link SuggestionsConfig#isTouchless(boolean)}.
+     * Sets the visibility of this section's header.
      */
     public void setHeaderVisibility(boolean headerVisibility) {
         if (mHeader != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 60334b4..85d6f0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -937,7 +937,9 @@
         // side is initialized
         assert mNativeInitialized : "Loading URL before native side initialized";
 
-        if (ReturnToChromeExperimentsUtil.willHandleLoadUrlFromLocationBar(url, transition)) return;
+        if (ReturnToChromeExperimentsUtil.willHandleLoadUrlFromStartSurface(url, transition)) {
+            return;
+        }
 
         if (currentTab != null
                 && (currentTab.isNativePage() || NewTabPage.isNTPUrl(currentTab.getUrl()))) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index 2b7ac60..7310ec68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -1065,7 +1065,7 @@
         mAutocomplete = controller;
     }
 
-    private static abstract class DeferredOnSelectionRunnable implements Runnable {
+    private abstract static class DeferredOnSelectionRunnable implements Runnable {
         protected final OmniboxSuggestion mSuggestion;
         protected final int mPosition;
         protected boolean mShouldLog;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java
index 7448ecfd..c6607270 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java
@@ -42,7 +42,7 @@
     private static final String TAG = "ConnectionInfoPopup";
 
     private static final String HELP_URL =
-            "https://support.google.com/chrome/answer/95617";
+            "https://support.google.com/chrome?p=android_connection_info";
 
     private final Context mContext;
     private final ModalDialogManager mModalDialogManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java
index 957f21c4..be3393f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java
@@ -17,8 +17,6 @@
 import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.webapps.WebApkActivity;
 import org.chromium.ui.base.PermissionCallback;
 import org.chromium.ui.base.WindowAndroid;
@@ -212,24 +210,17 @@
                 }
             }
         };
-        PropertyModel dialogModel;
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            dialogModel = TouchlessDelegate.getMissingPermissionDialogModel(
-                    activity, controller, messageId);
-        } else {
-            View view =
-                    activity.getLayoutInflater().inflate(R.layout.update_permissions_dialog, null);
-            TextView dialogText = view.findViewById(R.id.text);
-            dialogText.setText(messageId);
-            dialogModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
-                                  .with(ModalDialogProperties.CUSTOM_VIEW, view)
-                                  .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
-                                  .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
-                                          activity.getString(
-                                                  R.string.infobar_update_permissions_button_text))
-                                  .with(ModalDialogProperties.CONTROLLER, controller)
-                                  .build();
-        }
+        View view = activity.getLayoutInflater().inflate(R.layout.update_permissions_dialog, null);
+        TextView dialogText = view.findViewById(R.id.text);
+        dialogText.setText(messageId);
+        PropertyModel dialogModel =
+                new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
+                        .with(ModalDialogProperties.CUSTOM_VIEW, view)
+                        .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
+                        .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
+                                activity.getString(R.string.infobar_update_permissions_button_text))
+                        .with(ModalDialogProperties.CONTROLLER, controller)
+                        .build();
         modalDialogManager.showDialog(dialogModel, ModalDialogManager.ModalDialogType.APP);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogModel.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogModel.java
index c6a7c35a..c9d7124 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/PermissionDialogModel.java
@@ -12,8 +12,6 @@
 import android.widget.TextView;
 
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -23,10 +21,6 @@
 class PermissionDialogModel {
     public static PropertyModel getModel(
             ModalDialogProperties.Controller controller, PermissionDialogDelegate delegate) {
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            return TouchlessDelegate.getPermissionDialogModel(controller, delegate);
-        }
-
         Context context = delegate.getTab().getActivity();
         LayoutInflater inflater = LayoutInflater.from(context);
         View customView = inflater.inflate(R.layout.permission_dialog, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
index 9f45d0f..73a8819 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -409,12 +409,6 @@
     public static final String IMMERSIVE_UI_MODE_ENABLED = "immersive_ui_mode_enabled";
 
     /**
-     * The total number of browsing sessions in touchless mode.
-     */
-    public static final String TOUCHLESS_BROWSING_SESSION_COUNT =
-            "touchless_browsing_session_count";
-
-    /**
      * Key to cache whether offline indicator v2 (persistent offline indicator) is enabled.
      */
     public static final String OFFLINE_INDICATOR_V2_ENABLED_KEY = "offline_indicator_v2_enabled";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java
index 6030a29..c7ded73 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java
@@ -28,8 +28,6 @@
 import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource;
 import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.components.sync.ModelType;
@@ -104,9 +102,7 @@
     public static Intent createIntentForSettingsPage(
             Context context, @Nullable String fragmentName, @Nullable Bundle fragmentArgs) {
         Intent intent = new Intent();
-        intent.setClass(context, FeatureUtilities.isNoTouchModeEnabled()
-                        ? TouchlessDelegate.getTouchlessPreferencesClass()
-                        : Preferences.class);
+        intent.setClass(context, Preferences.class);
         if (!(context instanceof Activity)) {
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -204,8 +200,9 @@
                 GOOGLE_ACCOUNT_PWM_UI, MIN_GOOGLE_PLAY_SERVICES_VERSION_PARAM,
                 DEFAULT_MIN_GOOGLE_PLAY_SERVICES_APK_VERSION);
         if (AppHooks.get().isGoogleApiAvailableWithMinApkVersion(minGooglePlayServicesVersion)
-                != ConnectionResult.SUCCESS)
+                != ConnectionResult.SUCCESS) {
             return false;
+        }
 
         if (!ChromeFeatureList.isEnabled(GOOGLE_ACCOUNT_PWM_UI)) return false;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEditingBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEditingBridge.java
index d6a0223..b64bf36b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEditingBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEditingBridge.java
@@ -23,6 +23,21 @@
         mNativePasswordEditingBridge = nativePasswordEditingBridge;
     }
 
+    /**
+     * The method edits a password form saved in the password store according to changes performed
+     * in PasswordEntryEditor. The delegate holds all the information about the password form that
+     * was loaded in the PasswordEntryEditor, so there's no need to pass the site, the old username
+     * or the old password to this method. Sometimes the form can have no username (for PSL-matched
+     * credentials), but it has to always have a password.
+     *
+     * @param newUsername that will replace the old one if it's given.
+     * @param newPassword that will replace the old one.
+     */
+    public void editSavedPasswordEntry(String newUsername, String newPassword) {
+        PasswordEditingBridgeJni.get().handleEditSavedPasswordEntry(
+                mNativePasswordEditingBridge, PasswordEditingBridge.this, newUsername, newPassword);
+    }
+
     @CalledByNative
     private static PasswordEditingBridge create(long nativePasswordEditingBridge) {
         return new PasswordEditingBridge(nativePasswordEditingBridge);
@@ -51,5 +66,7 @@
     @NativeMethods
     interface Natives {
         void destroy(long nativePasswordEditingBridge, PasswordEditingBridge caller);
+        void handleEditSavedPasswordEntry(long nativePasswordEditingBridge,
+                PasswordEditingBridge caller, String newUsername, String newPassword);
     }
 }
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 b030e5f..81b6b2b 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
@@ -55,7 +55,6 @@
 import org.chromium.chrome.browser.preferences.SearchUtils;
 import org.chromium.chrome.browser.preferences.website.Website.StoredDataClearedCallback;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.ui.widget.Toast;
 
@@ -368,9 +367,6 @@
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.clear();
-        // We don't need the options menu in touchless mode (crbug/962562).
-        if (FeatureUtilities.isNoTouchModeEnabled()) return;
-
         inflater.inflate(R.menu.website_preferences_menu, menu);
 
         mSearchItem = menu.findItem(R.id.search);
@@ -482,9 +478,7 @@
                 prefServiceBridge.setCategoryEnabled(
                         SiteSettingsCategory.contentSettingsType(type), (boolean) newValue);
 
-                // Third-party cookies toggle doesn't exist in touchless. Refer to crbug/951850.
-                if (type == SiteSettingsCategory.Type.COOKIES
-                        && !FeatureUtilities.isNoTouchModeEnabled()) {
+                if (type == SiteSettingsCategory.Type.COOKIES) {
                     updateThirdPartyCookiesCheckBox();
                 } else if (type == SiteSettingsCategory.Type.NOTIFICATIONS) {
                     updateNotificationsVibrateCheckBox();
@@ -884,9 +878,7 @@
         }
 
         // Configure/hide the third-party cookies toggle, as needed.
-        // We don't need this toggle in touchless. Refer to crbug/951850.
-        if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES)
-                && !FeatureUtilities.isNoTouchModeEnabled()) {
+        if (mCategory.showSites(SiteSettingsCategory.Type.COOKIES)) {
             thirdPartyCookies.setOnPreferenceChangeListener(this);
             updateThirdPartyCookiesCheckBox();
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
index 8804478..3324b0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
@@ -14,7 +14,6 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.preferences.website.SiteSettingsCategory.Type;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.content_public.common.ContentSwitches;
 
 import java.util.ArrayList;
@@ -87,10 +86,6 @@
             if (!SiteSettingsCategory.adsCategoryEnabled()) {
                 getPreferenceScreen().removePreference(findPreference(Type.ADS));
             }
-            // We don't have clipboard support in touchless mode (crbug/963515).
-            if (FeatureUtilities.isNoTouchModeEnabled()) {
-                getPreferenceScreen().removePreference(findPreference(Type.CLIPBOARD));
-            }
             CommandLine commandLine = CommandLine.getInstance();
             if (!commandLine.hasSwitch(ContentSwitches.ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES)) {
                 getPreferenceScreen().removePreference(findPreference(Type.BLUETOOTH_SCANNING));
@@ -117,9 +112,7 @@
                 websitePrefs.add(Type.BLUETOOTH_SCANNING);
             }
             websitePrefs.add(Type.CAMERA);
-            if (!FeatureUtilities.isNoTouchModeEnabled()) {
-                websitePrefs.add(Type.CLIPBOARD);
-            }
+            websitePrefs.add(Type.CLIPBOARD);
             websitePrefs.add(Type.COOKIES);
             websitePrefs.add(Type.JAVASCRIPT);
             websitePrefs.add(Type.DEVICE_LOCATION);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java
index 72ca07ef..75a972b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/printing/PrintShareActivity.java
@@ -9,7 +9,6 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.share.ShareActivity;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.printing.PrintingController;
 import org.chromium.printing.PrintingControllerImpl;
 
@@ -23,9 +22,6 @@
     }
 
     public static boolean featureIsAvailable(Tab currentTab) {
-        // TODO(https://crbug.com/981065): The Share Sheet printing item gets disabled while the
-        // share sheet is still active in NoTouch mode. Remove this restriction once fixed.
-        if (FeatureUtilities.isNoTouchModeEnabled()) return false;
         PrintingController printingController = PrintingControllerImpl.getInstance();
         return (printingController != null && !currentTab.isNativePage()
                 && !currentTab.isShowingInterstitialPage() && !printingController.isBusy()
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
index 3f3b1f27..eb6cc739 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
@@ -14,7 +14,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -56,14 +55,6 @@
     }
 
     /**
-     * @return Whether currently running in touchless mode/device. When in touchless, some features
-     *         or UI elements may want to change to better support this configuration.
-     */
-    public static boolean isTouchless() {
-        return FeatureUtilities.isNoTouchModeEnabled();
-    }
-
-    /**
      * @param resources The resources to fetch the color from.
      * @return The background color for the suggestions sheet content.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
index d314a6d..4969c57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
@@ -4,10 +4,8 @@
 
 package org.chromium.chrome.browser.tab;
 
-import android.os.Bundle;
 import android.view.ViewGroup;
 
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.content_public.browser.RenderWidgetHostView;
 import org.chromium.ui.base.ViewAndroidDelegate;
 
@@ -43,11 +41,6 @@
         TabBrowserControlsState.get(mTab).setBottomOffset(bottomControlsOffsetY);
     }
 
-    @Override
-    public void performPrivateImeCommand(String action, Bundle data) {
-        AppHooks.get().performPrivateImeCommand(mTab.getWebContents(), action, data);
-    }
-
     /**
      * Sets the Visual Viewport bottom inset.
      * @param viewportInsetBottomPx The bottom inset in pixels.  Use {@code 0} for no inset.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java
index ae693be..b22a3d98 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManager.java
@@ -13,6 +13,7 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.annotations.VerifiesOnN;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.ui.base.WindowAndroid;
@@ -205,9 +206,12 @@
     }
 
     private static class DefaultTabModelSelectorFactory implements TabModelSelectorFactory {
+        // Do not inline since this uses some APIs only available on Android N versions, which cause
+        // verification errors.
+        @VerifiesOnN
         @Override
-        public TabModelSelector buildSelector(Activity activity,
-                TabCreatorManager tabCreatorManager, int selectorIndex) {
+        public TabModelSelector buildSelector(
+                Activity activity, TabCreatorManager tabCreatorManager, int selectorIndex) {
             // Merge tabs if this TabModelSelector is for a ChromeTabbedActivity created in
             // fullscreen mode and there are no TabModelSelector's currently alive. This indicates
             // that it is a cold start or process restart in fullscreen mode.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
index 4f9a103e8d..9f19b4e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
@@ -88,9 +88,7 @@
      * @param transition The page transition type.
      * @return true if we have handled the navigation, false otherwise.
      */
-    // TODO(mattsimmons): This needs to be updated for MV tiles to record the correct metrics.
-    // TODO(mattsimmons): Rename/Refactor since it's not just location bar now.
-    public static boolean willHandleLoadUrlFromLocationBar(
+    public static boolean willHandleLoadUrlFromStartSurface(
             String url, @PageTransition int transition) {
         ChromeActivity chromeActivity = getActivityPresentingOverviewWithOmnibox();
         if (chromeActivity == null) return false;
@@ -102,11 +100,15 @@
         chromeActivity.getTabCreator(model.isIncognito())
                 .createNewTab(params, TabLaunchType.FROM_CHROME_UI, null);
 
-        RecordUserAction.record("MobileOmniboxUse.GridTabSwitcher");
+        if (transition == PageTransition.AUTO_BOOKMARK) {
+            RecordUserAction.record("Suggestions.Tile.Tapped.GridTabSwitcher");
+        } else {
+            RecordUserAction.record("MobileOmniboxUse.GridTabSwitcher");
 
-        // These are duplicated here but would have been recorded by LocationBarLayout#loadUrl.
-        RecordUserAction.record("MobileOmniboxUse");
-        LocaleManager.getInstance().recordLocaleBasedSearchMetrics(false, url, transition);
+            // These are duplicated here but would have been recorded by LocationBarLayout#loadUrl.
+            RecordUserAction.record("MobileOmniboxUse");
+            LocaleManager.getInstance().recordLocaleBasedSearchMetrics(false, url, transition);
+        }
 
         return true;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index c4490d4e..7918529 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.firstrun.FirstRunUtils;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.ui.base.DeviceFormFactor;
 
@@ -611,14 +610,6 @@
     }
 
     /**
-     * @return Whether no-touch-mode is enabled.
-     */
-    @CalledByNative
-    public static boolean isNoTouchModeEnabled() {
-        return TouchlessDelegate.TOUCHLESS_MODE_ENABLED;
-    }
-
-    /**
      * Cache whether or not bootstrap tasks should be prioritized so on next startup, the value
      * can be made available immediately.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index fce5da8..b65b3128 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -11,7 +11,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.metrics.WebApkSplashscreenMetrics;
 import org.chromium.chrome.browser.metrics.WebApkUma;
@@ -76,12 +75,6 @@
     }
 
     @Override
-    public void onResumeWithNative() {
-        super.onResumeWithNative();
-        AppHooks.get().setDisplayModeForActivity(getWebApkInfo().displayMode(), this);
-    }
-
-    @Override
     protected void recordIntentToCreationTime(long timeMs) {
         super.recordIntentToCreationTime(timeMs);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
index cde09fe..2972f27f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.ui.base.Clipboard;
 
@@ -46,13 +45,8 @@
     private static final String ACTION_FOCUS =
             "org.chromium.chrome.browser.webapps.NOTIFICATION_ACTION_FOCUS";
 
-    static boolean isEnabled() {
-        // This UI doesn't work with no-touch.
-        return !FeatureUtilities.isNoTouchModeEnabled();
-    }
-
     public static void maybeShowNotification(Tab tab, WebappInfo webappInfo) {
-        if (!isEnabled() || tab == null) return;
+        if (tab == null) return;
 
         // All features provided by the notification are also available in the minimal-ui toolbar.
         if (webappInfo.displayMode() == WebDisplayMode.MINIMAL_UI) {
@@ -118,7 +112,6 @@
     }
 
     public static void cancelNotification() {
-        if (!isEnabled()) return;
         NotificationManager nm =
                 (NotificationManager) ContextUtils.getApplicationContext().getSystemService(
                         Context.NOTIFICATION_SERVICE);
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 974672d4..0582903 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
@@ -31,7 +31,6 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SingleTabActivity;
@@ -159,8 +158,6 @@
     protected void onNewIntent(Intent intent) {
         if (intent == null) return;
 
-        if (AppHooks.get().interceptWebAppIntent(intent, this)) return;
-
         super.onNewIntent(intent);
 
         WebappInfo newWebappInfo = popWebappInfo(WebappIntentDataProvider.idFromIntent(intent));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
index d7660f1c8..583f60a0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
@@ -7,7 +7,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.snackbar.Snackbar;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
 /**
@@ -73,11 +72,6 @@
             return false;
         }
 
-        // This UI isn't great for no-touch and will be handled a different way.
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            return false;
-        }
-
         // This will be null for Webapps or bound WebAPKs.
         String packageName = activity.getWebApkPackageName();
         // Show for unbound WebAPKs.
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 65cdddc2..c336e4d 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2253,9 +2253,6 @@
       <message name="IDS_NOTIFICATION_WEBAPK_INSTALLED" desc="Indicates that a WebAPK has been successfully added to Home screen.">
         Added to Home screen
       </message>
-      <message name="IDS_ADDED_TO_APPS" desc="Text that confirms a site or app has been added to the apps screen.">
-        <ph name="APP_NAME">%1$s<ex>Zomato</ex></ph> added to my apps
-      </message>
 
       <!-- Page info popup -->
       <message name="IDS_PAGE_INFO_SITE_SETTINGS_BUTTON" desc="Text in the button that opens a website's Site Settings from the Page Info dialog.">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index ba37432..a68c758 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -11,7 +11,6 @@
     "//chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni")
 import("//chrome/android/features/tab_ui/tab_management_java_sources.gni")
 import("//chrome/android/feed/feed_java_sources.gni")
-import("//chrome/android/touchless/touchless_java_sources.gni")
 import("//components/feed/features.gni")
 import("//components/offline_pages/buildflags/features.gni")
 import("//device/vr/buildflags/buildflags.gni")
@@ -22,14 +21,6 @@
   chrome_java_sources += [ "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java" ]
 }
 
-if (notouch_build) {
-  chrome_java_sources += touchless_java_sources
-  chrome_test_java_sources += touchless_test_java_sources
-  chrome_junit_test_java_sources += touchless_junit_test_java_sources
-} else {
-  chrome_java_sources += touchess_fallback_java_sources
-}
-
 # Only used for testing, should not be shipped to end users.
 if (enable_offline_pages_harness) {
   chrome_java_sources += [ "java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java" ]
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
index edebc26..48d1e8e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
@@ -55,7 +55,7 @@
 
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private static final int WAIT_RESPONSE_MS = 2000;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
index d158104a..8fe58c4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ExampleUiCaptureTest.java
@@ -30,7 +30,7 @@
 public class ExampleUiCaptureTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     @Rule
     public ScreenShooter mScreenShooter = new ScreenShooter();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
index 57ed9bf..0be23d63 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/FeaturesAnnotationsTest.java
@@ -33,7 +33,7 @@
 public class FeaturesAnnotationsTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     /**
      * Tests that {@link EnableFeatures} and {@link DisableFeatures} can alter the flags registered
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
index 134c02e..b842f56 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
@@ -31,7 +31,7 @@
 public class HTTPSTabsOpenedFromExternalAppTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private EmbeddedTestServer mTestServer;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
index 0abcb909..3ef1536 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser;
 
-import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.LargeTest;
 
@@ -19,9 +18,7 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
-import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -38,7 +35,7 @@
 public class JavaScriptEvalChromeTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
@@ -68,26 +65,11 @@
             throws InterruptedException, TimeoutException {
         Tab tab1 = mActivityTestRule.getActivity().getActivityTab();
         Tab tab2;
-        if (mActivityTestRule.getActivity() instanceof ChromeTabbedActivity) {
-            ChromeTabUtils.newTabFromMenu(
-                    InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-            tab2 = mActivityTestRule.getActivity().getActivityTab();
-            mActivityTestRule.loadUrl(JSTEST_URL);
-            ChromeTabUtils.switchTabInCurrentTabModel(
-                    mActivityTestRule.getActivity(), tab1.getId());
-        } else {
-            // For now, only NoTouchMode should hit this path.
-            // In NoTouchMode, multiple tabs are only supported though CCT, so use a CCT instead of
-            // a second tab.
-            Assert.assertTrue(FeatureUtilities.isNoTouchModeEnabled());
-            Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                    InstrumentationRegistry.getTargetContext(), "about:blank");
-            // NoTouchMode only allows CCT for 1p use-cases.
-            IntentHandler.addTrustedIntentExtras(intent);
-            mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-            tab2 = mCustomTabActivityTestRule.getActivity().getActivityTab();
-            mCustomTabActivityTestRule.loadUrl(JSTEST_URL);
-        }
+        ChromeTabUtils.newTabFromMenu(
+                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
+        tab2 = mActivityTestRule.getActivity().getActivityTab();
+        mActivityTestRule.loadUrl(JSTEST_URL);
+        ChromeTabUtils.switchTabInCurrentTabModel(mActivityTestRule.getActivity(), tab1.getId());
 
         Assert.assertFalse("Tab didn't open", tab1 == tab2);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
index 841a1735..23e471a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
@@ -63,7 +62,7 @@
 public class TabsOpenedFromExternalAppTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     static final String HTTP_REFERRER = "http://chromium.org/";
 
@@ -219,7 +218,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> testRule.getActivity().onNewIntent(intent));
         // NoTouchMode changes external app launch behaviour depending on whether Chrome is
         // foregrounded - which it is for these tests.
-        if (createNewTab && !FeatureUtilities.isNoTouchModeEnabled()) {
+        if (createNewTab) {
             CriteriaHelper.pollUiThread(new Criteria("Failed to select different tab") {
                 @Override
                 public boolean isSatisfied() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
index f9c2ddc..5a1bc47 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityShareTargetTest.java
@@ -26,14 +26,12 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.JniMocker;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.webapps.WebApkPostShareTargetNavigator;
 import org.chromium.chrome.browser.webapps.WebApkPostShareTargetNavigatorJni;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -45,7 +43,6 @@
 
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
 public class TrustedWebActivityShareTargetTest {
     // We are not actually navigating to POST target, so ok not to use test pages here.
     private static final ShareTarget POST_SHARE_TARGET =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
index 6b252c6..1efcb884 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
@@ -20,6 +20,7 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -34,7 +35,7 @@
 public class CompositorVisibilityTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private CompositorView mCompositorView;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
index 2062db6..dc8d139 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
@@ -23,6 +23,7 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
@@ -41,7 +42,7 @@
 public class CloseTabDirectActionHandlerTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private TabModelSelector mSelector;
     private CloseTabDirectActionHandler mHandler;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTest.java
index 1e4c6bc..be3068e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTest.java
@@ -23,11 +23,9 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.webapps.WebappActivityTestRule;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -81,10 +79,6 @@
     public void testCoreDirectActionInCustomTabActivity() throws Exception {
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
                 InstrumentationRegistry.getTargetContext(), "about:blank");
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // NoTouchMode only allows CCT for 1p use-cases.
-            IntentHandler.addTrustedIntentExtras(intent);
-        }
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
 
         assertThat(setupActivityAndGetDirectAction(mCustomTabActivityTestRule),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java
index c3025a0..22d889b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/DirectActionsInActivityTest.java
@@ -27,6 +27,7 @@
 import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -43,7 +44,7 @@
 public class DirectActionsInActivityTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     @Rule
     public DirectActionTestRule mDirectActionRule = new DirectActionTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
index 7cf705aa..cd542d76 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -11,17 +11,14 @@
 import android.annotation.TargetApi;
 import android.os.Build;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.contrib.RecyclerViewActions;
 import android.support.test.filters.SmallTest;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
-import android.view.View;
 
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Assert;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Rule;
@@ -40,7 +37,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.night_mode.NightModeTestUtils;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
@@ -226,39 +222,6 @@
 
     @Test
     @SmallTest
-    @Feature({"ExploreSites", "RenderTest"})
-    @Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
-    @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
-    public void testFocusRetention_WithBack(boolean nightModeEnabled) throws Exception {
-        Assume.assumeTrue(FeatureUtilities.isNoTouchModeEnabled());
-
-        InstrumentationRegistry.getInstrumentation().setInTouchMode(false);
-
-        final int defaultScrollPosition = mEsp.initialScrollPositionForTests();
-        Assert.assertEquals(defaultScrollPosition, getFocusedCategoryPosition());
-        Assert.assertEquals(0, getFocusedTileIndex());
-
-        // Change the focus from default so that we can verify it stays the same after navigation.
-        focusDifferentCard();
-
-        int focusedCategory = getFocusedCategoryPosition();
-        int focusedTile = getFocusedTileIndex();
-        Assert.assertNotEquals(defaultScrollPosition, focusedCategory);
-        Assert.assertNotEquals(0, focusedTile);
-
-        mRenderTestRule.render(mRecyclerView, "recycler_layout_focus");
-
-        mActivityTestRule.loadUrl("about:blank");
-
-        navigateBackToESP();
-
-        mRenderTestRule.render(mRecyclerView, "recycler_layout_focus_back");
-        Assert.assertEquals(focusedCategory, getFocusedCategoryPosition());
-        Assert.assertEquals(focusedTile, getFocusedTileIndex());
-    }
-
-    @Test
-    @SmallTest
     @Feature({"ExploreSites"})
     @Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
     public void testRecordTimestamp() throws Exception {
@@ -274,19 +237,6 @@
         Assert.assertEquals(histogramCount + 1, newHistogramCount);
     }
 
-    private void focusDifferentCard() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            ExploreSitesCategoryCardView cardView = null;
-            for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
-                cardView = (ExploreSitesCategoryCardView) mRecyclerView.getChildAt(i);
-                if (!cardView.hasFocus()) {
-                    cardView.getTileViewAt(2).requestFocus();
-                    break;
-                }
-            }
-        });
-    }
-
     private void navigateBackToESP() {
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> mActivityTestRule.getActivity().onBackPressed());
@@ -295,17 +245,6 @@
         mRecyclerView = mEsp.getView().findViewById(R.id.explore_sites_category_recycler);
     }
 
-    private int getFocusedCategoryPosition() {
-        View focusedView = mRecyclerView.getFocusedChild();
-        return mRecyclerView.getLayoutManager().getPosition(focusedView);
-    }
-
-    private int getFocusedTileIndex() {
-        ExploreSitesCategoryCardView focusedView =
-                (ExploreSitesCategoryCardView) mRecyclerView.getFocusedChild();
-        return focusedView.getFocusedTileIndex(-1);
-    }
-
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     public static void waitForEspLoaded(final Tab tab) {
         CriteriaHelper.pollUiThread(new Criteria("ESP never fully loaded") {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
index d86fb65..5965667 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.omnibox.UrlBar;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabStateBrowserControlsVisibilityDelegate;
@@ -75,7 +76,7 @@
 public class FullscreenManagerTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private static final String LONG_HTML_WITH_AUTO_FOCUS_INPUT_TEST_PAGE =
             UrlUtils.encodeHtmlDataUri("<html>"
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java
index 970032b..d45eea0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java
@@ -4,12 +4,10 @@
 
 package org.chromium.chrome.browser.login;
 
-import android.content.Intent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -22,13 +20,10 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
-import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -48,7 +43,7 @@
 public class ChromeHttpAuthHandlerTest {
     @Rule
     public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
-            ChromeActivityTestRule.forMainActivity();
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
@@ -110,20 +105,8 @@
     @Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void authDialogSuppressedOnBackgroundTab() throws Exception {
         Tab firstTab = mActivityTestRule.getActivity().getActivityTab();
-        if (mActivityTestRule.getActivity() instanceof ChromeTabbedActivity) {
-            ChromeTabUtils.newTabFromMenu(
-                    InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-        } else {
-            // For now, only NoTouchMode should hit this path.
-            // In NoTouchMode, multiple tabs are only supported though CCT, so use a CCT instead of
-            // a second tab.
-            Assert.assertTrue(FeatureUtilities.isNoTouchModeEnabled());
-            Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                    InstrumentationRegistry.getTargetContext(), "about:blank");
-            // NoTouchMode only allows CCT for 1p use-cases.
-            IntentHandler.addTrustedIntentExtras(intent);
-            mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        }
+        ChromeTabUtils.newTabFromMenu(
+                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
         // If the first tab was closed due to OOM, then just exit the test.
         if (TestThreadUtils.runOnUiThreadBlocking(
                     () -> firstTab.isClosing() || SadTab.isShowing(firstTab))) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
index a8936fc..1a8fd25 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
@@ -23,7 +23,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.DeviceConditions;
@@ -36,7 +35,6 @@
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
@@ -58,7 +56,6 @@
 
 /** Unit tests for auto-fetch-on-net-error-page. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         "enable-features=AutoFetchOnNetErrorPage", "disable-features=NewNetErrorPageUI"})
 public class OfflinePageAutoFetchTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchConfigurationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchConfigurationTest.java
index 62d2c3d..c61b2ba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchConfigurationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchConfigurationTest.java
@@ -15,13 +15,11 @@
 
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.offlinepages.OfflineTestUtil;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ReducedModeNativeTestRule;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -29,7 +27,6 @@
 
 /** Integration tests for {@link PrefetchConfiguration}. */
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class PrefetchConfigurationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
index f4ec9645..0a254f1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
@@ -22,7 +22,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -40,7 +39,6 @@
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ReducedModeNativeTestRule;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.components.background_task_scheduler.TaskIds;
 import org.chromium.components.background_task_scheduler.TaskParameters;
 import org.chromium.components.download.NetworkStatusListenerAndroid;
@@ -71,7 +69,6 @@
  * are run both in full browser mode and in reduced mode.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
 @RetryOnFailure
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PrefetchFeedFlowTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
index f5ade34..5e78c68 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -32,7 +31,6 @@
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.components.background_task_scheduler.TaskIds;
 import org.chromium.components.background_task_scheduler.TaskParameters;
 import org.chromium.components.download.NetworkStatusListenerAndroid;
@@ -57,7 +55,6 @@
  * PrefetchFeedFlowTest.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
 @RetryOnFailure
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PrefetchFlowTest implements WebServer.RequestHandler {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
index a80b5c3..a3565e0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
@@ -14,13 +14,11 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.device.geolocation.LocationProviderOverrider;
 import org.chromium.device.geolocation.MockLocationProvider;
@@ -69,7 +67,6 @@
      */
     @Test
     @MediumTest
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @Feature({"Location", "Main"})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testGeolocationPlumbingAllowedInfoBar() throws Exception {
@@ -105,7 +102,6 @@
      */
     @Test
     @MediumTest
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @Feature({"Location"})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testGeolocationWatchInfoBar() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
index 1901dbf..12ea49e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
@@ -14,13 +14,11 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.content_public.common.ContentSwitches;
 
 /**
@@ -62,7 +60,6 @@
     @MediumTest
     @Feature({"MediaPermissions", "Main"})
     @CommandLineFlags.Add({FAKE_DEVICE})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testMicrophonePermissionsPlumbingInfoBar() throws Exception {
         testMediaPermissionsPlumbing("Mic count:", "initiate_getMicrophone()", 1, false, false);
@@ -88,7 +85,6 @@
     @MediumTest
     @Feature({"MediaPermissions", "Main"})
     @CommandLineFlags.Add({FAKE_DEVICE})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testCameraPermissionsPlumbingInfoBar() throws Exception {
         testMediaPermissionsPlumbing("Camera count:", "initiate_getCamera()", 1, false, false);
@@ -116,7 +112,6 @@
     @MediumTest
     @Feature({"MediaPermissions", "Main"})
     @CommandLineFlags.Add({FAKE_DEVICE})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testCombinedPermissionsPlumbing() throws Exception {
         testMediaPermissionsPlumbing("Combined count:", "initiate_getCombined()", 1, false, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
index 7236f3a..67520a6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
@@ -14,13 +14,11 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 
 /**
  * Test suite for quota permissions requests.
@@ -59,7 +57,6 @@
     @Test
     @MediumTest
     @Feature({"QuotaPermissions"})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testQuotaShowsInfobar() throws Exception {
         testQuotaPermissionsPlumbing("initiate_requestQuota(1024)", 1, false, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataTest.java
index 514c3d9..c738fe79 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataTest.java
@@ -15,7 +15,6 @@
 
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.browsing_data.BrowsingDataType;
@@ -23,7 +22,6 @@
 import org.chromium.chrome.browser.browsing_data.TimePeriod;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.content_public.browser.test.util.JavaScriptUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -163,7 +161,6 @@
      */
     @Test
     @SmallTest
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     public void testHistoryDeleted() throws Exception {
         Assert.assertEquals(0, getCookieCount());
         mActivityTestRule.loadUrlInNewTab(mUrl);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
index 1ab825d..9d16562ff 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
@@ -87,17 +86,13 @@
         Assert.assertEquals(
                 ContentSettingValues.ALLOW, getGeolocation(DSE_ORIGIN, null, incognito));
 
-        // Incognito is not available in touchless mode.
-        if (!FeatureUtilities.isNoTouchModeEnabled()) {
-            // Resetting in incognito should not have the same behavior.
-            incognito = true;
-            setGeolocation(DSE_ORIGIN, null, ContentSettingValues.BLOCK, incognito);
-            Assert.assertEquals(
-                    ContentSettingValues.BLOCK, getGeolocation(DSE_ORIGIN, null, incognito));
-            setGeolocation(DSE_ORIGIN, null, ContentSettingValues.DEFAULT, incognito);
-            Assert.assertEquals(
-                    ContentSettingValues.ASK, getGeolocation(DSE_ORIGIN, null, incognito));
-        }
+        // Resetting in incognito should not have the same behavior.
+        incognito = true;
+        setGeolocation(DSE_ORIGIN, null, ContentSettingValues.BLOCK, incognito);
+        Assert.assertEquals(
+                ContentSettingValues.BLOCK, getGeolocation(DSE_ORIGIN, null, incognito));
+        setGeolocation(DSE_ORIGIN, null, ContentSettingValues.DEFAULT, incognito);
+        Assert.assertEquals(ContentSettingValues.ASK, getGeolocation(DSE_ORIGIN, null, incognito));
 
         // Resetting a different top level origin should not have the same behavior
         incognito = false;
@@ -145,19 +140,16 @@
         Assert.assertEquals(
                 ContentSettingValues.ALLOW, getNotifications(DSE_ORIGIN, null, incognito));
 
-        // Incognito is not available in touchless mode.
-        if (!FeatureUtilities.isNoTouchModeEnabled()) {
-            // Resetting in incognito should not have the same behavior.
-            TestThreadUtils.runOnUiThreadBlocking(
-                    () -> WebsitePreferenceBridgeJni.get().resetNotificationsSettingsForTest());
-            incognito = true;
-            setNotifications(DSE_ORIGIN, null, ContentSettingValues.BLOCK, incognito);
-            Assert.assertEquals(
-                    ContentSettingValues.BLOCK, getNotifications(DSE_ORIGIN, null, incognito));
-            setNotifications(DSE_ORIGIN, null, ContentSettingValues.DEFAULT, incognito);
-            Assert.assertEquals(
-                    ContentSettingValues.ASK, getNotifications(DSE_ORIGIN, null, incognito));
-        }
+        // Resetting in incognito should not have the same behavior.
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> WebsitePreferenceBridgeJni.get().resetNotificationsSettingsForTest());
+        incognito = true;
+        setNotifications(DSE_ORIGIN, null, ContentSettingValues.BLOCK, incognito);
+        Assert.assertEquals(
+                ContentSettingValues.BLOCK, getNotifications(DSE_ORIGIN, null, incognito));
+        setNotifications(DSE_ORIGIN, null, ContentSettingValues.DEFAULT, incognito);
+        Assert.assertEquals(
+                ContentSettingValues.ASK, getNotifications(DSE_ORIGIN, null, incognito));
 
         // // Resetting a different top level origin should not have the same behavior
         TestThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
index 38388c3..1565b87 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.preferences.website;
 
-import android.app.Activity;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.v7.preference.Preference;
@@ -19,26 +18,21 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ContentSettingsType;
-import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
 import org.chromium.chrome.browser.preferences.LocationSettings;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.InfoBarTestAnimationListener;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -116,7 +110,6 @@
      */
     @Test
     @SmallTest
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @Feature({"Preferences"})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testSetAllowLocationEnabled() throws Exception {
@@ -138,7 +131,6 @@
      */
     @Test
     @SmallTest
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @Feature({"Preferences"})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testSetAllowLocationNotEnabled() throws Exception {
@@ -276,7 +268,6 @@
     @Test
     @SmallTest
     @Feature({"Preferences"})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     public void testThirdPartyCookieToggleGetsDisabled() throws Exception {
         Preferences preferenceActivity =
                 SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES);
@@ -411,16 +402,7 @@
         mActivityTestRule.loadUrl(mTestServer.getURL("/chrome/test/data/android/popup.html"));
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // Popups open in a CustomTabActivity in touchless mode.
-            for (Activity activity : ApplicationStatus.getRunningActivities()) {
-                Assert.assertFalse(
-                        "Popup was not blocked, an instance of CustomTabActivity is running",
-                        activity instanceof CustomTabActivity);
-            }
-        } else {
-            Assert.assertEquals(1, getTabCount());
-        }
+        Assert.assertEquals(1, getTabCount());
     }
 
     /**
@@ -437,15 +419,7 @@
         mActivityTestRule.loadUrl(mTestServer.getURL("/chrome/test/data/android/popup.html"));
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            // Popups open in a CustomTabActivity in touchless mode.
-            for (Activity activity : ApplicationStatus.getRunningActivities()) {
-                if (activity instanceof CustomTabActivity) return;
-            }
-            Assert.fail("Popup was blocked, no instance of CustomTabActivity is running");
-        } else {
-            Assert.assertEquals(2, getTabCount());
-        }
+        Assert.assertEquals(2, getTabCount());
     }
 
     /**
@@ -640,7 +614,6 @@
     @Test
     @SmallTest
     @Feature({"Preferences"})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @CommandLineFlags.Add({ContentSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testCameraNotBlocked() throws Exception {
@@ -667,7 +640,6 @@
     @Test
     @SmallTest
     @Feature({"Preferences"})
-    @Restriction({ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH})
     @CommandLineFlags.Add({ContentSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM})
     @DisabledTest(message = "Modals are now enabled and test needs to be reworked crbug.com/935900")
     public void testMicNotBlocked() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java
index 502c409b..1e4fefc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java
@@ -28,8 +28,6 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -207,9 +205,7 @@
         WebApkActivity webApkActivity = mActivityTestRule.startWebApkActivity(createWebApkInfo(
                 getTestServerUrl("manifest_test_page.html"), getTestServerUrl("/")));
 
-        Class<? extends ChromeActivity> mainClass = FeatureUtilities.isNoTouchModeEnabled()
-                ? TouchlessDelegate.getNoTouchActivityClass()
-                : ChromeTabbedActivity.class;
+        Class<? extends ChromeActivity> mainClass = ChromeTabbedActivity.class;
 
         // Move WebAPK to the background by launching Chrome.
         Intent intent = new Intent(InstrumentationRegistry.getTargetContext(), mainClass);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 4af5445a..7cd567d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -38,7 +38,6 @@
 import androidx.annotation.Nullable;
 
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -78,7 +77,6 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsEventReporter;
 import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.support.DisableHistogramsRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
 import org.chromium.chrome.test.util.browser.Features;
@@ -303,9 +301,6 @@
 
     @Before
     public void setUp() {
-        // These tests fail on touchless builds, see https://crbug.com/981870.
-        Assume.assumeFalse(FeatureUtilities.isNoTouchModeEnabled());
-
         MockitoAnnotations.initMocks(this);
 
         // Ensure that NetworkChangeNotifier is initialized.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
index 349b9f0..4a7d16f8 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
@@ -29,7 +29,6 @@
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.registerCategory;
 
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -57,7 +56,6 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsEventReporter;
 import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.support.DisableHistogramsRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.CategoryInfoBuilder;
@@ -102,9 +100,6 @@
 
     @Before
     public void setUp() {
-        // These tests fail on touchless builds, see https://crbug.com/981870.
-        Assume.assumeFalse(FeatureUtilities.isNoTouchModeEnabled());
-
         // Ensure that NetworkChangeNotifier is initialized.
         if (!NetworkChangeNotifier.isInitialized()) {
             NetworkChangeNotifier.init();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
index 9f74539..31fc71d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -32,7 +32,6 @@
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.createDummySuggestions;
 
 import org.junit.After;
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -62,7 +61,6 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate;
 import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.support.DisableHistogramsRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
 import org.chromium.chrome.test.util.browser.Features;
@@ -119,9 +117,6 @@
 
     @Before
     public void setUp() {
-        // These tests fail on touchless builds, see https://crbug.com/981870.
-        Assume.assumeFalse(FeatureUtilities.isNoTouchModeEnabled());
-
         RecordUserAction.setDisabledForTests(true);
         MockitoAnnotations.initMocks(this);
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarControllerTest.java
index d48ec12..a072385 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarControllerTest.java
@@ -14,7 +14,6 @@
 
 import android.content.res.Resources;
 
-import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -26,7 +25,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.snackbar.Snackbar;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.webapk.lib.common.WebApkConstants;
 
 /**
@@ -44,10 +42,6 @@
 
     @Before
     public void setUp() throws InterruptedException {
-        // These tests are not applicable on touchless builds because snackbars/infobars are not
-        // shown on them, see https://crbug.com/981871.
-        Assume.assumeFalse(FeatureUtilities.isNoTouchModeEnabled());
-
         MockitoAnnotations.initMocks(this);
 
         doReturn("test text").when(mResources).getString(anyInt());
diff --git a/chrome/android/touchless/BUILD.gn b/chrome/android/touchless/BUILD.gn
deleted file mode 100644
index bc46a99..0000000
--- a/chrome/android/touchless/BUILD.gn
+++ /dev/null
@@ -1,64 +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.
-
-import("//build/config/android/rules.gni")
-
-java_strings_grd("touchless_strings_grd") {
-  grd_file = "java/strings/touchless_strings.grd"
-  outputs = [
-    "values/touchless_strings.xml",
-    "values-am/touchless_strings.xml",
-    "values-ar/touchless_strings.xml",
-    "values-bg/touchless_strings.xml",
-    "values-bn/touchless_strings.xml",
-    "values-ca/touchless_strings.xml",
-    "values-cs/touchless_strings.xml",
-    "values-da/touchless_strings.xml",
-    "values-de/touchless_strings.xml",
-    "values-el/touchless_strings.xml",
-    "values-en-rGB/touchless_strings.xml",
-    "values-es/touchless_strings.xml",
-    "values-es-rUS/touchless_strings.xml",
-    "values-et/touchless_strings.xml",
-    "values-fa/touchless_strings.xml",
-    "values-fi/touchless_strings.xml",
-    "values-fr/touchless_strings.xml",
-    "values-gu/touchless_strings.xml",
-    "values-hi/touchless_strings.xml",
-    "values-hr/touchless_strings.xml",
-    "values-hu/touchless_strings.xml",
-    "values-in/touchless_strings.xml",
-    "values-it/touchless_strings.xml",
-    "values-iw/touchless_strings.xml",
-    "values-ja/touchless_strings.xml",
-    "values-kn/touchless_strings.xml",
-    "values-ko/touchless_strings.xml",
-    "values-lt/touchless_strings.xml",
-    "values-lv/touchless_strings.xml",
-    "values-ml/touchless_strings.xml",
-    "values-mr/touchless_strings.xml",
-    "values-ms/touchless_strings.xml",
-    "values-nb/touchless_strings.xml",
-    "values-nl/touchless_strings.xml",
-    "values-pl/touchless_strings.xml",
-    "values-pt-rBR/touchless_strings.xml",
-    "values-pt-rPT/touchless_strings.xml",
-    "values-ro/touchless_strings.xml",
-    "values-ru/touchless_strings.xml",
-    "values-sk/touchless_strings.xml",
-    "values-sl/touchless_strings.xml",
-    "values-sr/touchless_strings.xml",
-    "values-sv/touchless_strings.xml",
-    "values-sw/touchless_strings.xml",
-    "values-ta/touchless_strings.xml",
-    "values-te/touchless_strings.xml",
-    "values-th/touchless_strings.xml",
-    "values-tl/touchless_strings.xml",
-    "values-tr/touchless_strings.xml",
-    "values-uk/touchless_strings.xml",
-    "values-vi/touchless_strings.xml",
-    "values-zh-rCN/touchless_strings.xml",
-    "values-zh-rTW/touchless_strings.xml",
-  ]
-}
diff --git a/chrome/android/touchless/OWNERS b/chrome/android/touchless/OWNERS
deleted file mode 100644
index 65f4572b..0000000
--- a/chrome/android/touchless/OWNERS
+++ /dev/null
@@ -1,14 +0,0 @@
-# General
-mdjones@chromium.org
-mthiesse@chromium.org
-yfriedman@chromium.org
-
-# NTP/Explore
-chili@chromium.org
-dewittj@chromium.org
-pavely@chromium.org
-skym@chromium.org
-wylieb@chromium.org
-
-# COMPONENT: Mobile>Touchless
-# OS: Android
diff --git a/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java b/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java
deleted file mode 100644
index 7a388fb..0000000
--- a/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java
+++ /dev/null
@@ -1,11 +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.download;
-
-/**
- * Fallback class for accessing this class name in
- * {@link org.chromium.chrome.browser.download.DownloadNotificationFactory}.
- */
-public class TouchlessDownloadActivity {}
diff --git a/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java b/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java
deleted file mode 100644
index 101637b..0000000
--- a/chrome/android/touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java
+++ /dev/null
@@ -1,59 +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.touchless;
-
-import android.content.Context;
-
-import androidx.annotation.StringRes;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.native_page.NativePage;
-import org.chromium.chrome.browser.native_page.NativePageHost;
-import org.chromium.chrome.browser.permissions.PermissionDialogDelegate;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * The fallback version of TouchlessDelegate, when touchless mode isn't enabled.
- */
-public class TouchlessDelegate {
-    public static final boolean TOUCHLESS_MODE_ENABLED = false;
-
-    public static NativePage createTouchlessNewTabPage(
-            ChromeActivity activity, NativePageHost host) {
-        return null;
-    }
-
-    public static boolean isTouchlessNewTabPage(NativePage nativePage) {
-        return false;
-    }
-
-    public static NativePage createTouchlessExploreSitesPage(
-            ChromeActivity activity, NativePageHost host) {
-        return null;
-    }
-
-    public static Class<? extends ChromeActivity> getNoTouchActivityClass() {
-        return null;
-    }
-
-    public static Class<?> getTouchlessPreferencesClass() {
-        return null;
-    }
-
-    public static PropertyModel getPermissionDialogModel(
-            ModalDialogProperties.Controller controller, PermissionDialogDelegate delegate) {
-        return null;
-    }
-
-    public static PropertyModel getMissingPermissionDialogModel(Context context,
-            ModalDialogProperties.Controller controller, @StringRes int messageId) {
-        return null;
-    }
-
-    public static TouchlessUiCoordinator getTouchlessUiCoordinator(ChromeActivity activity) {
-        return null;
-    }
-}
diff --git a/chrome/android/touchless/java/DEPS b/chrome/android/touchless/java/DEPS
deleted file mode 100644
index c17ad3c..0000000
--- a/chrome/android/touchless/java/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
-  "+chrome/lib/lifecycle/public",
-  "+chrome/browser/ui/android/widget",
-  "+components/feature_engagement/public",
-  "+components/offline_items_collection/core/android/java",
-  "+content/public/android/java/src/org/chromium/content_public",
-]
diff --git a/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml b/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml
deleted file mode 100644
index 15732ab..0000000
--- a/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/default_disabled_alpha" android:color="@color/default_text_color"
-          android:state_enabled="false"/>
-    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
-    <item android:color="@color/default_text_color"/>
-</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml b/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml
deleted file mode 100644
index 44ec600..0000000
--- a/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="@dimen/default_disabled_alpha"
-          android:color="@color/default_text_color_secondary" android:state_enabled="false"/>
-    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
-    <item android:color="@color/default_text_color_secondary"/>
-</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/color/touchless_icon_color.xml b/chrome/android/touchless/java/res/color/touchless_icon_color.xml
deleted file mode 100644
index 67b3937..0000000
--- a/chrome/android/touchless/java/res/color/touchless_icon_color.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
-    <item android:color="@color/default_icon_color"/>
-</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_1.png b/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_1.png
deleted file mode 100644
index 4fe34e64..0000000
--- a/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_2.png b/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_2.png
deleted file mode 100644
index 81ecb7f..0000000
--- a/chrome/android/touchless/java/res/drawable-hdpi/dino_stomp_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-hdpi/progress_bar_shadow.9.png b/chrome/android/touchless/java/res/drawable-hdpi/progress_bar_shadow.9.png
deleted file mode 100644
index 427ff726..0000000
--- a/chrome/android/touchless/java/res/drawable-hdpi/progress_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_1.png b/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_1.png
deleted file mode 100644
index b9c3162..0000000
--- a/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_2.png b/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_2.png
deleted file mode 100644
index 66d6474..0000000
--- a/chrome/android/touchless/java/res/drawable-mdpi/dino_stomp_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-mdpi/progress_bar_shadow.9.png b/chrome/android/touchless/java/res/drawable-mdpi/progress_bar_shadow.9.png
deleted file mode 100644
index f6bf182..0000000
--- a/chrome/android/touchless/java/res/drawable-mdpi/progress_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_1.png b/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_1.png
deleted file mode 100644
index 53a7d05..0000000
--- a/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_2.png b/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_2.png
deleted file mode 100644
index b1d85de..0000000
--- a/chrome/android/touchless/java/res/drawable-xhdpi/dino_stomp_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xhdpi/progress_bar_shadow.9.png b/chrome/android/touchless/java/res/drawable-xhdpi/progress_bar_shadow.9.png
deleted file mode 100644
index 4d611a10..0000000
--- a/chrome/android/touchless/java/res/drawable-xhdpi/progress_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_1.png b/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_1.png
deleted file mode 100644
index 8e8e320..0000000
--- a/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_2.png b/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_2.png
deleted file mode 100644
index cb2d0d6..0000000
--- a/chrome/android/touchless/java/res/drawable-xxhdpi/dino_stomp_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxhdpi/progress_bar_shadow.9.png b/chrome/android/touchless/java/res/drawable-xxhdpi/progress_bar_shadow.9.png
deleted file mode 100644
index 3f4962c..0000000
--- a/chrome/android/touchless/java/res/drawable-xxhdpi/progress_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_1.png b/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_1.png
deleted file mode 100644
index 1b354d00e..0000000
--- a/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_1.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_2.png b/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_2.png
deleted file mode 100644
index 4c826cfe..0000000
--- a/chrome/android/touchless/java/res/drawable-xxxhdpi/dino_stomp_2.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable-xxxhdpi/progress_bar_shadow.9.png b/chrome/android/touchless/java/res/drawable-xxxhdpi/progress_bar_shadow.9.png
deleted file mode 100644
index fcb1c69..0000000
--- a/chrome/android/touchless/java/res/drawable-xxxhdpi/progress_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/drawable/dialog_rounded_top.xml b/chrome/android/touchless/java/res/drawable/dialog_rounded_top.xml
deleted file mode 100644
index 1b17b7a..0000000
--- a/chrome/android/touchless/java/res/drawable/dialog_rounded_top.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <solid
-        android:color="@color/modern_primary_color" />
-
-    <corners
-        android:radius="1dp"
-        android:topLeftRadius="@dimen/default_rounded_corner_radius"
-        android:topRightRadius="@dimen/default_rounded_corner_radius"
-        android:bottomLeftRadius="0dp"
-        android:bottomRightRadius="0dp" />
-</shape>
diff --git a/chrome/android/touchless/java/res/drawable/dino_splash_animation.xml b/chrome/android/touchless/java/res/drawable/dino_splash_animation.xml
deleted file mode 100644
index 347599ff..0000000
--- a/chrome/android/touchless/java/res/drawable/dino_splash_animation.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
-                android:oneshot="false" android:visible="true">
-    <item android:drawable="@drawable/dino_stomp_1" android:duration="1000"/>
-    <item android:drawable="@drawable/dino_stomp_2" android:duration="500"/>
-</animation-list>
diff --git a/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml
deleted file mode 100644
index 1cace257..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml
+++ /dev/null
@@ -1,14 +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. -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        tools:targetApi="21">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M13,7h-2v4L7,11v2h4v4h2v-4h4v-2h-4L13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_cancel_circle.xml b/chrome/android/touchless/java/res/drawable/ic_cancel_circle.xml
deleted file mode 100644
index 1c15589..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_cancel_circle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        tools:targetApi="21"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM15.59,7L12,10.59 8.41,7 7,8.41 10.59,12 7,15.59 8.41,17 12,13.41 15.59,17 17,15.59 13.41,12 17,8.41z"/>
-</vector>
-
diff --git a/chrome/android/touchless/java/res/drawable/ic_check_circle.xml b/chrome/android/touchless/java/res/drawable/ic_check_circle.xml
deleted file mode 100644
index 796d6e0..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_check_circle.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        tools:targetApi="21"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM10,14.2l-2.6,-2.6L6,13l4,4 8,-8 -1.4,-1.4z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_cursor_navigation.xml b/chrome/android/touchless/java/res/drawable/ic_cursor_navigation.xml
deleted file mode 100644
index 99867785..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_cursor_navigation.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="14.0"
-    android:viewportWidth="14.0"
-    tools:ignore="NewApi">
-    <path
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"
-        android:pathData="M13.75,5.898L0.25,0.25L5.905,13.75H6.64L8.62,8.62L13.75,6.633V5.898ZM6.227,10.645L3.047,3.047L10.645,6.22L8.073,7.218L7.457,7.457L7.218,8.08L6.227,10.645Z" />
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml
deleted file mode 100644
index d21627d7..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml
+++ /dev/null
@@ -1,15 +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. -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        tools:ignore="NewApi">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:fillType="evenOdd"
-        android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_note_add.xml b/chrome/android/touchless/java/res/drawable/ic_note_add.xml
deleted file mode 100644
index 55149c24..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_note_add.xml
+++ /dev/null
@@ -1,14 +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. -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        tools:targetApi="21">
-  <path
-      android:fillColor="@color/touchless_icon_color"
-      android:pathData="M13,10h-2v3L8,13v2h3v3h2v-3h3v-2h-3zM14,2L6,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM18,20L6,20L6,4h7v5h5v11z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_pause_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_pause_circle_outline_24dp.xml
deleted file mode 100644
index f58ca261..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_pause_circle_outline_24dp.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        tools:targetApi="21"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M9,16h2L11,8L9,8v8zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM13,16h2L15,8h-2v8z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_play_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_play_circle_outline_24dp.xml
deleted file mode 100644
index 7394e98..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_play_circle_outline_24dp.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        tools:targetApi="21"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M10,16.5l6,-4.5 -6,-4.5v9zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml
deleted file mode 100644
index e3e5741..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml
+++ /dev/null
@@ -1,15 +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. -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        tools:ignore="NewApi">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:fillType="evenOdd"
-        android:pathData="M7,11v2h10v-2L7,11zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_search.xml b/chrome/android/touchless/java/res/drawable/ic_search.xml
deleted file mode 100644
index e59e61d..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_search.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:tools="http://schemas.android.com/tools"
-        android:height="24dp"
-        android:viewportHeight="24"
-        android:viewportWidth="24"
-        android:width="24dp"
-        tools:ignore="NewApi">
-    <path
-        android:fillColor="@color/touchless_icon_color"
-        android:pathData="M20.49,19l-5.73,-5.73C15.53,12.2 16,10.91 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.41,0 2.7,-0.47 3.77,-1.24L19,20.49 20.49,19zM5,9.5C5,7.01 7.01,5 9.5,5S14,7.01 14,9.5 11.99,14 9.5,14 5,11.99 5,9.5z"/>
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_spatial_navigation.xml b/chrome/android/touchless/java/res/drawable/ic_spatial_navigation.xml
deleted file mode 100644
index 152908ee..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_spatial_navigation.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="14.0"
-    android:viewportWidth="18.0"
-    tools:ignore="NewApi">
-    <path
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"
-        android:pathData="M2.25,0.25H15.75C16.575,0.25 17.25,0.925 17.25,1.75V12.25C17.25,13.075 16.575,13.75 15.75,13.75H2.25C1.425,13.75 0.75,13.075 0.75,12.25V1.75C0.75,0.925 1.425,0.25 2.25,0.25ZM2.25,12.25H15.75V1.75H2.25V12.25ZM9.007,2.125L7.5,4H10.5L9.007,2.125ZM13.5,8.5V5.5L15.375,7.008L13.5,8.5ZM4.5,5.5L2.625,7.008L4.5,8.5V5.5ZM7.5,10H10.5L9.007,11.875L7.5,10Z" />
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_zoom_in.xml b/chrome/android/touchless/java/res/drawable/ic_zoom_in.xml
deleted file mode 100644
index 2d373f7e..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_zoom_in.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="14.0"
-    android:viewportWidth="14.0"
-    tools:ignore="NewApi">
-    <path
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"
-        android:pathData="M13.368,12.25L9.07,7.952C9.648,7.15 10,6.182 10,5.125C10,2.432 7.818,0.25 5.125,0.25C2.432,0.25 0.25,2.432 0.25,5.125C0.25,7.818 2.432,10 5.125,10C6.182,10 7.15,9.648 7.952,9.07L12.25,13.368L13.368,12.25ZM5.125,8.5C3.257,8.5 1.75,6.992 1.75,5.125C1.75,3.257 3.257,1.75 5.125,1.75C6.992,1.75 8.5,3.257 8.5,5.125C8.5,6.992 6.992,8.5 5.125,8.5ZM7.375,4.375H5.875V2.875H4.375V4.375H2.875V5.875H4.375V7.375H5.875V5.875H7.375V4.375Z" />
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_zoom_out.xml b/chrome/android/touchless/java/res/drawable/ic_zoom_out.xml
deleted file mode 100644
index 32c8b8c..0000000
--- a/chrome/android/touchless/java/res/drawable/ic_zoom_out.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="14.0"
-    android:viewportWidth="14.0"
-    tools:ignore="NewApi">
-    <path
-        android:fillColor="#ffffff"
-        android:fillType="evenOdd"
-        android:pathData="M9.086,7.962C9.003,8.078 8.915,8.19 8.823,8.297L8.297,8.823C8.19,8.915 8.078,9.003 7.962,9.086L7.563,8.688L8.688,7.563L9.086,7.962ZM9.086,7.962C9.662,7.161 10,6.18 10,5.125C10,2.432 7.818,0.25 5.125,0.25C2.432,0.25 0.25,2.432 0.25,5.125C0.25,7.818 2.432,10 5.125,10C6.18,10 7.161,9.662 7.962,9.086L12.25,13.368L13.368,12.25L9.086,7.962ZM5.125,8.5C3.257,8.5 1.75,6.992 1.75,5.125C1.75,3.257 3.257,1.75 5.125,1.75C6.992,1.75 8.5,3.257 8.5,5.125C8.5,6.992 6.992,8.5 5.125,8.5ZM7,4.375H3.25V5.875H7V4.375Z" />
-</vector>
diff --git a/chrome/android/touchless/java/res/drawable/notouch_key_functions_iph_item_bg.xml b/chrome/android/touchless/java/res/drawable/notouch_key_functions_iph_item_bg.xml
deleted file mode 100644
index 7bf83f6..0000000
--- a/chrome/android/touchless/java/res/drawable/notouch_key_functions_iph_item_bg.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <stroke
-        android:width="1dp"
-        android:color="@color/notouch_key_functions_iph_item_border" />
-
-    <corners
-        android:bottomLeftRadius="4dp"
-        android:bottomRightRadius="4dp"
-        android:topLeftRadius="4dp"
-        android:topRightRadius="4dp" />
-</shape>
diff --git a/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml b/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml
deleted file mode 100644
index 3088e7d0..0000000
--- a/chrome/android/touchless/java/res/drawable/notouch_progress_bar_drawable.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background">
-        <shape>
-            <corners android:radius="@dimen/notouch_progressbar_radius"/>
-            <solid android:color="@color/notouch_progress_bar_background"/>
-        </shape>
-    </item>
-
-    <!-- Without the 1dp padding, the edges of this layer will be partially visible when a
-    foreground layer is added on top. -->
-    <item android:id="@android:id/progress"
-          android:left="1dp"
-          android:right="1dp"
-          android:top="1dp">
-        <clip>
-            <shape>
-                <corners android:radius="@dimen/notouch_progressbar_radius"/>
-                <solid android:color="@color/notouch_progress_bar_fill"/>
-            </shape>
-        </clip>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/notouch_progress_bar_pill.xml b/chrome/android/touchless/java/res/drawable/notouch_progress_bar_pill.xml
deleted file mode 100644
index e9beec2..0000000
--- a/chrome/android/touchless/java/res/drawable/notouch_progress_bar_pill.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <corners android:radius="@dimen/notouch_progressbar_radius"/>
-    <solid android:color="@android:color/white"/>
-</shape>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/notouch_tooltip_bg.xml b/chrome/android/touchless/java/res/drawable/notouch_tooltip_bg.xml
deleted file mode 100644
index 2a06a08b..0000000
--- a/chrome/android/touchless/java/res/drawable/notouch_tooltip_bg.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <solid
-        android:color="@color/notouch_tooltip_background" />
-
-    <corners
-        android:bottomLeftRadius="8dp"
-        android:bottomRightRadius="8dp"
-        android:topLeftRadius="8dp"
-        android:topRightRadius="8dp" />
-</shape>
diff --git a/chrome/android/touchless/java/res/drawable/suggestion_tile_background.xml b/chrome/android/touchless/java/res/drawable/suggestion_tile_background.xml
deleted file mode 100644
index d1599ca..0000000
--- a/chrome/android/touchless/java/res/drawable/suggestion_tile_background.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/suggestion_tile_focused_background" android:state_focused="true"/>
-    <item android:drawable="@drawable/tile_view_icon_background_modern" />
-</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_background.xml b/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_background.xml
deleted file mode 100644
index bb77a80..0000000
--- a/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_background.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <solid android:color="@color/modern_blue_600_alpha_12" />
-</shape>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_highlight.xml b/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_highlight.xml
deleted file mode 100644
index 7529ac62..0000000
--- a/chrome/android/touchless/java/res/drawable/suggestion_tile_focused_highlight.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval">
-    <stroke android:width="@dimen/focus_ring_stroke_width" android:color="@color/modern_blue_800"/>
-</shape>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/suggestion_tile_highlight.xml b/chrome/android/touchless/java/res/drawable/suggestion_tile_highlight.xml
deleted file mode 100644
index 4a64b1d..0000000
--- a/chrome/android/touchless/java/res/drawable/suggestion_tile_highlight.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/suggestion_tile_focused_highlight" android:state_focused="true"/>
-</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/dialog_list_item.xml b/chrome/android/touchless/java/res/layout/dialog_list_item.xml
deleted file mode 100644
index 3b2c166..0000000
--- a/chrome/android/touchless/java/res/layout/dialog_list_item.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:focusable="true"
-    android:paddingStart="12dp"
-    android:paddingEnd="12dp"
-    android:paddingTop="9dp"
-    android:paddingBottom="9dp"
-    android:orientation="horizontal"
-    android:background="@color/modern_primary_color"
-    android:theme="@style/Theme.AppCompat.Light">
-
-    <org.chromium.ui.widget.ChromeImageView
-        android:id="@+id/dialog_item_icon"
-        android:layout_width="18dp"
-        android:layout_height="18dp"
-        android:layout_gravity="center_vertical"
-        android:layout_marginEnd="10dp"
-        android:duplicateParentState="true"
-        android:scaleType="centerInside"
-        android:visibility="gone"/>
-
-    <TextView
-        android:id="@+id/dialog_item_text"
-        style="@style/TextAppearance.BlackBodyDefault.Touchless"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="center_vertical"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/dino_splash_view.xml b/chrome/android/touchless/java/res/layout/dino_splash_view.xml
deleted file mode 100644
index 54a2a95..0000000
--- a/chrome/android/touchless/java/res/layout/dino_splash_view.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:background="@android:color/white">
-
-        <TextView style="@style/TextAppearance.BlackTitle1"
-                  android:id="@+id/dino_splash_text_image"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:layout_centerInParent="true"
-                  android:drawablePadding="35dp"
-                  android:gravity="center"
-                  android:drawableTop="@drawable/dino_splash_animation"
-                  android:layout_gravity="center_horizontal"
-                  android:text="@string/dino_game_title"/>
-</RelativeLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/most_likely_touchless.xml b/chrome/android/touchless/java/res/layout/most_likely_touchless.xml
deleted file mode 100644
index 6a5f879..0000000
--- a/chrome/android/touchless/java/res/layout/most_likely_touchless.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingVertical="@dimen/most_likely_carousel_edge_spacer"
-    android:gravity="center_horizontal">
-
-    <org.chromium.chrome.browser.touchless.SiteSuggestionsRecyclerView
-        android:id="@+id/most_likely_launcher_recycler"
-        android:background="@color/modern_primary_color"
-        android:scrollbars="none"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal" />
-
-    <TextView
-        android:id="@+id/most_likely_web_title_text"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:textAppearance="@style/TextAppearance.BlackTitle2"
-        android:maxLines="1"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/new_tab_page_touchless.xml b/chrome/android/touchless/java/res/layout/new_tab_page_touchless.xml
deleted file mode 100644
index 0f52686..0000000
--- a/chrome/android/touchless/java/res/layout/new_tab_page_touchless.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<org.chromium.chrome.browser.touchless.TouchlessNewTabPageTopLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:gravity="center">
-
-    <ViewStub android:id="@+id/most_likely_stub"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/most_likely_bottom_margin"
-        android:layout="@layout/most_likely_touchless" />
-
-    <org.chromium.chrome.browser.touchless.OpenLastTabView
-        android:id="@+id/open_last_tab_button"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:paddingHorizontal="@dimen/open_last_tab_button_padding_horizontal"
-        android:paddingVertical="@dimen/open_last_tab_button_padding_vertical"
-        android:layout_marginBottom="@dimen/open_last_tab_bottom_margin"
-        android:background="@drawable/hairline_border_card_background"
-        style="@style/Theme.AppCompat.Light"/>
-
-</org.chromium.chrome.browser.touchless.TouchlessNewTabPageTopLayout>
diff --git a/chrome/android/touchless/java/res/layout/new_tab_page_touchless_view.xml b/chrome/android/touchless/java/res/layout/new_tab_page_touchless_view.xml
deleted file mode 100644
index 0019fd06..0000000
--- a/chrome/android/touchless/java/res/layout/new_tab_page_touchless_view.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <org.chromium.chrome.browser.touchless.TouchlessRecyclerView
-        android:id="@+id/suggestions_recycler_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:scrollbars="vertical"
-        android:scrollbarStyle="outsideOverlay"
-        android:paddingStart="@dimen/touchless_new_tab_view_padding_horizontal"
-        android:paddingEnd="@dimen/touchless_new_tab_view_padding_horizontal" />
-</FrameLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/notouch_key_functions_view.xml b/chrome/android/touchless/java/res/layout/notouch_key_functions_view.xml
deleted file mode 100644
index efd1419..0000000
--- a/chrome/android/touchless/java/res/layout/notouch_key_functions_view.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<org.chromium.chrome.browser.touchless.ui.iph.KeyFunctionsIPHView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    tools:ignore="ContentDescription,HardcodedText">
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layoutDirection="ltr"
-        android:orientation="horizontal">
-
-        <LinearLayout
-            android:layout_width="@dimen/notouch_key_functions_tooltip_item_width"
-            android:layout_height="@dimen/notouch_key_functions_tooltip_item_height"
-            android:background="@drawable/notouch_key_functions_iph_item_bg"
-            android:orientation="horizontal">
-
-            <TextView
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:gravity="center"
-                android:paddingStart="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:text="0"
-                android:textAppearance="@style/TextAppearance.NoTouchKeyFunctionsIPH"/>
-
-            <ImageView
-                android:id="@+id/navigation_mode_image"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:paddingBottom="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:paddingEnd="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:paddingTop="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:scaleType="centerInside"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="@dimen/notouch_key_functions_tooltip_item_width"
-            android:layout_height="@dimen/notouch_key_functions_tooltip_item_height"
-            android:layout_marginEnd="@dimen/notouch_key_functions_tooltip_item_horizontal_margin"
-            android:layout_marginStart="@dimen/notouch_key_functions_tooltip_item_horizontal_margin"
-            android:background="@drawable/notouch_key_functions_iph_item_bg"
-            android:orientation="horizontal">
-
-            <TextView
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:gravity="center"
-                android:paddingStart="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:text="1"
-                android:textAppearance="@style/TextAppearance.NoTouchKeyFunctionsIPH"/>
-
-            <ImageView
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:paddingBottom="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:paddingEnd="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:paddingTop="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:scaleType="centerInside"
-                app:srcCompat="@drawable/ic_zoom_out"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="@dimen/notouch_key_functions_tooltip_item_width"
-            android:layout_height="@dimen/notouch_key_functions_tooltip_item_height"
-            android:background="@drawable/notouch_key_functions_iph_item_bg"
-            android:orientation="horizontal">
-
-            <TextView
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:gravity="center"
-                android:paddingStart="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:text="3"
-                android:textAppearance="@style/TextAppearance.NoTouchKeyFunctionsIPH"/>
-
-            <ImageView
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:paddingBottom="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:paddingEnd="@dimen/notouch_key_functions_tooltip_item_padding"
-                android:paddingTop="@dimen/notouch_key_functions_tooltip_item_image_vertical_padding"
-                android:scaleType="centerInside"
-                app:srcCompat="@drawable/ic_zoom_in"/>
-
-        </LinearLayout>
-    </LinearLayout>
-</org.chromium.chrome.browser.touchless.ui.iph.KeyFunctionsIPHView>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml b/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml
deleted file mode 100644
index 3405ffa..0000000
--- a/chrome/android/touchless/java/res/layout/notouch_progress_bar_view.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal"
-    android:background="@drawable/progress_bar_shadow">
-
-    <org.chromium.chrome.browser.touchless.ui.progressbar.PillProgressBarView
-        android:id="@+id/notouch_progress_bar_view"
-        style="@android:style/Widget.ProgressBar.Horizontal"
-        android:layout_width="192dp"
-        android:layout_height="36dp"/>
-
-    <TextView
-        android:id="@+id/notouch_url_text_view"
-        style="@style/TextAppearance.NoTouchProgressBar"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="center"
-        android:gravity="center"
-        android:ellipsize="start"
-        android:singleLine="true"
-        android:textDirection="ltr"/>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/notouch_tooltip_view.xml b/chrome/android/touchless/java/res/layout/notouch_tooltip_view.xml
deleted file mode 100644
index 3089b05..0000000
--- a/chrome/android/touchless/java/res/layout/notouch_tooltip_view.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:alpha=".9"
-             android:background="@drawable/notouch_tooltip_bg"
-             android:focusable="false"
-             android:focusableInTouchMode="false"
-             android:padding="@dimen/notouch_tooltip_padding"/>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml b/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
deleted file mode 100644
index 11575ed4..0000000
--- a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<merge
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:targetApi="21">
-    <org.chromium.ui.widget.ChromeImageView
-        android:id="@+id/favicon"
-        android:layout_width="@dimen/open_last_tab_icon_size"
-        android:layout_height="@dimen/open_last_tab_icon_size"
-        android:layout_gravity="center_vertical"
-        android:scaleType="centerInside"/>
-
-    <TextView
-        android:id="@+id/title"
-        style="@style/TextAppearance.BlackBodyDefault.Touchless"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_marginStart="@dimen/open_last_tab_title_text_margin_left"
-        android:ellipsize="end"
-        android:maxLines="1"/>
-
-    <TextView
-        android:id="@+id/timestamp"
-        style="@style/TextAppearance.BlackCaption.Touchless"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/open_last_tab_timestamp_text_margin_left"
-        android:ellipsize="end"
-        android:maxLines="1" />
-
-</merge>
diff --git a/chrome/android/touchless/java/res/layout/touchless_action_card.xml b/chrome/android/touchless/java/res/layout/touchless_action_card.xml
deleted file mode 100644
index 6ae4b6c..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_action_card.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:focusable="false">
-
-    <!-- android:id should match what ActionItem#ViewHolder expects. -->
-    <include android:id="@+id/action_button" layout="@layout/dialog_list_item"/>
-
-    <org.chromium.chrome.browser.ntp.cards.ProgressIndicatorView
-        android:id="@+id/progress_indicator"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"/>
-
-</FrameLayout>
diff --git a/chrome/android/touchless/java/res/layout/touchless_content_suggestions_card.xml b/chrome/android/touchless/java/res/layout/touchless_content_suggestions_card.xml
deleted file mode 100644
index d8c666b..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_content_suggestions_card.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="@drawable/hairline_border_card_background"
-    android:layout_marginBottom="@dimen/content_suggestions_card_modern_margin">
-
-    <LinearLayout
-        android:id="@+id/text_layout"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        android:layout_toStartOf="@+id/article_thumbnail"
-        android:layout_alignWithParentIfMissing="true"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:paddingHorizontal="@dimen/touchless_snippets_padding"
-        android:orientation="vertical">
-
-        <TextView
-            style="@style/TextAppearance.BlackBodyDefault"
-            android:id="@+id/article_headline"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/touchless_snippets_headline_margin_top"
-            android:ellipsize="end"
-            tools:text="Article headline" />
-
-        <TextView
-            android:id="@+id/article_age"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:layout_marginTop="@dimen/touchless_snippets_age_margin_top"
-            android:layout_marginBottom="@dimen/touchless_snippets_age_margin_bottom"
-            android:textAppearance="@style/TextAppearance.BlackCaption"
-            android:textDirection="locale"
-            tools:text=" 3 hours ago" />
-
-    </LinearLayout>
-
-    <ImageView
-        android:id="@+id/article_thumbnail"
-        android:importantForAccessibility="no"
-        android:layout_width="@dimen/touchless_snippets_thumbnail_size"
-        android:layout_height="@dimen/touchless_snippets_thumbnail_size"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="@dimen/touchless_thumbnail_margin"
-        android:layout_marginTop="@dimen/touchless_thumbnail_margin"
-        android:layout_marginBottom="@dimen/touchless_thumbnail_margin"
-        android:scaleType="centerCrop" />
-
-</RelativeLayout>
diff --git a/chrome/android/touchless/java/res/layout/touchless_dialog_view.xml b/chrome/android/touchless/java/res/layout/touchless_dialog_view.xml
deleted file mode 100644
index d288cab..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_dialog_view.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:paddingTop="12dp">
-
-    <org.chromium.ui.widget.ChromeImageView
-        android:id="@+id/touchless_dialog_icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:visibility="gone" />
-
-    <TextView
-        android:id="@+id/touchless_dialog_title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:ellipsize="end"
-        android:padding="8dp"
-        android:textAppearance="@style/TextAppearance.BlackTitle1"
-        android:visibility="gone" />
-
-    <TextView
-        android:id="@+id/touchless_dialog_description"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:padding="8dp"
-        android:textAppearance="@style/TextAppearance.BlackBody"
-        android:visibility="gone" />
-
-    <FrameLayout
-        android:id="@+id/custom"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:visibility="gone" />
-
-    <ListView
-        android:id="@+id/touchless_dialog_option_list"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="8dp"
-        android:paddingBottom="12dp"
-        android:paddingHorizontal="8dp"
-        android:divider="@android:color/transparent"
-        android:dividerHeight="8dp"
-        android:layout_gravity="center"
-        android:clipToPadding="false"
-        android:scrollbars="none" />
-
-</LinearLayout>
diff --git a/chrome/android/touchless/java/res/layout/touchless_download_options.xml b/chrome/android/touchless/java/res/layout/touchless_download_options.xml
deleted file mode 100644
index 772c406..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_download_options.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:paddingTop="12dp">
-
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:ellipsize="middle"
-        android:padding="8dp"
-        android:singleLine="true"
-        android:gravity="center"
-        android:textAppearance="@style/TextAppearance.BlackTitle1"/>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingTop="8dp"
-        android:paddingHorizontal="8dp"
-        android:divider="@android:color/transparent"
-        android:dividerHeight="8dp"
-        android:layout_gravity="center"
-        android:scrollbars="none">
-
-        <!-- TODO(976819): Use TextViewWithCompoundDrawables instead of these LinearLayouts. -->
-        <LinearLayout
-            android:id="@+id/pause_resume_option"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="12dp"
-            android:paddingEnd="12dp"
-            android:paddingTop="9dp"
-            android:paddingBottom="9dp"
-            android:layout_marginBottom="8dp"
-            android:orientation="horizontal"
-            android:background="@color/modern_primary_color"
-            android:clickable="true"
-            android:focusable="true"
-            android:theme="@style/Theme.AppCompat.Light">
-
-            <org.chromium.ui.widget.ChromeImageView
-                android:id="@+id/pause_resume_icon"
-                android:layout_width="18dp"
-                android:layout_height="18dp"
-                android:layout_gravity="center_vertical"
-                android:layout_marginEnd="10dp"
-                android:scaleType="centerInside"
-                android:duplicateParentState="true"/>
-
-            <TextView
-                android:id="@+id/pause_resume_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:gravity="center_vertical"
-                style="@style/TextAppearance.BlackBodyDefault.Touchless"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:id="@+id/cancel_option"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingStart="12dp"
-            android:paddingEnd="12dp"
-            android:paddingTop="9dp"
-            android:paddingBottom="9dp"
-            android:orientation="horizontal"
-            android:background="@color/modern_primary_color"
-            android:clickable="true"
-            android:focusable="true"
-            android:theme="@style/Theme.AppCompat.Light">
-
-            <org.chromium.ui.widget.ChromeImageView
-                android:layout_width="18dp"
-                android:layout_height="18dp"
-                android:layout_gravity="center_vertical"
-                android:layout_marginEnd="10dp"
-                android:scaleType="centerInside"
-                app:srcCompat="@drawable/ic_cancel_circle"
-                android:duplicateParentState="true"/>
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:gravity="center_vertical"
-                style="@style/TextAppearance.BlackBodyDefault.Touchless"
-                android:text="@string/cancel"/>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/chrome/android/touchless/java/res/layout/touchless_explore_sites_category_card_view.xml b/chrome/android/touchless/java/res/layout/touchless_explore_sites_category_card_view.xml
deleted file mode 100644
index a3312e0..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_explore_sites_category_card_view.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<org.chromium.chrome.browser.touchless.TouchlessExploreSitesCategoryCardView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:gravity="center_horizontal"
-    android:orientation="vertical"
-    android:paddingBottom="@dimen/explore_sites_category_padding_vertical_condensed"
-    android:paddingTop="@dimen/explore_sites_category_padding_vertical_condensed"
-    android:paddingStart="@dimen/explore_sites_category_padding_horizontal_condensed"
-    android:paddingEnd="@dimen/explore_sites_category_padding_horizontal_condensed">
-
-    <TextView
-        android:id="@+id/category_title"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:textAppearance="@style/TextAppearance.BlackBodyDefault"
-        tools:text="Category" />
-
-    <org.chromium.chrome.browser.suggestions.tile.TileGridLayout
-        android:id="@+id/category_sites"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:orientation="horizontal"
-        android:columnCount="4"
-        android:columnOrderPreserved="true"
-        app:minHorizontalSpacing="@dimen/explore_sites_category_grid_minimum_spacing"
-        android:paddingTop="@dimen/explore_sites_category_title_spacing_condensed" />
-
-</org.chromium.chrome.browser.touchless.TouchlessExploreSitesCategoryCardView>
diff --git a/chrome/android/touchless/java/res/layout/touchless_explore_sites_tile_view_condensed.xml b/chrome/android/touchless/java/res/layout/touchless_explore_sites_tile_view_condensed.xml
deleted file mode 100644
index ab6748e..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_explore_sites_tile_view_condensed.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<org.chromium.chrome.browser.explore_sites.ExploreSitesTileView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="@dimen/explore_sites_tile_view_width_condensed"
-    android:layout_height="wrap_content"
-    android:paddingStart="@dimen/explore_sites_tile_view_icon_padding_horizontal_condensed"
-    android:paddingEnd="@dimen/explore_sites_tile_view_icon_padding_horizontal_condensed">
-        <!-- The icon background. -->
-        <View
-            android:id="@+id/tile_view_icon_background"
-            android:layout_width="@dimen/explore_sites_tile_view_icon_background_size_condensed"
-            android:layout_height="@dimen/explore_sites_tile_view_icon_background_size_condensed"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="@dimen/tile_view_icon_background_margin_top_modern"
-            android:background="@drawable/tile_view_icon_background_modern" />
-
-        <!-- The main icon. -->
-        <ImageView
-            android:id="@+id/tile_view_icon"
-            android:layout_width="@dimen/explore_sites_tile_view_icon_size_condensed"
-            android:layout_height="@dimen/explore_sites_tile_view_icon_size_condensed"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="@dimen/explore_sites_tile_view_icon_margin_top_condensed"
-            tools:ignore="ContentDescription"  />
-
-        <!-- The touch highlight. -->
-        <View
-            android:id="@+id/tile_view_highlight"
-            android:layout_width="@dimen/explore_sites_tile_view_icon_background_size_condensed"
-            android:layout_height="@dimen/explore_sites_tile_view_icon_background_size_condensed"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="@dimen/tile_view_icon_background_margin_top_modern"
-            android:background="@drawable/tile_view_highlight" />
-
-        <!-- The offline badge. -->
-        <ImageView
-            android:id="@+id/offline_badge"
-            android:layout_width="@dimen/tile_view_offline_badge_size_modern"
-            android:layout_height="@dimen/tile_view_offline_badge_size_modern"
-            android:layout_gravity="top|end"
-            android:layout_marginTop="@dimen/tile_view_offline_badge_margin_top_modern"
-            android:layout_marginEnd="@dimen/tile_view_offline_badge_margin_end_modern"
-            android:visibility="gone"
-            android:contentDescription="@string/accessibility_ntp_offline_badge"
-            app:srcCompat="@drawable/ic_offline_pin_blue_white" />
-
-        <!-- The title. -->
-        <TextView
-            android:id="@+id/tile_view_title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/explore_sites_tile_view_title_margin_top_condensed"
-            android:ellipsize="end"
-            android:gravity="center_horizontal"
-            android:lines="2"
-            android:lineSpacingMultiplier="1.17"
-            android:layout_marginBottom="@dimen/explore_sites_tile_view_text_margin_bottom_condensed"
-            android:textAppearance="@style/TextAppearance.BlackCaptionDefault" />
-</org.chromium.chrome.browser.explore_sites.ExploreSitesTileView>
diff --git a/chrome/android/touchless/java/res/layout/touchless_suggestions_tile_view.xml b/chrome/android/touchless/java/res/layout/touchless_suggestions_tile_view.xml
deleted file mode 100644
index 5287523..0000000
--- a/chrome/android/touchless/java/res/layout/touchless_suggestions_tile_view.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<org.chromium.chrome.browser.touchless.SiteSuggestionsTileView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="@dimen/tile_view_icon_size"
-    android:layout_height="@dimen/tile_view_icon_size"
-    android:layout_gravity="center"
-    android:background="@drawable/suggestion_tile_highlight">
-    <!-- The icon background. -->
-    <View
-        android:id="@+id/tile_view_icon_background"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@drawable/suggestion_tile_background"
-        android:duplicateParentState="true" />
-
-    <!-- The main icon. -->
-    <org.chromium.chrome.browser.touchless.QuantizedSizeIconView
-        android:id="@+id/tile_view_icon"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="center"
-        app:smallSize="@dimen/most_likely_quantized_icon_size_small"
-        app:largeSize="@dimen/most_likely_quantized_icon_size_large"
-        android:layout_margin="@dimen/most_likely_quantized_icon_margin" />
-
-    <!-- Focus highlight. -->
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@drawable/suggestion_tile_highlight"
-        android:duplicateParentState="true" />
-
-    <!-- The offline badge. -->
-    <ImageView
-        android:id="@+id/offline_badge"
-        android:layout_width="@dimen/tile_view_offline_badge_size_modern"
-        android:layout_height="@dimen/tile_view_offline_badge_size_modern"
-        android:layout_gravity="top|end"
-        android:layout_marginEnd="@dimen/tile_view_offline_badge_margin_end_modern_condensed"
-        android:visibility="gone"
-        android:importantForAccessibility="no"
-        app:srcCompat="@drawable/ic_offline_pin_blue_white" />
-</org.chromium.chrome.browser.touchless.SiteSuggestionsTileView>
diff --git a/chrome/android/touchless/java/res/mipmap/dino.png b/chrome/android/touchless/java/res/mipmap/dino.png
deleted file mode 100644
index 071d624..0000000
--- a/chrome/android/touchless/java/res/mipmap/dino.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/touchless/java/res/values-v17/attrs.xml b/chrome/android/touchless/java/res/values-v17/attrs.xml
deleted file mode 100644
index 029600d..0000000
--- a/chrome/android/touchless/java/res/values-v17/attrs.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2014 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-
-<resources>
-    <declare-styleable name="QuantizedSizeIconView">
-        <attr name="smallSize" format="dimension"/>
-        <attr name="largeSize" format="dimension"/>
-    </declare-styleable>
-</resources>
diff --git a/chrome/android/touchless/java/res/values-v17/colors.xml b/chrome/android/touchless/java/res/values-v17/colors.xml
deleted file mode 100644
index 5f8c7d08..0000000
--- a/chrome/android/touchless/java/res/values-v17/colors.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<resources>
-    <color name="modern_blue_600_alpha_12">#1F185ABC</color>
-    <color name="modern_blue_600_alpha_24">#3D1A73E8</color>
-    <color name="notouch_progress_bar_background">@color/modern_blue_600_alpha_24</color>
-    <color name="notouch_progress_bar_fill">@color/modern_blue_600</color>
-    <color name="notouch_progress_bar_text">@color/modern_grey_800</color>
-    <color name="notouch_tooltip_background">@color/modern_grey_800</color>
-    <color name="notouch_key_functions_iph_item_border">@android:color/white</color>
-</resources>
diff --git a/chrome/android/touchless/java/res/values-v17/dimens.xml b/chrome/android/touchless/java/res/values-v17/dimens.xml
deleted file mode 100644
index 4c1b170..0000000
--- a/chrome/android/touchless/java/res/values-v17/dimens.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-<resources>
-    <dimen name="touchless_new_tab_view_padding_horizontal">8dp</dimen>
-    <dimen name="touchless_new_tab_recycler_view_over_scroll">24dp</dimen>
-
-    <dimen name="notouch_tooltip_padding">8dp</dimen>
-    <dimen name="notouch_tooltip_margin_bottom">16dp</dimen>
-    <dimen name="notouch_key_functions_tooltip_item_width">40dp</dimen>
-    <dimen name="notouch_key_functions_tooltip_item_height">24dp</dimen>
-    <dimen name="notouch_key_functions_tooltip_item_padding">4dp</dimen>
-    <dimen name="notouch_key_functions_tooltip_item_image_vertical_padding">5dp</dimen>
-    <dimen name="notouch_key_functions_tooltip_item_horizontal_margin">4dp</dimen>
-
-    <dimen name="notouch_progressbar_fill_height">2dp</dimen>
-    <dimen name="notouch_progressbar_radius">18dp</dimen>
-
-    <dimen name="focus_ring_stroke_width">2dp</dimen>
-    <dimen name="touchless_preferences_highlight_padding">8dp</dimen>
-
-    <!-- Open last tab button dimensions. -->
-    <dimen name="open_last_tab_button_padding_horizontal">12dp</dimen>
-    <dimen name="open_last_tab_button_padding_vertical">9dp</dimen>
-    <dimen name="open_last_tab_bottom_margin">8dp</dimen>
-    <dimen name="open_last_tab_icon_size">16dp</dimen>
-    <dimen name="open_last_tab_title_text_margin_left">12dp</dimen>
-    <dimen name="open_last_tab_timestamp_text_margin_left">10dp</dimen>
-
-    <!-- Most likely carousel dimensions. -->
-    <dimen name="most_likely_bottom_margin">16dp</dimen>
-    <dimen name="most_likely_carousel_edge_spacer">8dp</dimen>
-    <dimen name="most_likely_tile_size">40dp</dimen>
-    <dimen name="most_likely_quantized_icon_size_large">24dp</dimen>
-    <dimen name="most_likely_quantized_icon_size_small">18dp</dimen>
-    <!-- 6dp chosen so that the icon is large in the inner 3 positions and small in
-         the outer two positions. -->
-    <dimen name="most_likely_quantized_icon_margin">6dp</dimen>
-
-    <!-- Article specific dimensions. -->
-    <dimen name="touchless_snippets_padding">12dp</dimen>
-    <dimen name="touchless_snippets_thumbnail_size">64dp</dimen>
-    <dimen name="touchless_thumbnail_margin">12dp</dimen>
-    <!-- Desired 12dp space but headline text has 2dp of ascenders padding that
-    the mocks don't take into account -->
-    <dimen name="touchless_snippets_headline_margin_top">10dp</dimen>
-    <!-- Desired 8dp of space but adjusted to 7dp to to allow cards to match
-    specified height. Then, the headline's descender padding and age acender's
-    padding contribut to 3dp more. 7 - 3 = 4. -->
-    <dimen name="touchless_snippets_age_margin_top">4dp</dimen>
-    <dimen name="touchless_publisher_icon_size">12dp</dimen>
-    <!-- Desired 11dp of padding but age text has 1 dp of descender padding that
-    the mocks don't take into account -->
-    <dimen name="touchless_snippets_age_margin_bottom">10dp</dimen>
-
-    <dimen name="explore_sites_category_padding_vertical_condensed">12dp</dimen>
-    <dimen name="explore_sites_category_padding_horizontal_condensed">4dp</dimen>
-    <dimen name="explore_sites_category_grid_minimum_spacing">8dp</dimen>
-    <dimen name="explore_sites_category_title_spacing_condensed">10dp</dimen>
-    <dimen name="explore_sites_tile_view_icon_background_size_condensed">44dp</dimen>
-    <dimen name="explore_sites_tile_view_icon_size_condensed">22dp</dimen>
-    <dimen name="explore_sites_tile_view_icon_margin_top_condensed">18dp</dimen>
-    <dimen name="explore_sites_tile_view_title_margin_top_condensed">51dp</dimen>
-    <dimen name="explore_sites_tile_view_width_condensed">72dp</dimen>
-    <dimen name="explore_sites_tile_view_icon_padding_horizontal_condensed">4dp</dimen>
-    <dimen name="explore_sites_tile_view_text_margin_bottom_condensed">4dp</dimen>
-
-</resources>
diff --git a/chrome/android/touchless/java/res/values-v17/styles.xml b/chrome/android/touchless/java/res/values-v17/styles.xml
deleted file mode 100644
index eac946a..0000000
--- a/chrome/android/touchless/java/res/values-v17/styles.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<resources xmlns:tools="http://schemas.android.com/tools">
-    <style name="TextAppearance.BlackBodyDefault.Touchless">
-        <item name="android:textColor">@color/touchless_default_text_color_list</item>
-        <item name="android:duplicateParentState">true</item>
-    </style>
-
-    <style name="TextAppearance.BlackCaption.Touchless">
-        <item name="android:textColor">@color/touchless_default_text_color_secondary_list</item>
-        <item name="android:duplicateParentState">true</item>
-    </style>
-
-    <style name="TextAppearance.NoTouchProgressBar">
-        <item name="android:textSize">14sp</item>
-        <item name="android:textColor">@color/notouch_progress_bar_text</item>
-    </style>
-
-    <style name="TextAppearance.NoTouchKeyFunctionsIPH">
-        <item name="android:textSize">14sp</item>
-        <item name="android:textColor">@android:color/white</item>
-    </style>
-
-    <style name="PreferenceActionBarModern.Touchless">
-        <item name="titleTextStyle">@style/TextAppearance.BlackTitle1</item>
-    </style>
-
-    <style name="Theme.Chromium.Preferences.Touchless">
-        <item name="android:statusBarColor" tools:targetApi="21">@color/modern_primary_color</item>
-        <item name="android:windowLightStatusBar" tools:targetApi="23">@bool/window_light_navigation_bar</item>
-        <item name="actionBarStyle">@style/PreferenceActionBarModern.Touchless</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java
deleted file mode 100644
index 1ffacfd6..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java
+++ /dev/null
@@ -1,125 +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.download;
-
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.browser.SynchronousInitializationActivity;
-import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
-import org.chromium.chrome.browser.download.home.glue.OfflineContentProviderGlue;
-import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
-import org.chromium.chrome.touchless.R;
-import org.chromium.components.offline_items_collection.ContentId;
-import org.chromium.components.offline_items_collection.OfflineItem;
-import org.chromium.components.offline_items_collection.OfflineItemState;
-import org.chromium.ui.widget.ChromeImageView;
-
-/**
- * An activity that reacts to download notifications on touchless devices. This activity is 1:1
- * with each download and will only show the title of the download and actions to pause, resume, and
- * cancel.
- */
-public class TouchlessDownloadActivity extends SynchronousInitializationActivity {
-    /** The title of the download UI. */
-    private TextView mDownloadTitle;
-
-    /** The view containing the text for the pause/resume button. */
-    private TextView mPauseResumeText;
-
-    /** The view for the icon shown for the pause/resume option. */
-    private ChromeImageView mPauseResumeIcon;
-
-    /** A handle to the offline item representing the download. */
-    private OfflineItem mOfflineItem;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        // Hard-code setIsOffTheRecord to false since incognito is unsupported in touchless mode.
-        DownloadManagerUiConfig config = new DownloadManagerUiConfig.Builder()
-                                                 .setIsOffTheRecord(false)
-                                                 .setIsSeparateActivity(true)
-                                                 .build();
-
-        OfflineContentProviderGlue downloadGlue =
-                new OfflineContentProviderGlue(OfflineContentAggregatorFactory.get(), config);
-
-        final ContentId id = DownloadBroadcastManager.getContentIdFromIntent(getIntent());
-
-        // If there's no ID for the download, finish the activity.
-        if (id == null) finish();
-
-        ViewGroup group =
-                (ViewGroup) getLayoutInflater().inflate(R.layout.touchless_download_options, null);
-        setContentView(group);
-        mDownloadTitle = (TextView) group.findViewById(R.id.title);
-        mPauseResumeIcon = (ChromeImageView) group.findViewById(R.id.pause_resume_icon);
-        mPauseResumeText = (TextView) group.findViewById(R.id.pause_resume_text);
-        updateVisualsForOfflineItem(null);
-
-        // TODO(976419): Use getItemById once implemented.
-        downloadGlue.getAllItems((items) -> {
-            for (OfflineItem item : items) {
-                if (item.id.equals(id)) {
-                    mOfflineItem = item;
-                    break;
-                }
-            }
-
-            // Don't show the UI if there's no download to display.
-            if (mOfflineItem == null) finish();
-
-            updateVisualsForOfflineItem(mOfflineItem);
-        });
-
-        // Handle clicks on the cancel option.
-        View cancelOption = group.findViewById(R.id.cancel_option);
-        cancelOption.setOnClickListener((v) -> {
-            if (mOfflineItem == null) return;
-            downloadGlue.cancelDownload(mOfflineItem);
-            finish();
-        });
-
-        View pauseOption = group.findViewById(R.id.pause_resume_option);
-        pauseOption.setOnClickListener((v) -> {
-            if (mOfflineItem == null) return;
-            if (mOfflineItem.state != OfflineItemState.PAUSED) {
-                downloadGlue.pauseDownload(mOfflineItem);
-            } else {
-                downloadGlue.resumeDownload(mOfflineItem, true);
-            }
-            finish();
-        });
-    }
-
-    /**
-     * Update the state of the UI to reflect the offline item.
-     * @param item The offline item.
-     */
-    private void updateVisualsForOfflineItem(OfflineItem item) {
-        mDownloadTitle.setText(item != null ? item.title : "");
-
-        boolean isPaused = item != null && item.state == OfflineItemState.PAUSED;
-
-        @DrawableRes
-        int iconId = isPaused ? R.drawable.ic_play_circle_outline_24dp
-                              : R.drawable.ic_pause_circle_outline_24dp;
-        @StringRes
-        int textId = isPaused ? org.chromium.chrome.R.string.download_notification_resume_button
-                              : org.chromium.chrome.R.string.download_notification_pause_button;
-
-        mPauseResumeIcon.setImageDrawable(
-                ApiCompatibilityUtils.getDrawable(getResources(), iconId));
-        mPauseResumeText.setText(textId);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/AboveTheFoldViewHolder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/AboveTheFoldViewHolder.java
deleted file mode 100644
index 95c30cf..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/AboveTheFoldViewHolder.java
+++ /dev/null
@@ -1,64 +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.touchless;
-
-import android.os.Bundle;
-import android.view.View;
-
-import androidx.annotation.IntDef;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Custom ViewHolder for the last tab button and site suggestions carousel. Handles restore focus
- * for those components.
- */
-public class AboveTheFoldViewHolder extends NewTabPageViewHolder {
-    private static final String FOCUS_TYPE_KEY = "FTK";
-
-    @IntDef({FocusType.UNKNOWN, FocusType.LAST_TAB_BUTTON, FocusType.SITE_SUGGESTIONS})
-    @Retention(RetentionPolicy.SOURCE)
-    private @interface FocusType {
-        int UNKNOWN = 0;
-        int LAST_TAB_BUTTON = 1;
-        int SITE_SUGGESTIONS = 2;
-    }
-
-    private final Map<Integer, FocusableComponent> mComponents;
-
-    public AboveTheFoldViewHolder(View itemView, FocusableComponent focusableOpenLastTab,
-            FocusableComponent focusableSiteSuggestions) {
-        super(itemView);
-        mComponents = new HashMap<>();
-        mComponents.put(FocusType.LAST_TAB_BUTTON, focusableOpenLastTab);
-        mComponents.put(FocusType.SITE_SUGGESTIONS, focusableSiteSuggestions);
-    }
-
-    @Override
-    public void requestFocusWithBundle(Bundle focusBundle) {
-        @FocusType
-        int type = focusBundle.getInt(FOCUS_TYPE_KEY);
-        if (mComponents.containsKey(type)) {
-            mComponents.get(type).requestFocus();
-        }
-    }
-
-    @Override
-    public void setOnFocusListener(Callback<Bundle> callback) {
-        for (Map.Entry<Integer, FocusableComponent> kv : mComponents.entrySet()) {
-            kv.getValue().setOnFocusListener(() -> {
-                Bundle focusBundle = new Bundle();
-                focusBundle.putInt(FOCUS_TYPE_KEY, kv.getKey());
-                callback.onResult(focusBundle);
-            });
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java
deleted file mode 100644
index 5781f7e..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java
+++ /dev/null
@@ -1,46 +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.touchless;
-
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-final class ContentSuggestionsViewBinder {
-    public static void bind(
-            PropertyModel model, SuggestionsRecyclerView view, PropertyKey propertyKey) {
-        if (TouchlessNewTabPageProperties.SCROLL_POSITION_CALLBACK == propertyKey) {
-            Callback<ScrollPositionInfo> callback =
-                    model.get(TouchlessNewTabPageProperties.SCROLL_POSITION_CALLBACK);
-            view.addOnScrollListener(new RecyclerView.OnScrollListener() {
-                @Override
-                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                    super.onScrolled(recyclerView, dx, dy);
-
-                    LinearLayoutManager layoutManager =
-                            ((LinearLayoutManager) recyclerView.getLayoutManager());
-                    int index = layoutManager.findFirstVisibleItemPosition();
-                    int offset = layoutManager.findViewByPosition(index).getTop();
-                    callback.onResult(new ScrollPositionInfo(index, offset));
-                }
-            });
-        } else if (TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK == propertyKey) {
-            // Ignored.
-        } else if (TouchlessNewTabPageProperties.INITIAL_FOCUS == propertyKey) {
-            // Ignored.
-        } else if (TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION == propertyKey) {
-            ScrollPositionInfo position =
-                    model.get(TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION);
-            view.getLinearLayoutManager().scrollToPositionWithOffset(
-                    position.index, position.offset);
-        } else {
-            assert false : "Unhandled property update";
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java
deleted file mode 100644
index 5c6bf17..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java
+++ /dev/null
@@ -1,110 +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.touchless;
-
-import android.content.Intent;
-import android.graphics.drawable.AnimationDrawable;
-import android.os.Bundle;
-import android.support.design.widget.CoordinatorLayout;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.SingleTabActivity;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
-import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.browser.tab.TabState;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.chrome.touchless.R;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.ui.UiUtils;
-import org.chromium.ui.base.PageTransition;
-
-/**
- * An Activity used to display the Dino Run game.
- */
-public class DinoActivity extends SingleTabActivity {
-    private View mSplashView;
-
-    @Override
-    protected void doLayoutInflation() {
-        super.doLayoutInflation();
-        mSplashView = LayoutInflater.from(this).inflate(R.layout.dino_splash_view, null);
-        mSplashView.addOnLayoutChangeListener(
-                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    TextView dinoImage = v.findViewById(R.id.dino_splash_text_image);
-                    AnimationDrawable dinoAnimation =
-                            (AnimationDrawable) dinoImage.getCompoundDrawables()[1];
-                    dinoAnimation.start();
-                });
-        ViewGroup coordinatorLayout = (ViewGroup) findViewById(R.id.coordinator);
-        CoordinatorLayout.LayoutParams layoutParams =
-                new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT,
-                        CoordinatorLayout.LayoutParams.MATCH_PARENT);
-        mSplashView.setLayoutParams(layoutParams);
-        coordinatorLayout.addView(mSplashView);
-    }
-
-    @Override
-    public void finishNativeInitialization() {
-        initializeCompositorContent(new LayoutManager(getCompositorViewHolder()), null /* urlBar */,
-                (ViewGroup) findViewById(android.R.id.content), null /* controlContainer */);
-        getFullscreenManager().setTab(getActivityTab());
-        super.finishNativeInitialization();
-    }
-
-    @Override
-    protected Tab createTab() {
-        Tab tab = super.createTab();
-        LoadUrlParams loadUrlParams = new LoadUrlParams(UrlConstants.CHROME_DINO_URL);
-        loadUrlParams.setHasUserGesture(true);
-        loadUrlParams.setTransitionType(PageTransition.LINK | PageTransition.FROM_API);
-        tab.loadUrl(loadUrlParams);
-        tab.addObserver(new EmptyTabObserver() {
-            @Override
-            public void onPageLoadFinished(Tab tab, String url) {
-                UiUtils.removeViewFromParent(mSplashView);
-            }
-        });
-        return tab;
-    }
-
-    @Override
-    public void onNewIntentWithNative(Intent intent) {}
-
-    @Override
-    public @ChromeActivity.ActivityType int getActivityType() {
-        return ChromeActivity.ActivityType.DINO;
-    }
-
-    @Override
-    protected void initializeToolbar() {}
-
-    @Override
-    public boolean supportsFindInPage() {
-        return false;
-    }
-
-    @Override
-    protected ChromeFullscreenManager createFullscreenManager() {
-        return new ChromeFullscreenManager(this, ChromeFullscreenManager.ControlsPosition.NONE);
-    }
-
-    @Override
-    protected TabDelegateFactory createTabDelegateFactory() {
-        return new NoTouchTabDelegateFactory(
-                this, getFullscreenManager().getBrowserVisibilityDelegate());
-    }
-
-    @Override
-    protected TabState restoreTabState(Bundle savedInstanceState, int tabId) {
-        return null;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/FocusableComponent.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/FocusableComponent.java
deleted file mode 100644
index 81e1830..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/FocusableComponent.java
+++ /dev/null
@@ -1,20 +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.touchless;
-
-/**
- * Mediators for focusable UI components can implement this to participate in focus save/restore for
- * a page.
- */
-public interface FocusableComponent {
-    /** Signals that the component should try to focus itself as soon as possible. */
-    void requestFocus();
-
-    /**
-     * Sets a single callback to be invoked when the component is focused. Calling this multiple
-     * times will override the previous listeners.
-     */
-    void setOnFocusListener(Runnable onFocus);
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
deleted file mode 100644
index 4bd630f..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
+++ /dev/null
@@ -1,289 +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.
-
-package org.chromium.chrome.browser.touchless;
-
-import static org.chromium.chrome.browser.util.UrlConstants.NTP_URL;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.view.ViewGroup;
-
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.ChromeInactivityTracker;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
-import org.chromium.chrome.browser.IntentHandler.TabOpenType;
-import org.chromium.chrome.browser.SingleTabActivity;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
-import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.browser.tab.TabRedirectHandler;
-import org.chromium.chrome.browser.tab.TabState;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.common.Referrer;
-import org.chromium.ui.base.PageTransition;
-
-/**
- * An Activity used to display WebContents on devices that don't support touch.
- */
-public class NoTouchActivity extends SingleTabActivity {
-    public static final String DINOSAUR_GAME_INTENT =
-            "org.chromium.chrome.browser.touchless.DinoActivity";
-
-    @VisibleForTesting
-    static final String LAST_BACKGROUNDED_TIME_MS_PREF = "NoTouchActivity.BackgroundTimeMs";
-
-    // Time at which an intent was received and handled.
-    private long mIntentHandlingTimeMs;
-
-    /** The class that finishes this activity after a timeout. */
-    private ChromeInactivityTracker mInactivityTracker;
-
-    /** Tab observer that tracks media state. */
-    private TouchlessTabObserver mTabObserver;
-
-    /**
-     * Internal class which performs the intent handling operations delegated by IntentHandler.
-     */
-    private class InternalIntentDelegate implements IntentHandler.IntentHandlerDelegate {
-        /**
-         * Processes a url view intent.
-         *
-         * @param url The url from the intent.
-         */
-        @Override
-        public void processUrlViewIntent(String url, String referer, String headers,
-                @TabOpenType int tabOpenType, String externalAppId, int tabIdToBringToFront,
-                boolean hasUserGesture, Intent intent) {
-            // TODO(mthiesse): ChromeTabbedActivity records a user Action here, we should do the
-            // same.
-            assert getActivityTab() != null;
-
-            switch (tabOpenType) {
-                case TabOpenType.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB:
-                    if (getActivityTab().getUrl().contentEquals(url)) break;
-                    // fall through
-                case TabOpenType.REUSE_APP_ID_MATCHING_TAB_ELSE_NEW_TAB: // fall through
-                case TabOpenType.OPEN_NEW_TAB: // fall through
-                    InterceptNavigationDelegateImpl delegate =
-                            InterceptNavigationDelegateImpl.get(getActivityTab());
-                    if (delegate != null && delegate.shouldIgnoreNewTab(url, false)) return;
-                    // fall through
-                case TabOpenType.BRING_TAB_TO_FRONT: // fall through
-                case TabOpenType.CLOBBER_CURRENT_TAB:
-                    // TODO(mthiesse): For now, let's just clobber current tab always. Are the other
-                    // tab open types meaningful when we only have a single tab?
-
-                    boolean stopped = ApplicationStatus.getStateForActivity(NoTouchActivity.this)
-                            == ActivityState.STOPPED;
-
-                    // When we get a view intent while stopped, create a new tab to reset history
-                    // state so that back returns you to the sender.
-                    if (tabOpenType != TabOpenType.BRING_TAB_TO_FRONT && stopped) {
-                        createAndShowTab();
-                    }
-                    Tab currentTab = getActivityTab();
-                    TabRedirectHandler.from(currentTab).updateIntent(intent);
-                    int transitionType = PageTransition.LINK | PageTransition.FROM_API;
-                    LoadUrlParams loadUrlParams = new LoadUrlParams(url);
-                    loadUrlParams.setIntentReceivedTimestamp(mIntentHandlingTimeMs);
-                    loadUrlParams.setHasUserGesture(hasUserGesture);
-                    loadUrlParams.setTransitionType(
-                            IntentHandler.getTransitionTypeFromIntent(intent, transitionType));
-                    if (referer != null) {
-                        loadUrlParams.setReferrer(new Referrer(
-                                referer, IntentHandler.getReferrerPolicyFromIntent(intent)));
-                    }
-                    currentTab.loadUrl(loadUrlParams);
-                    break;
-                case TabOpenType.OPEN_NEW_INCOGNITO_TAB:
-                    // Incognito is unsupported for this Activity.
-                    assert false;
-                    break;
-                default:
-                    assert false : "Unknown TabOpenType: " + tabOpenType;
-                    break;
-            }
-        }
-
-        @Override
-        public void processWebSearchIntent(String query) {
-            assert false;
-        }
-    }
-
-    @Override
-    public void finishNativeInitialization() {
-        initializeCompositorContent(new LayoutManager(getCompositorViewHolder()), null /* urlBar */,
-                (ViewGroup) findViewById(android.R.id.content), null /* controlContainer */);
-
-        getFullscreenManager().setTab(getActivityTab());
-
-        super.finishNativeInitialization();
-    }
-
-    @Override
-    public void initializeState() {
-        mInactivityTracker = new ChromeInactivityTracker(
-                LAST_BACKGROUNDED_TIME_MS_PREF, this.getLifecycleDispatcher());
-        boolean launchNtpDueToInactivity = shouldForceNTPDueToInactivity(null);
-
-        // SingleTabActivity#initializeState creates a tab based on #getSavedInstanceState(), so if
-        // we need to clear it due to inactivity, we should do it before calling
-        // super#initializeState.
-        if (launchNtpDueToInactivity) resetSavedInstanceState();
-
-        ((TouchlessTabCreator) getTabCreator(false))
-                .setTabModel(getTabModelSelector().getModel(false));
-
-        super.initializeState();
-
-        // By this point if we were going to restore a URL from savedInstanceState we would already
-        // have done so.
-        if (getActivityTab().getUrl().isEmpty()) {
-            boolean intentWithEffect = false;
-            Intent intent = getIntent();
-            mIntentHandlingTimeMs = SystemClock.uptimeMillis();
-            if (!launchNtpDueToInactivity && intent != null) {
-                // Treat Dino intent action like a url request for chrome://dino
-                if (DINOSAUR_GAME_INTENT.equals(intent.getComponent().getClassName())) {
-                    intent.setData(Uri.parse(UrlConstants.CHROME_DINO_URL));
-                }
-
-                if (!mIntentHandler.shouldIgnoreIntent(intent)) {
-                    intentWithEffect = mIntentHandler.onNewIntent(intent);
-                }
-            }
-            if (!intentWithEffect) getTabCreator(false).launchNTP();
-        }
-        resetSavedInstanceState();
-    }
-
-    private boolean shouldForceNTPDueToInactivity(Intent intent) {
-        if (intent != null) {
-            String intentData = intent.getDataString();
-            if (intentData != null && !intentData.isEmpty()) return false;
-        }
-        if (mInactivityTracker == null) return false;
-        if (mTabObserver == null) return false;
-
-        return !mTabObserver.isPlayingMedia() && mInactivityTracker.inactivityThresholdPassed();
-    }
-
-    @Override
-    public void onNewIntent(Intent intent) {
-        mIntentHandlingTimeMs = SystemClock.uptimeMillis();
-
-        if (intent.getComponent() != null
-                && DINOSAUR_GAME_INTENT.equals(intent.getComponent().getClassName())) {
-            intent.setData(Uri.parse(UrlConstants.CHROME_DINO_URL));
-        }
-
-        super.onNewIntent(intent);
-    }
-
-    @Override
-    public void onNewIntentWithNative(Intent intent) {
-        if (shouldForceNTPDueToInactivity(intent)) {
-            if (!mIntentHandler.shouldIgnoreIntent(intent)) {
-                if (!NTP_URL.equals(getActivityTab().getUrl())) {
-                    intent.setData(Uri.parse(NTP_URL));
-                }
-            }
-        }
-        super.onNewIntentWithNative(intent);
-    }
-
-    @Override
-    protected IntentHandlerDelegate createIntentHandlerDelegate() {
-        return new InternalIntentDelegate();
-    }
-
-    @Override
-    public @ChromeActivity.ActivityType int getActivityType() {
-        return ChromeActivity.ActivityType.NO_TOUCH;
-    }
-
-    @Override
-    protected void initializeToolbar() {}
-
-    /**
-     * @return  Whether this activity supports the find in page page
-     */
-    @Override
-    public boolean supportsFindInPage() {
-        return false;
-    }
-
-    @Override
-    protected ChromeFullscreenManager createFullscreenManager() {
-        return new ChromeFullscreenManager(this, ChromeFullscreenManager.ControlsPosition.NONE);
-    }
-
-    @Override
-    protected TabDelegateFactory createTabDelegateFactory() {
-        return new NoTouchTabDelegateFactory(
-                this, getFullscreenManager().getBrowserVisibilityDelegate());
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        saveTabState(outState);
-    }
-
-    private void saveTabState(Bundle outState) {
-        Tab tab = getActivityTab();
-        if (tab == null || tab.getUrl() == null || tab.getUrl().isEmpty()) return;
-        if (TabState.saveState(outState, TabState.from(tab))) {
-            outState.putInt(BUNDLE_TAB_ID, tab.getId());
-        }
-    }
-
-    @Override
-    protected Tab createTab() {
-        Tab tab = super.createTab();
-        mTabObserver = new TouchlessTabObserver();
-        tab.addObserver(mTabObserver);
-        return tab;
-    }
-
-    @Override
-    protected TabState restoreTabState(Bundle savedInstanceState, int tabId) {
-        return TabState.restoreTabState(savedInstanceState);
-    }
-
-    @Override
-    public void performPreInflationStartup() {
-        super.performPreInflationStartup();
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        ChromePreferenceManager.getInstance().incrementInt(
-                ChromePreferenceManager.TOUCHLESS_BROWSING_SESSION_COUNT);
-    }
-
-    @Override
-    public void onStopWithNative() {
-        super.onStopWithNative();
-        getFullscreenManager().exitPersistentFullscreenMode();
-    }
-
-    @Override
-    protected TabCreator createNormalTabCreator() {
-        return new TouchlessTabCreator(this, getWindowAndroid(), false /* incognito */);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchTabDelegateFactory.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchTabDelegateFactory.java
deleted file mode 100644
index 73bc628..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchTabDelegateFactory.java
+++ /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.
-
-package org.chromium.chrome.browser.touchless;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab_activity_glue.TabDelegateFactoryImpl;
-
-/**
- * TabDelegateFactory for all touchless activities.
- */
-public class NoTouchTabDelegateFactory extends TabDelegateFactoryImpl {
-    private final BrowserControlsVisibilityDelegate mDelegate;
-
-    public NoTouchTabDelegateFactory(
-            ChromeActivity activity, BrowserControlsVisibilityDelegate delegate) {
-        super(activity);
-        mDelegate = delegate;
-    }
-
-    @Override
-    public BrowserControlsVisibilityDelegate createBrowserControlsVisibilityDelegate(Tab tab) {
-        return mDelegate;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabCoordinator.java
deleted file mode 100644
index 1e36fa48..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabCoordinator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.touchless;
-
-import android.content.Context;
-
-import org.chromium.chrome.browser.native_page.NativePageHost;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-
-/**
- * Provides data for the view and coordinates interactivity.
- */
-class OpenLastTabCoordinator {
-    private final OpenLastTabMediator mMediator;
-
-    OpenLastTabCoordinator(Context context, Profile profile, NativePageHost nativePageHost,
-            OpenLastTabView view, TouchlessLayoutManager layoutManager) {
-        PropertyModel model = new PropertyModel.Builder(OpenLastTabProperties.ALL_KEYS)
-                                      .with(OpenLastTabProperties.ASYNC_FOCUS_DELEGATE,
-                                              layoutManager.createCallbackToSetViewToFocus())
-                                      .build();
-        PropertyModelChangeProcessor.create(model, view, OpenLastTabViewBinder::bind);
-
-        mMediator = new OpenLastTabMediator(context, profile, nativePageHost, model, view);
-    }
-
-    public void destroy() {
-        mMediator.destroy();
-    }
-    public FocusableComponent getFocusableComponent() {
-        return mMediator;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java
deleted file mode 100644
index 6a95bd41..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java
+++ /dev/null
@@ -1,287 +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.touchless;
-
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-import static android.text.format.DateUtils.getRelativeTimeSpanString;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.graphics.Bitmap;
-
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.favicon.LargeIconBridge;
-import org.chromium.chrome.browser.history.BrowsingHistoryBridge;
-import org.chromium.chrome.browser.history.HistoryItem;
-import org.chromium.chrome.browser.history.HistoryProvider;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.native_page.ContextMenuManager.ContextMenuItemId;
-import org.chromium.chrome.browser.native_page.NativePageFactory;
-import org.chromium.chrome.browser.native_page.NativePageHost;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabSelectionType;
-import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.browser.widget.RoundedIconGenerator;
-import org.chromium.chrome.touchless.R;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.ui.base.PageTransition;
-import org.chromium.ui.modelutil.PropertyModel;
-
-import java.util.List;
-
-/**
- * Mediator used to look for history events and update the model accordingly.
- */
-// TODO(crbug.com/948858): Add unit tests for this behavior.
-class OpenLastTabMediator extends EmptyTabObserver
-        implements HistoryProvider.BrowsingHistoryObserver, FocusableComponent {
-    private static final String LAST_TAB_URL = "TOUCHLESS_LAST_TAB_URL";
-
-    private final Context mContext;
-    private final Profile mProfile;
-    private final NativePageHost mNativePageHost;
-
-    private final PropertyModel mModel;
-
-    private BrowsingHistoryBridge mHistoryBridge;
-    private final RoundedIconGenerator mIconGenerator;
-    private final LargeIconBridge mIconBridge;
-
-    private HistoryItem mHistoryItem;
-    private List<HistoryItem> mHistoryResult;
-    private boolean mPreferencesRead;
-    private String mLastTabUrl;
-
-    /**
-     * Sets up an observer on the tab to track the last tab that was opened. The purpose of this is
-     * to filter out history results that come from other activities, like PWAs.
-     * @param activity the activity to lookup shared prefs with.
-     * @param activityTabProvider the source of the tab navigation events.
-     * @return a new observer that can be destroyed on shutdown.
-     */
-    public static ActivityTabProvider.ActivityTabTabObserver createActivityScopedObserver(
-            Activity activity, ActivityTabProvider activityTabProvider) {
-        return new ActivityTabProvider.ActivityTabTabObserver(activityTabProvider) {
-            @Override
-            public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) {
-                String url = tab.getUrl();
-                if (navigation.isInMainFrame() && !NativePageFactory.isNativePageUrl(url, false)) {
-                    PostTask.postTask(TaskTraits.USER_VISIBLE, () -> {
-                        SharedPreferences prefs = getSharedPreferences(activity);
-                        prefs.edit()
-                                .putString(OpenLastTabMediator.LAST_TAB_URL, tab.getUrl())
-                                .apply();
-                    });
-                }
-            }
-        };
-    }
-
-    OpenLastTabMediator(Context context, Profile profile, NativePageHost nativePageHost,
-            PropertyModel model, OpenLastTabView view) {
-        mModel = model;
-        mContext = context;
-        mProfile = profile;
-        mNativePageHost = nativePageHost;
-
-        mHistoryBridge = new BrowsingHistoryBridge(false);
-        mHistoryBridge.setObserver(this);
-        mNativePageHost.getActiveTab().addObserver(this);
-
-        mIconGenerator =
-                ViewUtils.createDefaultRoundedIconGenerator(mContext.getResources(), false);
-        mIconBridge = new LargeIconBridge(mProfile);
-
-        readPreferences();
-
-        // TODO(wylieb):Investigate adding an item limit to the API.
-        // Query the history for everything (no API exists to only query for the most recent).
-        refreshHistoryData();
-    }
-
-    private SharedPreferences getSharedPreferences() {
-        return getSharedPreferences(mNativePageHost.getActiveTab().getActivity());
-    }
-
-    private static SharedPreferences getSharedPreferences(Activity activity) {
-        return activity.getPreferences(Context.MODE_PRIVATE);
-    }
-
-    private void readPreferences() {
-        PostTask.postTask(TaskTraits.USER_VISIBLE, () -> {
-            // Check if this is a first launch of Chrome.
-            SharedPreferences prefs = getSharedPreferences();
-            mLastTabUrl = prefs.getString(LAST_TAB_URL, null);
-            PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> {
-                mPreferencesRead = true;
-                updateModel();
-            });
-        });
-    }
-
-    void destroy() {
-        if (mHistoryBridge != null) {
-            mHistoryBridge.destroy();
-            mHistoryBridge = null;
-        }
-        mNativePageHost.getActiveTab().removeObserver(this);
-    }
-
-    void refreshHistoryData() {
-        mHistoryBridge.queryHistory("");
-    }
-
-    @Override
-    public void onShown(Tab tab, @TabSelectionType int type) {
-        // Query the history as it may have been cleared while the app was hidden. This could happen
-        // via the Android settings.
-        refreshHistoryData();
-    }
-
-    @Override
-    public void requestFocus() {
-        mModel.set(OpenLastTabProperties.SHOULD_FOCUS_VIEW, true);
-    }
-
-    @Override
-    public void setOnFocusListener(Runnable listener) {
-        mModel.set(OpenLastTabProperties.ON_FOCUS_CALLBACK, listener);
-    }
-
-    @Override
-    public void onQueryHistoryComplete(List<HistoryItem> items, boolean hasMorePotentialMatches) {
-        mHistoryItem = null;
-        mHistoryResult = items;
-        // Ignore |hasMorePotentialMatches|, it's possible a user with a lot of PWA  history does
-        // not get a match in the first query. In this case, we'll simply not show the last tab
-        // button. It probably isn't really recent anyways.
-
-        if (mPreferencesRead) {
-            updateModel();
-        }
-    }
-
-    // updateModel is only called after preferences are read. It populates model with data from
-    // mHistoryItem.
-    private void updateModel() {
-        if (mHistoryResult != null) {
-            for (HistoryItem item : mHistoryResult) {
-                if (item.getUrl().equals(mLastTabUrl)) {
-                    mHistoryItem = item;
-                    break;
-                }
-            }
-            mHistoryResult = null;
-        }
-
-        if (mHistoryItem == null) {
-            // Consider the case where the history has nothing in it to be a failure.
-            mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_LOAD_SUCCESS, false);
-            return;
-        }
-
-        String title = UrlUtilities.getDomainAndRegistry(mHistoryItem.getUrl(), false);
-        // Default the timestamp to happening just now. If it happened over a minute ago, calculate
-        // and set the relative timestamp string.
-        String timestamp = mContext.getResources().getString(R.string.open_last_tab_just_now);
-        long now = System.currentTimeMillis();
-        if (now - mHistoryItem.getTimestamp() > MINUTE_IN_MILLIS) {
-            timestamp =
-                    getRelativeTimeSpanString(mHistoryItem.getTimestamp(), now, MINUTE_IN_MILLIS)
-                            .toString();
-        }
-
-        mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_TITLE, title);
-        mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_TIMESTAMP, timestamp);
-        boolean willReturnIcon = mIconBridge.getLargeIconForUrl(mHistoryItem.getUrl(),
-                mContext.getResources().getDimensionPixelSize(R.dimen.open_last_tab_icon_size),
-                (icon, fallbackColor, isFallbackColorDefault, iconType) -> {
-                    setAndShowButton(mHistoryItem.getUrl(), icon, fallbackColor, title);
-                });
-
-        // False if icon bridge won't call us back.
-        if (!willReturnIcon) {
-            setAndShowButton(mHistoryItem.getUrl(), null, R.color.default_icon_color, title);
-        }
-        mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_LOAD_SUCCESS, true);
-    }
-
-    @Override
-    public void onHistoryDeleted() {
-        refreshHistoryData();
-    }
-
-    @Override
-    public void hasOtherFormsOfBrowsingData(boolean hasOtherForms) {}
-
-    private void setAndShowButton(String url, Bitmap icon, int fallbackColor, String title) {
-        mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_ON_CLICK_LISTENER, view -> {
-            mNativePageHost.loadUrl(new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK),
-                    /* Explore page is never off the record. */ false);
-        });
-
-        if (icon == null) {
-            mIconGenerator.setBackgroundColor(fallbackColor);
-            icon = mIconGenerator.generateIconForUrl(url);
-        }
-        mModel.set(OpenLastTabProperties.OPEN_LAST_TAB_FAVICON, icon);
-
-        final Bitmap shortcutIcon = icon;
-        TouchlessContextMenuManager.Delegate delegate =
-                new TouchlessContextMenuManager.EmptyDelegate() {
-                    @Override
-                    public boolean isItemSupported(
-                            @ContextMenuManager.ContextMenuItemId int menuItemId) {
-                        return menuItemId == ContextMenuItemId.SEARCH
-                                || menuItemId == ContextMenuManager.ContextMenuItemId.REMOVE;
-                    }
-
-                    @Override
-                    public void removeItem() {
-                        PostTask.postTask(TaskTraits.USER_VISIBLE, () -> {
-                            SharedPreferences prefs = getSharedPreferences();
-                            prefs.edit().remove(LAST_TAB_URL).apply();
-                        });
-                        // Don't actually remove the element from history db. This is fine since
-                        // we're tracking it in the pref, the open last tab button will not show it.
-                        // If this history item is backed by 2+ rows a history deletion could
-                        // trigger a clear and suppression of suggested articles, see
-                        // https://crbug.com/982973.
-                        mHistoryItem = null;
-                        mLastTabUrl = null;
-                        updateModel();
-                    }
-
-                    @Override
-                    public String getUrl() {
-                        return url;
-                    }
-
-                    @Override
-                    public String getContextMenuTitle() {
-                        return title;
-                    }
-
-                    @Override
-                    public String getTitle() {
-                        return title;
-                    }
-
-                    @Override
-                    public Bitmap getIconBitmap() {
-                        return shortcutIcon;
-                    }
-                };
-        mModel.set(OpenLastTabProperties.CONTEXT_MENU_DELEGATE, delegate);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabProperties.java
deleted file mode 100644
index 6822398..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabProperties.java
+++ /dev/null
@@ -1,51 +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.touchless;
-
-import android.graphics.Bitmap;
-import android.view.View;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-class OpenLastTabProperties {
-    public static final PropertyModel
-            .WritableObjectPropertyKey<View.OnClickListener> OPEN_LAST_TAB_ON_CLICK_LISTENER =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyModel.WritableObjectPropertyKey<Bitmap> OPEN_LAST_TAB_FAVICON =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyModel.WritableObjectPropertyKey<String> OPEN_LAST_TAB_TITLE =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyModel.WritableObjectPropertyKey<String> OPEN_LAST_TAB_TIMESTAMP =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyModel.WritableBooleanPropertyKey OPEN_LAST_TAB_LOAD_SUCCESS =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel.WritableObjectPropertyKey<Runnable> ON_FOCUS_CALLBACK =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyModel.WritableBooleanPropertyKey SHOULD_FOCUS_VIEW =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel
-            .ReadableObjectPropertyKey<Callback<View>> ASYNC_FOCUS_DELEGATE =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    public static final PropertyModel
-            .WritableObjectPropertyKey<ContextMenuManager.Delegate> CONTEXT_MENU_DELEGATE =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    // Property keys for the open last tab button.
-    public static final PropertyKey[] ALL_KEYS = {OPEN_LAST_TAB_ON_CLICK_LISTENER,
-            OPEN_LAST_TAB_FAVICON, OPEN_LAST_TAB_TITLE, OPEN_LAST_TAB_TIMESTAMP,
-            OPEN_LAST_TAB_LOAD_SUCCESS, ON_FOCUS_CALLBACK, SHOULD_FOCUS_VIEW, ASYNC_FOCUS_DELEGATE,
-            CONTEXT_MENU_DELEGATE};
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
deleted file mode 100644
index 50196fa3..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java
+++ /dev/null
@@ -1,87 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.touchless.R;
-
-/**
- * View for the button to open the last tab.
- */
-// TODO(crbug.com/948858): Add render tests for this view.
-public class OpenLastTabView extends LinearLayout {
-    private ImageView mIconView;
-    private TextView mTitleText;
-    private TextView mTimestampText;
-    private Callback<View> mAsyncFocusDelegate;
-
-    public OpenLastTabView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        LayoutInflater.from(context).inflate(R.layout.open_last_tab_button, this);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mIconView = findViewById(R.id.favicon);
-        mTitleText = findViewById(R.id.title);
-        mTimestampText = findViewById(R.id.timestamp);
-    }
-
-    void setLoadSuccess(boolean loadSuccess) {
-        setVisibility(loadSuccess ? View.VISIBLE : View.GONE);
-    }
-
-    void setOpenLastTabOnClickListener(OnClickListener onClickListener) {
-        setOnClickListener(onClickListener);
-    }
-
-    void setFavicon(Bitmap favicon) {
-        mIconView.setImageDrawable(new BitmapDrawable(getContext().getResources(), favicon));
-    }
-
-    void setTitle(String title) {
-        mTitleText.setText(title);
-    }
-
-    void setTimestamp(String timestamp) {
-        mTimestampText.setText(timestamp);
-    }
-
-    void setOnFocusCallback(Runnable callback) {
-        setOnFocusChangeListener((View view, boolean hasFocus) -> {
-            if (hasFocus) {
-                callback.run();
-            }
-        });
-    }
-
-    void triggerRequestFocus() {
-        if (mAsyncFocusDelegate != null) {
-            mAsyncFocusDelegate.onResult(this);
-        }
-    }
-
-    void setAsyncFocusDelegate(Callback<View> asyncFocusDelegate) {
-        mAsyncFocusDelegate = asyncFocusDelegate;
-    }
-
-    void setContextMenuDelegate(ContextMenuManager.Delegate delegate) {
-        ContextMenuManager.registerViewForTouchlessContextMenu(this, delegate);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabViewBinder.java
deleted file mode 100644
index 7f32e03f..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabViewBinder.java
+++ /dev/null
@@ -1,39 +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.touchless;
-
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Binder between the OpenLastTabModel and OpenLastTabButton.
- */
-class OpenLastTabViewBinder {
-    public static void bind(PropertyModel model, OpenLastTabView view, PropertyKey propertyKey) {
-        if (propertyKey == OpenLastTabProperties.OPEN_LAST_TAB_ON_CLICK_LISTENER) {
-            view.setOpenLastTabOnClickListener(
-                    model.get(OpenLastTabProperties.OPEN_LAST_TAB_ON_CLICK_LISTENER));
-        } else if (propertyKey == OpenLastTabProperties.OPEN_LAST_TAB_FAVICON) {
-            view.setFavicon(model.get(OpenLastTabProperties.OPEN_LAST_TAB_FAVICON));
-        } else if (propertyKey == OpenLastTabProperties.OPEN_LAST_TAB_TITLE) {
-            view.setTitle(model.get(OpenLastTabProperties.OPEN_LAST_TAB_TITLE));
-        } else if (propertyKey == OpenLastTabProperties.OPEN_LAST_TAB_TIMESTAMP) {
-            view.setTimestamp(model.get(OpenLastTabProperties.OPEN_LAST_TAB_TIMESTAMP));
-        } else if (propertyKey == OpenLastTabProperties.OPEN_LAST_TAB_LOAD_SUCCESS) {
-            view.setLoadSuccess(model.get(OpenLastTabProperties.OPEN_LAST_TAB_LOAD_SUCCESS));
-        } else if (propertyKey == OpenLastTabProperties.ON_FOCUS_CALLBACK) {
-            view.setOnFocusCallback(model.get(OpenLastTabProperties.ON_FOCUS_CALLBACK));
-        } else if (propertyKey == OpenLastTabProperties.SHOULD_FOCUS_VIEW) {
-            if (model.get(OpenLastTabProperties.SHOULD_FOCUS_VIEW)) view.triggerRequestFocus();
-            model.set(OpenLastTabProperties.SHOULD_FOCUS_VIEW, false);
-        } else if (propertyKey == OpenLastTabProperties.ASYNC_FOCUS_DELEGATE) {
-            view.setAsyncFocusDelegate(model.get(OpenLastTabProperties.ASYNC_FOCUS_DELEGATE));
-        } else if (propertyKey == OpenLastTabProperties.CONTEXT_MENU_DELEGATE) {
-            view.setContextMenuDelegate(model.get(OpenLastTabProperties.CONTEXT_MENU_DELEGATE));
-        } else {
-            assert false : "Unhandled property detected.";
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/QuantizedSizeIconView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/QuantizedSizeIconView.java
deleted file mode 100644
index 4d995b6..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/QuantizedSizeIconView.java
+++ /dev/null
@@ -1,80 +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.touchless;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.chrome.touchless.R;
-
-/** ImageView that keeps its image square and limited to a static set of sizes. */
-public class QuantizedSizeIconView extends ImageView {
-    private int[] mSizes;
-
-    public QuantizedSizeIconView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        Resources res = context.getResources();
-        TypedArray styledAttrs =
-                context.obtainStyledAttributes(attrs, R.styleable.QuantizedSizeIconView);
-        // Defaults are MAX_VALUE, in other words do not quantize.
-        mSizes = new int[] {styledAttrs.getDimensionPixelOffset(
-                                    R.styleable.QuantizedSizeIconView_largeSize, Integer.MAX_VALUE),
-                styledAttrs.getDimensionPixelOffset(
-                        R.styleable.QuantizedSizeIconView_smallSize, Integer.MAX_VALUE)};
-        styledAttrs.recycle();
-    }
-
-    public void setSizes(int[] sizes) {
-        mSizes = sizes;
-    }
-
-    @Override
-    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
-
-        int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
-        int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
-
-        if (widthSpecMode == MeasureSpec.UNSPECIFIED && heightSpecMode != MeasureSpec.UNSPECIFIED) {
-            measuredWidth = measuredHeight;
-        } else if (heightSpecMode == MeasureSpec.UNSPECIFIED
-                && widthSpecMode != MeasureSpec.UNSPECIFIED) {
-            measuredHeight = measuredWidth;
-        } else if (heightSpecMode == MeasureSpec.UNSPECIFIED) {
-            // If both are UNSPECIFIED, take up as much room as possible.
-            measuredWidth = Integer.MAX_VALUE;
-            measuredHeight = Integer.MAX_VALUE;
-        } else if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.EXACTLY) {
-            measuredWidth = Math.min(measuredHeight, measuredWidth);
-        } else if (heightSpecMode == MeasureSpec.AT_MOST && widthSpecMode == MeasureSpec.EXACTLY) {
-            measuredHeight = Math.min(measuredWidth, measuredHeight);
-        } else if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
-            int minimumDimension = Math.min(measuredHeight, measuredWidth);
-            measuredWidth = minimumDimension;
-            measuredHeight = minimumDimension;
-        }
-        // else keep values from the MeasureSpec because both modes are EXACTLY.
-
-        measuredHeight = quantizeDimension(measuredHeight);
-        measuredWidth = quantizeDimension(measuredWidth);
-
-        setMeasuredDimension(measuredWidth, measuredHeight);
-    }
-
-    private int quantizeDimension(int dimension) {
-        for (int sizeOption : mSizes) {
-            if (sizeOption <= dimension) {
-                return sizeOption;
-            }
-        }
-        return dimension;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ScrollPositionInfo.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ScrollPositionInfo.java
deleted file mode 100644
index d495992..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ScrollPositionInfo.java
+++ /dev/null
@@ -1,65 +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.touchless;
-
-import android.support.v7.widget.RecyclerView;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Holds onto fields that represent the scroll position on a page, and the ability to be round
- * tripped through a String.
- */
-public class ScrollPositionInfo {
-    private static final String INDEX_KEY = "index";
-    private static final String OFFSET_KEY = "offset";
-
-    public final int index;
-    public final int offset;
-
-    public ScrollPositionInfo(int index, int offset) {
-        this.index = index;
-        this.offset = offset;
-    }
-
-    /**
-     * Turns the current ScrollPosition object into a String that can be more easily stored and
-     * restored. If anything goes wrong then an empty string is returned instead.
-     *
-     * @return The values encoded into a String.
-     */
-    public String serialize() {
-        try {
-            JSONObject json = new JSONObject();
-            json.put(INDEX_KEY, index);
-            json.put(OFFSET_KEY, offset);
-            return json.toString();
-        } catch (JSONException e) {
-            return "";
-        }
-    }
-
-    /**
-     * Turns the given String into a ScrollPosition object. If anything goes wrong a default value
-     * ScrollPosition is returned that essentially means there was no scrolling yet.
-     *
-     * @param str The serialized form of a ScrollPosition.
-     * @return An instantiated ScrollPosition object.
-     */
-    public static ScrollPositionInfo deserialize(String str) {
-        if (str == null || str.isEmpty()) return newDefault();
-        try {
-            JSONObject json = new JSONObject(str);
-            return new ScrollPositionInfo(json.getInt(INDEX_KEY), json.getInt(OFFSET_KEY));
-        } catch (JSONException e) {
-            return newDefault();
-        }
-    }
-
-    private static ScrollPositionInfo newDefault() {
-        return new ScrollPositionInfo(RecyclerView.NO_POSITION, 0);
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java
deleted file mode 100644
index 969b06b..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java
+++ /dev/null
@@ -1,47 +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.touchless;
-
-import android.graphics.Bitmap;
-import android.text.TextUtils;
-
-import org.chromium.chrome.browser.suggestions.SiteSuggestion;
-import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * UI property-model based encapsulating class for important site suggestion data.
- */
-class SiteSuggestionModel {
-    static final PropertyModel.ReadableObjectPropertyKey<String> TITLE_KEY =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-    static final PropertyModel.ReadableObjectPropertyKey<String> URL_KEY =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-    static final PropertyModel.ReadableIntPropertyKey SOURCE_KEY =
-            new PropertyModel.ReadableIntPropertyKey();
-    static final PropertyModel.ReadableObjectPropertyKey<String> WHITELIST_ICON_PATH_KEY =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-    static final PropertyModel.WritableObjectPropertyKey<Bitmap> ICON_KEY =
-            new PropertyModel.WritableObjectPropertyKey<>();
-    static final PropertyModel.ReadableObjectPropertyKey<Bitmap> DEFAULT_ICON_KEY =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    static PropertyModel getSiteSuggestionModel(SiteSuggestion suggestion, Bitmap defaultIcon) {
-        String title = UrlUtilities.getDomainAndRegistry(suggestion.url, false);
-        if (TextUtils.isEmpty(title)) {
-            // Fallback to title.
-            title = suggestion.title;
-        }
-        return new PropertyModel
-                .Builder(TITLE_KEY, URL_KEY, ICON_KEY, SOURCE_KEY, WHITELIST_ICON_PATH_KEY,
-                        DEFAULT_ICON_KEY)
-                .with(TITLE_KEY, title)
-                .with(URL_KEY, suggestion.url)
-                .with(SOURCE_KEY, suggestion.source)
-                .with(WHITELIST_ICON_PATH_KEY, suggestion.whitelistIconPath)
-                .with(DEFAULT_ICON_KEY, defaultIcon)
-                .build();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
deleted file mode 100644
index dc467ad7..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
+++ /dev/null
@@ -1,298 +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.touchless;
-
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.ASYNC_FOCUS_DELEGATE;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.CURRENT_INDEX_KEY;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.INITIAL_INDEX_KEY;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.ITEM_COUNT_KEY;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.ON_FOCUS_CALLBACK;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.REMOVAL_KEY;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.SHOULD_FOCUS_VIEW;
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.SUGGESTIONS_KEY;
-
-import android.graphics.Bitmap;
-import android.support.graphics.drawable.VectorDrawableCompat;
-import android.view.ContextMenu;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
-
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.native_page.ContextMenuManager.ContextMenuItemId;
-import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.ForwardingListObservable;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyObservable;
-import org.chromium.ui.modelutil.RecyclerViewAdapter;
-import org.chromium.ui.mojom.WindowOpenDisposition;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Recycler view adapter and view binder for Touchless Suggestions carousel.
- *
- * Allows for an almost-infinite side-scrolling carousel with snapping focus in the center if
- * there are 2 or more items; does not scroll if there is 1 or fewer items.
- *
- * Focus changes on containing items will cause the passed-in title view to change.
- */
-class SiteSuggestionsAdapter extends ForwardingListObservable<PropertyKey>
-        implements RecyclerViewAdapter.Delegate<
-                           SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder, PropertyKey>,
-                   PropertyObservable.PropertyObserver<PropertyKey> {
-    @IntDef({ViewType.ALL_APPS_TYPE, ViewType.SUGGESTION_TYPE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ViewType {
-        int ALL_APPS_TYPE = 0;
-        int SUGGESTION_TYPE = 1;
-    }
-
-    private class SiteSuggestionInteractionDelegate
-            implements TouchlessContextMenuManager.Delegate, View.OnCreateContextMenuListener {
-        private PropertyModel mSuggestion;
-
-        SiteSuggestionInteractionDelegate(PropertyModel model) {
-            mSuggestion = model;
-        }
-
-        @Override
-        public void onCreateContextMenu(
-                ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
-            mContextMenuManager.createContextMenu(menu, v, this);
-        }
-
-        @Override
-        public void openItem(int windowDisposition) {
-            mNavDelegate.navigateToSuggestionUrl(
-                    windowDisposition, mSuggestion.get(SiteSuggestionModel.URL_KEY));
-        }
-
-        @Override
-        public void removeItem() {
-            // Notify about removal.
-            mModel.set(REMOVAL_KEY, mSuggestion);
-            // Force-trigger rebind of current_index to update text.
-            onPropertyChanged(mModel, CURRENT_INDEX_KEY);
-        }
-
-        @Override
-        public String getUrl() {
-            return mSuggestion.get(SiteSuggestionModel.URL_KEY);
-        }
-
-        @Override
-        public String getContextMenuTitle() {
-            return mSuggestion.get(SiteSuggestionModel.TITLE_KEY);
-        }
-
-        @Override
-        public boolean isItemSupported(int menuItemId) {
-            return menuItemId == ContextMenuManager.ContextMenuItemId.SEARCH
-                    || menuItemId == ContextMenuManager.ContextMenuItemId.REMOVE;
-        }
-
-        @Override
-        public void onContextMenuCreated() {}
-
-        @Override
-        public String getTitle() {
-            return mSuggestion.get(SiteSuggestionModel.TITLE_KEY);
-        }
-
-        @Override
-        public Bitmap getIconBitmap() {
-            if (mSuggestion.get(SiteSuggestionModel.ICON_KEY) == null) {
-                return mSuggestion.get(SiteSuggestionModel.DEFAULT_ICON_KEY);
-            }
-            return mSuggestion.get(SiteSuggestionModel.ICON_KEY);
-        }
-    }
-
-    private PropertyModel mModel;
-    private SuggestionsNavigationDelegate mNavDelegate;
-    private ContextMenuManager mContextMenuManager;
-    private SiteSuggestionsLayoutManager mLayoutManager;
-    private TextView mTitleView;
-
-    /**
-     * @param model the main property model coming from {@link SiteSuggestionsCoordinator}.
-     * @param navigationDelegate delegate for navigation controls
-     * @param contextMenuManager handles context menu creation
-     * @param layoutManager the layout manager controlling this recyclerview and adapter
-     * @param titleView the view to update site title when focus changes.
-     */
-    SiteSuggestionsAdapter(PropertyModel model, SuggestionsNavigationDelegate navigationDelegate,
-            ContextMenuManager contextMenuManager, SiteSuggestionsLayoutManager layoutManager,
-            TextView titleView) {
-        mModel = model;
-        mNavDelegate = navigationDelegate;
-        mContextMenuManager = contextMenuManager;
-        mLayoutManager = layoutManager;
-        mTitleView = titleView;
-
-        mModel.get(SUGGESTIONS_KEY).addObserver(this);
-        mModel.addObserver(this);
-
-        // Initialize the titleView text.
-        onPropertyChanged(mModel, CURRENT_INDEX_KEY);
-    }
-
-    @Override
-    public int getItemCount() {
-        if (mModel.get(SUGGESTIONS_KEY).size() > 0) {
-            return Integer.MAX_VALUE;
-        }
-        return 1;
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        int itemCount = mModel.get(ITEM_COUNT_KEY);
-        if (itemCount == 1 || position % itemCount == 0) return ViewType.ALL_APPS_TYPE;
-        return ViewType.SUGGESTION_TYPE;
-    }
-
-    @Override
-    public void onBindViewHolder(SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder holder,
-            int position, PropertyKey payload) {
-        SiteSuggestionsTileView tile = (SiteSuggestionsTileView) holder.itemView;
-        // Updates focus change listener.
-        tile.setOnFocusChangeListener((View v, boolean hasFocus) -> {
-            if (hasFocus) {
-                mModel.set(CURRENT_INDEX_KEY, position);
-                if (mModel.get(ON_FOCUS_CALLBACK) != null) {
-                    mModel.get(ON_FOCUS_CALLBACK).run();
-                }
-            }
-        });
-
-        if (holder.getItemViewType() == ViewType.ALL_APPS_TYPE) {
-            tile.setIconDrawable(VectorDrawableCompat.create(tile.getResources(),
-                    R.drawable.ic_apps_blue_24dp, tile.getContext().getTheme()));
-            // If explore sites, clicks navigate to the Explore URL.
-            tile.setOnClickListener(
-                    (view)
-                            -> mNavDelegate.navigateToSuggestionUrl(
-                                    WindowOpenDisposition.CURRENT_TAB, UrlConstants.EXPLORE_URL));
-            ContextMenuManager.registerViewForTouchlessContextMenu(
-                    tile, new ContextMenuManager.EmptyDelegate() {
-                        @Override
-                        public boolean isItemSupported(@ContextMenuItemId int menuItemId) {
-                            return menuItemId == ContextMenuManager.ContextMenuItemId.SEARCH;
-                        }
-                    });
-            tile.setContentDescription(tile.getResources().getString(R.string.ntp_all_apps));
-        } else if (holder.getItemViewType() == ViewType.SUGGESTION_TYPE) {
-            // If site suggestion, attach context menu handler; clicks navigate to site url.
-            int itemCount = mModel.get(ITEM_COUNT_KEY);
-            // Subtract 1 from position % MAX_TILES to account for "all apps" taking up one space.
-            PropertyModel item = mModel.get(SUGGESTIONS_KEY).get((position % itemCount) - 1);
-            // Only update the icon for icon updates.
-            if (payload == SiteSuggestionModel.ICON_KEY) {
-                tile.updateIcon(item.get(SiteSuggestionModel.ICON_KEY),
-                        item.get(SiteSuggestionModel.DEFAULT_ICON_KEY));
-            } else {
-                tile.updateIcon(item.get(SiteSuggestionModel.ICON_KEY),
-                        item.get(SiteSuggestionModel.DEFAULT_ICON_KEY));
-
-                SiteSuggestionInteractionDelegate interactionDelegate =
-                        new SiteSuggestionInteractionDelegate(item);
-
-                tile.setOnClickListener(
-                        (View v)
-                                -> interactionDelegate.openItem(WindowOpenDisposition.CURRENT_TAB));
-
-                tile.setOnCreateContextMenuListener(interactionDelegate);
-                ContextMenuManager.registerViewForTouchlessContextMenu(tile, interactionDelegate);
-                tile.setContentDescription(item.get(SiteSuggestionModel.TITLE_KEY));
-            }
-        }
-    }
-
-    @Override
-    public void onPropertyChanged(
-            PropertyObservable<PropertyKey> source, @Nullable PropertyKey propertyKey) {
-        if (propertyKey == CURRENT_INDEX_KEY) {
-            // When the current index changes, we want to update the title.
-            int position = mModel.get(CURRENT_INDEX_KEY);
-            int itemCount = mModel.get(ITEM_COUNT_KEY);
-            if (itemCount == 1 || position % itemCount == 0) {
-                mTitleView.setText(R.string.ntp_all_apps);
-            } else {
-                mTitleView.setText(mModel.get(SUGGESTIONS_KEY)
-                                           .get(position % itemCount - 1)
-                                           .get(SiteSuggestionModel.TITLE_KEY));
-            }
-        } else if (propertyKey == SHOULD_FOCUS_VIEW && mModel.get(SHOULD_FOCUS_VIEW)
-                && mModel.get(ASYNC_FOCUS_DELEGATE) != null) {
-            mLayoutManager.focusCenterItem();
-            mModel.set(SHOULD_FOCUS_VIEW, false);
-        } else if (propertyKey == INITIAL_INDEX_KEY) {
-            mLayoutManager.scrollToPosition(mModel.get(INITIAL_INDEX_KEY));
-        }
-    }
-
-    @Override
-    public void notifyItemRangeInserted(int index, int count) {
-        if (mModel.get(SUGGESTIONS_KEY).size() == 1) {
-            // When we just added something for the first time,
-            // we would change from non-scrolling to infinite-scrolling.
-            super.notifyItemRangeInserted(1, Integer.MAX_VALUE - 1);
-        } else {
-            // Otherwise, rebind the visible spectrum.
-            // Account for edge conditions so we don't crash in the impossible case.
-            int start = mLayoutManager.findFirstVisibleItemPosition();
-            int itemCount = mModel.get(ITEM_COUNT_KEY);
-            int newCount = Integer.MAX_VALUE - 1 - start >= (itemCount * 2)
-                    ? itemCount * 2
-                    : Integer.MAX_VALUE - 1 - start;
-            super.notifyItemRangeChanged(start, newCount, null);
-        }
-    }
-
-    @Override
-    public void notifyItemRangeRemoved(int index, int count) {
-        if (mModel.get(SUGGESTIONS_KEY).size() == 0) {
-            // When we removed the last item in the model, we would go from infinite scroll
-            // back to non-scrolling. Notify Recyclerview to remove everything.
-            super.notifyItemRangeRemoved(1, Integer.MAX_VALUE - 1);
-        } else {
-            // Otherwise, rebind the visible spectrum.
-            // Account for edge conditions so we don't crash in the impossible case.
-            int start = mLayoutManager.findFirstVisibleItemPosition();
-            int itemCount = mModel.get(ITEM_COUNT_KEY);
-            int newCount = Integer.MAX_VALUE - 1 - start >= (itemCount * 2)
-                    ? itemCount * 2
-                    : Integer.MAX_VALUE - 1 - start;
-            super.notifyItemRangeChanged(start, newCount, null);
-        }
-    }
-
-    @Override
-    public void notifyItemRangeChanged(int index, int count, @Nullable PropertyKey payload) {
-        if (mModel.get(SUGGESTIONS_KEY).size() == 0) {
-            // If itemCount is 1, then notify super.
-            // This should only happen if "All apps" icon has changed in some way and we aren't
-            // infinite-scrolling.
-            super.notifyItemRangeChanged(index, count, payload);
-        } else {
-            // Otherwise, rebind the visible spectrum.
-            // Account for edge conditions so we don't crash in the impossible case.
-            int start = mLayoutManager.findFirstVisibleItemPosition();
-            int itemCount = mModel.get(ITEM_COUNT_KEY);
-            int newCount = Integer.MAX_VALUE - 1 - start >= (itemCount * 2)
-                    ? itemCount * 2
-                    : Integer.MAX_VALUE - 1 - start;
-            super.notifyItemRangeChanged(start, newCount, payload);
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
deleted file mode 100644
index 5961b2d..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
+++ /dev/null
@@ -1,114 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-import android.view.ViewStub;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.suggestions.ImageFetcher;
-import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate;
-import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.browser.widget.RoundedIconGenerator;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyListModel;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.RecyclerViewAdapter;
-
-/**
- * Controller for the carousel version of most likely, to be shown on touchless devices.
- */
-class SiteSuggestionsCoordinator {
-    static final PropertyModel.WritableIntPropertyKey CURRENT_INDEX_KEY =
-            new PropertyModel.WritableIntPropertyKey();
-    static final PropertyModel.WritableIntPropertyKey INITIAL_INDEX_KEY =
-            new PropertyModel.WritableIntPropertyKey();
-    static final PropertyModel
-            .ReadableObjectPropertyKey<PropertyListModel<PropertyModel, PropertyKey>>
-                    SUGGESTIONS_KEY = new PropertyModel.ReadableObjectPropertyKey<>();
-    static final PropertyModel.WritableIntPropertyKey ITEM_COUNT_KEY =
-            new PropertyModel.WritableIntPropertyKey();
-    static final PropertyModel.WritableObjectPropertyKey<PropertyModel> REMOVAL_KEY =
-            new PropertyModel.WritableObjectPropertyKey<>();
-    public static final PropertyModel.WritableObjectPropertyKey<Runnable> ON_FOCUS_CALLBACK =
-            new PropertyModel.WritableObjectPropertyKey<>();
-    public static final PropertyModel.WritableBooleanPropertyKey SHOULD_FOCUS_VIEW =
-            new PropertyModel.WritableBooleanPropertyKey();
-    public static final PropertyModel
-            .ReadableObjectPropertyKey<Callback<View>> ASYNC_FOCUS_DELEGATE =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    private SiteSuggestionsMediator mMediator;
-
-    SiteSuggestionsCoordinator(View parentView, Profile profile,
-            SuggestionsNavigationDelegate navigationDelegate, ContextMenuManager contextMenuManager,
-            ImageFetcher imageFetcher, TouchlessLayoutManager touchlessLayoutManager) {
-        Context context = parentView.getContext();
-        PropertyModel model =
-                new PropertyModel
-                        .Builder(CURRENT_INDEX_KEY, INITIAL_INDEX_KEY, SUGGESTIONS_KEY,
-                                ITEM_COUNT_KEY, REMOVAL_KEY, ON_FOCUS_CALLBACK, SHOULD_FOCUS_VIEW,
-                                ASYNC_FOCUS_DELEGATE)
-                        .with(SUGGESTIONS_KEY, new PropertyListModel<>())
-                        .with(ITEM_COUNT_KEY, 1)
-                        .with(ASYNC_FOCUS_DELEGATE,
-                                touchlessLayoutManager.createCallbackToSetViewToFocus())
-                        .build();
-        View suggestionsView =
-                ((ViewStub) parentView.findViewById(R.id.most_likely_stub)).inflate();
-
-        SiteSuggestionsLayoutManager layoutManager =
-                new SiteSuggestionsLayoutManager(context, model);
-
-        RoundedIconGenerator iconGenerator = ViewUtils.createDefaultRoundedIconGenerator(
-                context.getResources(), /* circularIcon = */ true);
-        int iconSize =
-                context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_min_size);
-
-        RecyclerView recyclerView =
-                suggestionsView.findViewById(R.id.most_likely_launcher_recycler);
-        SiteSuggestionsAdapter adapterDelegate = new SiteSuggestionsAdapter(model,
-                navigationDelegate, contextMenuManager, layoutManager,
-                suggestionsView.findViewById(R.id.most_likely_web_title_text));
-
-        RecyclerViewAdapter<SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder, PropertyKey>
-                adapter = new RecyclerViewAdapter<>(
-                        adapterDelegate, new SiteSuggestionsViewHolderFactory());
-
-        // Add spacing because tile margins get swallowed/overridden somehow.
-        // TODO(chili): use layout margin.
-        recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
-            @Override
-            public void getItemOffsets(
-                    Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-                outRect.bottom = context.getResources().getDimensionPixelSize(
-                        R.dimen.most_likely_carousel_edge_spacer);
-                outRect.left = 0;
-                outRect.right = 0;
-                outRect.top = context.getResources().getDimensionPixelSize(
-                        R.dimen.most_likely_carousel_edge_spacer);
-            }
-        });
-        recyclerView.setLayoutManager(layoutManager);
-        recyclerView.setAdapter(adapter);
-
-        mMediator =
-                new SiteSuggestionsMediator(model, profile, imageFetcher, iconGenerator, iconSize);
-    }
-
-    public void destroy() {
-        mMediator.destroy();
-    }
-
-    public FocusableComponent getFocusableComponent() {
-        return mMediator;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsLayoutManager.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsLayoutManager.java
deleted file mode 100644
index d11b77eb..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsLayoutManager.java
+++ /dev/null
@@ -1,342 +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.touchless;
-
-import static org.chromium.chrome.browser.touchless.SiteSuggestionsCoordinator.ITEM_COUNT_KEY;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Custom layout manager for site suggestions carousel. Handles custom effects such as
- * layout such that items at the edges are smaller than the center item and keeping focus
- * to the middle of the view.
- */
-class SiteSuggestionsLayoutManager extends RecyclerView.LayoutManager {
-    private static final float[] SCALE_FACTORS = {0.8f, 0.9f, 1f, 0.9f, 0.8f};
-    private static final float SUM_FACTORS;
-    // Initialize SUM_FACTORS to be sum of scale factors.
-    static {
-        float sum = 0f;
-        for (float num : SCALE_FACTORS) {
-            sum += num;
-        }
-        SUM_FACTORS = sum;
-    }
-    private static final int MAX_TILES = 5;
-
-    private int mFocusPosition;
-    private View mFocusView;
-    private boolean mShouldFocusAfterLayout;
-    private boolean mNeedRebind;
-    private Context mContext;
-    private RecyclerView mRecyclerView;
-    private PropertyModel mModel;
-
-    SiteSuggestionsLayoutManager(Context context, PropertyModel model) {
-        setAutoMeasureEnabled(true);
-        mContext = context;
-        mFocusPosition = 0;
-        mNeedRebind = false;
-        mFocusView = null;
-        mShouldFocusAfterLayout = false;
-        mModel = model;
-    }
-
-    @Override
-    public boolean onRequestChildFocus(
-            RecyclerView parent, RecyclerView.State state, View child, View focused) {
-        if (focused != null) {
-            int newChildPos = getPosition(focused);
-
-            // Stop scrolling if we're in the middle of a swipe/fling, see https://crbug.com/982357.
-            parent.stopScroll();
-
-            scrollToPosition(newChildPos);
-        }
-        return true;
-    }
-
-    @Override
-    public boolean supportsPredictiveItemAnimations() {
-        return false;
-    }
-
-    @Override
-    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
-        return new RecyclerView.LayoutParams(
-                RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
-    }
-
-    /**
-     * Calculates what views should be shown in the viewport and lays them out. Inherently does not
-     * support animations.
-     *
-     * @param recycler Recycler to use for fetching potentially cached views for a position.
-     * @param state Transient state of the RecyclerView.
-     */
-    @Override
-    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
-        if (getItemCount() == 0) {
-            return;
-        }
-        int currentFirstPosition = 0;
-        if (getChildCount() != 0) {
-            currentFirstPosition = getPosition(getChildAt(0));
-        }
-
-        SparseArray<View> viewCache = new SparseArray<>();
-        if (mNeedRebind) {
-            // If we need to re-bind all the data, recycle everything to force re-bind.
-            removeAndRecycleAllViews(recycler);
-            mNeedRebind = false;
-        } else {
-            // Temporarily cache all views.
-            for (int i = 0; i < getChildCount(); i++) {
-                viewCache.append(currentFirstPosition + i, getChildAt(i));
-            }
-
-            // Temporarily detach all views.
-            for (int i = 0; i < viewCache.size(); i++) {
-                detachView(viewCache.valueAt(i));
-            }
-        }
-
-        int futureFirstPosition = findFirstVisibleItemPosition();
-        int futureLastPosition = findLastVisibleItemPosition();
-
-        // Adds all the views necessary.
-        for (int i = futureFirstPosition; i <= futureLastPosition; i++) {
-            View child = viewCache.get(i);
-            if (child == null) {
-                // If only 1 view, set spacers around the view such that it appears in the center.
-                child = recycler.getViewForPosition(i);
-                addView(child);
-            } else {
-                viewCache.remove(i);
-                attachView(child);
-            }
-            if (i == mFocusPosition) {
-                mFocusView = child;
-            }
-        }
-
-        resizeViews();
-
-        // Recycle all unused views.
-        for (int i = 0; i < viewCache.size(); i++) {
-            removeDetachedView(viewCache.valueAt(i));
-            recycler.recycleView(viewCache.valueAt(i));
-        }
-    }
-
-    @Override
-    public void onLayoutCompleted(RecyclerView.State state) {
-        super.onLayoutCompleted(state);
-        if (mShouldFocusAfterLayout) {
-            mShouldFocusAfterLayout = false;
-            mFocusView.requestFocus();
-        }
-    }
-
-    @Override
-    public boolean canScrollHorizontally() {
-        return getItemCount() > 1;
-    }
-
-    /**
-     * Scrolls the views by a delta. Layout new views only when one has been completely
-     * scrolled off the screen.
-     *
-     * Note that this method does not scale the children as they move across the screen and does not
-     * layout partial views, which may be a suboptimal visual experience on a normal device.
-     *
-     * TODO(chili): Soften the jump when the new tile appears.
-     */
-    @Override
-    public int scrollHorizontallyBy(
-            int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
-        if (getItemCount() <= 1 || getChildCount() == 0) return 0;
-
-        // Move all children by -dx. This is because if we're dragging the elements to the left
-        // (<0), scrollbar is moving to the right (>0).
-        offsetChildrenHorizontal(-dx);
-
-        // Whether the first item is completely visible.
-        boolean isFirstItemVisible = getDecoratedRight(getChildAt(0)) > 0;
-        // Whether the last item is completely visible.
-        boolean isLastItemVisible = getDecoratedLeft(getChildAt(getChildCount() - 1)) < getWidth();
-
-        if (!isFirstItemVisible || !isLastItemVisible) {
-            if (dx > 0) {
-                mFocusPosition++;
-            } else {
-                mFocusPosition--;
-            }
-            onLayoutChildren(recycler, state);
-        }
-
-        return dx;
-    }
-
-    @Override
-    public void scrollToPosition(int position) {
-        if (position == mFocusPosition) return;
-        mFocusPosition = position;
-        assertNotInLayoutOrScroll("Scroll called within scroll");
-        requestLayout();
-    }
-
-    /**
-     * Returns what the first visible item position should be. Might not be accurate during layout.
-     */
-    public int findFirstVisibleItemPosition() {
-        return Math.max(0, mFocusPosition - 2);
-    }
-
-    /**
-     * Returns what the last visible item position should be. Might not be accurate during layout.
-     */
-    public int findLastVisibleItemPosition() {
-        int lastVisiblePosition = mFocusPosition + 2;
-        if (lastVisiblePosition < 0 || lastVisiblePosition == Integer.MAX_VALUE) {
-            lastVisiblePosition = Integer.MAX_VALUE - 1;
-        }
-        if (lastVisiblePosition >= getItemCount()) {
-            lastVisiblePosition = getItemCount() - 1;
-        }
-        return lastVisiblePosition;
-    }
-
-    @Override
-    public void onItemsChanged(RecyclerView recyclerView) {
-        requestFullRebind();
-    }
-
-    @Override
-    public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
-        requestFullRebind();
-    }
-
-    @Override
-    public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
-        requestFullRebind();
-    }
-
-    @Override
-    public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) {
-        requestFullRebind();
-    }
-
-    @Override
-    public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) {
-        requestFullRebind();
-    }
-
-    @Override
-    public void onAttachedToWindow(RecyclerView view) {
-        super.onAttachedToWindow(view);
-        mRecyclerView = view;
-    }
-
-    @Override
-    public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
-        super.onDetachedFromWindow(view, recycler);
-        mRecyclerView = null;
-    }
-
-    @Override
-    public int getRowCountForAccessibility(
-            RecyclerView.Recycler recycler, RecyclerView.State state) {
-        return 1;
-    }
-
-    @Override
-    public int getColumnCountForAccessibility(
-            RecyclerView.Recycler recycler, RecyclerView.State state) {
-        return mModel.get(ITEM_COUNT_KEY);
-    }
-
-    /**
-     * Requests layout such that it forces rebind of all visible items with
-     * updated data from the adapter.
-     */
-    private void requestFullRebind() {
-        mNeedRebind = true;
-        requestLayout();
-    }
-
-    void focusCenterItem() {
-        focusCenterItem(View.FOCUS_DOWN, null);
-    }
-
-    boolean focusCenterItem(int direction, Rect previouslyFocusedRect) {
-        if (mRecyclerView == null || mRecyclerView.isComputingLayout() || mFocusView == null) {
-            mShouldFocusAfterLayout = true;
-            return true;
-        }
-        return mFocusView.requestFocus(direction, previouslyFocusedRect);
-    }
-
-    /**
-     * Resizes currently attached views based on their position (larger in the middle).
-     *
-     * Views are centered, with increasing space between them as the screen widens. We assume
-     * that the screens are at least wide enough to display all of the icons at with minimal space.
-     * The tiles will overlap if there is a screen too small to do so.
-     */
-    private void resizeViews() {
-        int leftOffset = 0;
-        final int defaultIconSize =
-                mContext.getResources().getDimensionPixelSize(R.dimen.most_likely_tile_size);
-        // Amount of space to leave between items such that it would take up all available width.
-        final int horizontalSpacer =
-                (int) ((getWidth() - SUM_FACTORS * defaultIconSize) / (MAX_TILES - 1));
-
-        // Number of "empty" spaces to leave on the left side.
-        // This helps ensure that mFocusPosition is laid out in the center even if there are
-        // no elements to the left of it.
-        int leftSpaceCount =
-                (SCALE_FACTORS.length / 2) - mFocusPosition + findFirstVisibleItemPosition();
-        int leftDecrement = leftSpaceCount;
-
-        for (int i = 0; i < Math.min(getChildCount() + leftSpaceCount, MAX_TILES); i++) {
-            int iconSize = (int) (defaultIconSize * SCALE_FACTORS[i]);
-            int decoratedChildWidth = iconSize;
-            if (leftDecrement == 0) {
-                View child = getChildAt(i - leftSpaceCount);
-
-                // Scale according to position.
-                ViewGroup.LayoutParams params = child.getLayoutParams();
-
-                params.height = iconSize;
-                params.width = iconSize;
-                child.setLayoutParams(params);
-
-                // Offset the top so that it's centered vertically.
-                int topOffset = (defaultIconSize - iconSize) / 2;
-
-                measureChildWithMargins(child, 0, 0);
-                decoratedChildWidth = getDecoratedMeasuredWidth(child);
-                int decoratedChildHeight = getDecoratedMeasuredHeight(child);
-
-                layoutDecoratedWithMargins(child, leftOffset, topOffset,
-                        leftOffset + decoratedChildWidth, topOffset + decoratedChildHeight);
-            } else {
-                leftDecrement--;
-            }
-
-            // The next tile needs to be <horizontal spacer> padded away from this tile.
-            leftOffset += decoratedChildWidth + horizontalSpacer;
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
deleted file mode 100644
index 48742325..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
+++ /dev/null
@@ -1,212 +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.touchless;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.browser.explore_sites.ExploreSitesBridge;
-import org.chromium.chrome.browser.explore_sites.ExploreSitesCatalogUpdateRequestSource;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.suggestions.ImageFetcher;
-import org.chromium.chrome.browser.suggestions.SiteSuggestion;
-import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory;
-import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSites;
-import org.chromium.chrome.browser.widget.RoundedIconGenerator;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyObservable;
-import org.chromium.ui.widget.Toast;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Handles SiteSuggestion loading from MostVisitedSites. This includes images and reloading more
- * suggestions when needed.
- */
-
-class SiteSuggestionsMediator implements MostVisitedSites.Observer,
-                                         PropertyObservable.PropertyObserver<PropertyKey>,
-                                         FocusableComponent {
-    private static final int NUM_FETCHED_SITES = 8;
-    // The ML tiles could show anywhere between 2-5 tiles. To ensure that the initial index
-    // would land on % n == 0 and be roughly Integer.MAX / 2, where n could be [2,5],
-    // we divide by 240 (which is 5!) before multiplying by 120.
-    // TODO(chili): Maybe better formula for if this needs to be more generic.
-    private static final int INITIAL_SCROLLED_POSITION = Integer.MAX_VALUE / 240 * 120;
-    private static final int MAX_DISPLAYED_TILES = 4;
-
-    private PropertyModel mModel;
-    private ImageFetcher mImageFetcher;
-    private MostVisitedSites mMostVisitedSites;
-    private Profile mProfile;
-    private RoundedIconGenerator mDefaultIconGenerator;
-    private int mIconSize;
-
-    // Whether we should set focus to the data. Used to delay focus-setting until after loading
-    // pending suggestions.
-    private boolean mShouldSetFocus;
-    // Whether we have pending requests for suggestions.
-    private boolean mHasPendingRequests;
-
-    SiteSuggestionsMediator(PropertyModel model, Profile profile, ImageFetcher imageFetcher,
-            RoundedIconGenerator iconGenerator, int minIconSize) {
-        mModel = model;
-        mImageFetcher = imageFetcher;
-        mIconSize = minIconSize;
-        mProfile = profile;
-        mDefaultIconGenerator = iconGenerator;
-
-        mHasPendingRequests = true;
-        mMostVisitedSites =
-                SuggestionsDependencyFactory.getInstance().createMostVisitedSites(mProfile);
-        mMostVisitedSites.setObserver(this, NUM_FETCHED_SITES);
-
-        mModel.addObserver(this);
-
-        ExploreSitesBridge.initializeCatalog(
-                mProfile, ExploreSitesCatalogUpdateRequestSource.NEW_TAB_PAGE);
-    }
-
-    @Override
-    public void onSiteSuggestionsAvailable(List<SiteSuggestion> siteSuggestions) {
-        mHasPendingRequests = false;
-        HashSet<String> urls = new HashSet<>();
-        for (PropertyModel model : mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY)) {
-            urls.add(model.get(SiteSuggestionModel.URL_KEY));
-        }
-
-        // Because of the way we calculate mods, it's better to add suggestions all at once.
-        List<PropertyModel> modelList = new ArrayList<>(siteSuggestions.size());
-
-        // Map each SiteSuggestion into a PropertyModel representation and fetch the icon.
-        for (SiteSuggestion suggestion : siteSuggestions) {
-            // Do not put duplicates.
-            if (urls.contains(suggestion.url)) continue;
-
-            PropertyModel siteSuggestion = SiteSuggestionModel.getSiteSuggestionModel(
-                    suggestion, mDefaultIconGenerator.generateIconForText(suggestion.title));
-            modelList.add(siteSuggestion);
-            if (suggestion.whitelistIconPath.isEmpty()) {
-                makeIconRequest(siteSuggestion);
-            } else {
-                AsyncTask<Bitmap> task = new AsyncTask<Bitmap>() {
-                    @Override
-                    protected Bitmap doInBackground() {
-                        return BitmapFactory.decodeFile(suggestion.whitelistIconPath);
-                    }
-                    @Override
-                    protected void onPostExecute(Bitmap icon) {
-                        if (icon == null) makeIconRequest(siteSuggestion);
-                    }
-                };
-                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-            }
-        }
-
-        // If everything was duplicate. don't do anything.
-        if (modelList.isEmpty()) return;
-
-        // Total item count is 1 more than number of site suggestions to account for "all apps".
-        mModel.set(SiteSuggestionsCoordinator.ITEM_COUNT_KEY,
-                getItemCount(modelList.size() + urls.size()));
-        mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY).addAll(modelList);
-
-        // If we fetched site suggestions the first time, set initial and current position.
-        // We don't want to set position if we've already set position before.
-        if (siteSuggestions.size() > 0
-                && mModel.get(SiteSuggestionsCoordinator.INITIAL_INDEX_KEY) == 0) {
-            mModel.set(SiteSuggestionsCoordinator.INITIAL_INDEX_KEY, INITIAL_SCROLLED_POSITION);
-            mModel.set(SiteSuggestionsCoordinator.CURRENT_INDEX_KEY, INITIAL_SCROLLED_POSITION);
-        }
-
-        if (mShouldSetFocus) {
-            mModel.set(SiteSuggestionsCoordinator.SHOULD_FOCUS_VIEW, true);
-        }
-    }
-
-    @Override
-    public void onIconMadeAvailable(String siteUrl) {
-        // Update icon if an icon was made available.
-        for (PropertyModel suggestion : mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY)) {
-            if (suggestion.get(SiteSuggestionModel.URL_KEY).equals(siteUrl)) {
-                makeIconRequest(suggestion);
-            }
-        }
-    }
-
-    @Override
-    public void onPropertyChanged(
-            PropertyObservable<PropertyKey> source, @Nullable PropertyKey propertyKey) {
-        if (propertyKey == SiteSuggestionsCoordinator.REMOVAL_KEY) {
-            PropertyModel suggestion = mModel.get(SiteSuggestionsCoordinator.REMOVAL_KEY);
-            mMostVisitedSites.addBlacklistedUrl(suggestion.get(SiteSuggestionModel.URL_KEY));
-
-            Toast.makeText(ContextUtils.getApplicationContext(), R.string.most_visited_item_removed,
-                         Toast.LENGTH_SHORT)
-                    .show();
-
-            // When we remove an item, reset the item count key first.
-            int itemCount =
-                    getItemCount(mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY).size() - 1);
-            mModel.set(SiteSuggestionsCoordinator.ITEM_COUNT_KEY, itemCount);
-            // Actually remove the suggestion.
-            mModel.get(SiteSuggestionsCoordinator.SUGGESTIONS_KEY).remove(suggestion);
-            if (itemCount == 1) {
-                // If we removed everything except "All Apps", reset the index to 0.
-                mModel.set(SiteSuggestionsCoordinator.INITIAL_INDEX_KEY, 0);
-                mModel.set(SiteSuggestionsCoordinator.CURRENT_INDEX_KEY, 0);
-            }
-            // When removal of a site causes us to have fewer sites than we want to display, fetch
-            // again.
-            if (itemCount < MAX_DISPLAYED_TILES) {
-                mHasPendingRequests = true;
-                mMostVisitedSites.setObserver(this, NUM_FETCHED_SITES);
-            }
-        }
-    }
-
-    public void destroy() {
-        mMostVisitedSites.destroy();
-    }
-
-    @Override
-    public void requestFocus() {
-        if (mHasPendingRequests) {
-            mShouldSetFocus = true;
-        } else {
-            mModel.set(SiteSuggestionsCoordinator.SHOULD_FOCUS_VIEW, true);
-        }
-    }
-
-    @Override
-    public void setOnFocusListener(Runnable listener) {
-        mModel.set(SiteSuggestionsCoordinator.ON_FOCUS_CALLBACK, listener);
-    }
-
-    private int getItemCount(int listSize) {
-        // Item count is number of site suggestions available, up to MAX_DISPLAYED_TILES, + 1 for
-        // "All apps".
-        return (listSize > MAX_DISPLAYED_TILES ? MAX_DISPLAYED_TILES : listSize) + 1;
-    }
-
-    private void makeIconRequest(PropertyModel suggestion) {
-        // Fetches the icon for a site suggestion.
-        mImageFetcher.makeLargeIconRequest(suggestion.get(SiteSuggestionModel.URL_KEY), mIconSize,
-                (@Nullable Bitmap icon, int fallbackColor, boolean isFallbackDefault,
-                        int iconType) -> {
-                    if (icon != null) {
-                        suggestion.set(SiteSuggestionModel.ICON_KEY, icon);
-                    }
-                });
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java
deleted file mode 100644
index 2572952..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java
+++ /dev/null
@@ -1,40 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView;
-import android.util.AttributeSet;
-
-/**
- * Creates a custom recycler view that would initialize focus search on the middle child.
- */
-public class SiteSuggestionsRecyclerView extends RecyclerView {
-    private SiteSuggestionsLayoutManager mLayoutManager;
-
-    public SiteSuggestionsRecyclerView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    public void setLayoutManager(LayoutManager layout) {
-        super.setLayoutManager(layout);
-
-        if (layout instanceof SiteSuggestionsLayoutManager) {
-            mLayoutManager = (SiteSuggestionsLayoutManager) layout;
-        }
-    }
-
-    @Override
-    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        // If we don't have layoutmanager or if we're searching based on a previous focus,
-        // default to parent focus search.
-        if (mLayoutManager == null || previouslyFocusedRect != null) {
-            return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
-        }
-        return mLayoutManager.focusCenterItem(direction, null);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java
deleted file mode 100644
index 42519ff..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java
+++ /dev/null
@@ -1,54 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-
-import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.browser.widget.tile.TileView;
-import org.chromium.chrome.touchless.R;
-
-/**
- * View for a category name and site tiles.
- */
-public class SiteSuggestionsTileView extends TileView {
-    private final int mIconSizePx;
-
-
-    public SiteSuggestionsTileView(Context ctx, AttributeSet attrs) {
-        super(ctx, attrs);
-        mIconSizePx = getResources().getDimensionPixelSize(R.dimen.most_likely_tile_size);
-    }
-
-    /**
-     * Updates the icon in the tile.
-     *
-     * @param iconImage Bitmap icon to update.
-     * @param defaultIcon Default icon for the tile.
-     */
-    public void updateIcon(Bitmap iconImage, Bitmap defaultIcon) {
-        setIconDrawable(getDrawableForBitmap(iconImage, defaultIcon));
-    }
-
-    /**
-     * Generates a Drawable from the Bitmap version of an icon.
-     *
-     * @param image The Bitmap image. Can be null.
-     * @param defaultIcon Default icon for the tile.
-     * @return Drawable encapsulating either the scrabble tile or the bitmap.
-     */
-    public Drawable getDrawableForBitmap(Bitmap image, Bitmap defaultIcon) {
-        if (image == null) {
-            return new BitmapDrawable(getResources(), defaultIcon);
-        }
-        return ViewUtils.createRoundedBitmapDrawable(
-                Bitmap.createScaledBitmap(image, mIconSizePx, mIconSizePx, false),
-                ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java
deleted file mode 100644
index 5682079..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java
+++ /dev/null
@@ -1,35 +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.touchless;
-
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.RecyclerViewAdapter;
-
-/**
- * ViewHolderFactory for touchless suggestion tiles.
- */
-public class SiteSuggestionsViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory<
-        SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder> {
-    /**
-     * Actual ViewHolder for a touchless suggestion.
-     */
-    public static class SiteSuggestionsViewHolder extends RecyclerView.ViewHolder {
-        public SiteSuggestionsViewHolder(View view) {
-            super(view);
-        }
-    }
-
-    @Override
-    public SiteSuggestionsViewHolder createViewHolder(ViewGroup parent, int viewType) {
-        return new SiteSuggestionsViewHolder(
-                LayoutInflater.from(parent.getContext())
-                        .inflate(R.layout.touchless_suggestions_tile_view, parent, false));
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java
deleted file mode 100644
index cb215cc..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java
+++ /dev/null
@@ -1,86 +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.touchless;
-
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.native_page.ContextMenuManager.ContextMenuItemId;
-import org.chromium.chrome.browser.ntp.cards.ActionItem;
-import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.widget.ChromeImageView;
-import org.chromium.ui.widget.Toast;
-
-/** ViewHolder associated to {@link ItemViewType#ACTION} for touchless devices. */
-class TouchlessActionItemViewHolder extends ActionItem.ViewHolder {
-    private TextView mTextView;
-    private ChromeImageView mImageView;
-
-    TouchlessActionItemViewHolder(SuggestionsRecyclerView recyclerView,
-            ContextMenuManager contextMenuManager, final SuggestionsUiDelegate uiDelegate,
-            UiConfig uiConfig) {
-        super(R.layout.touchless_action_card, recyclerView, contextMenuManager, uiDelegate,
-                uiConfig);
-        mTextView = itemView.findViewById(R.id.dialog_item_text);
-        mImageView = itemView.findViewById(R.id.dialog_item_icon);
-    }
-
-    @Override
-    public void onBindViewHolder(ActionItem item) {
-        super.onBindViewHolder(item);
-
-        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(itemView.getLayoutParams());
-        params.bottomMargin = itemView.getResources().getDimensionPixelSize(
-                R.dimen.touchless_new_tab_recycler_view_over_scroll);
-        itemView.setLayoutParams(params);
-
-        mButton.setBackground(ApiCompatibilityUtils.getDrawable(
-                itemView.getResources(), R.drawable.hairline_border_card_background));
-        mTextView.setText(itemView.getResources().getString(R.string.more_articles));
-        mImageView.setImageDrawable(
-                ApiCompatibilityUtils.getDrawable(itemView.getResources(), R.drawable.ic_note_add));
-        // Image view defaults to GONE.
-        mImageView.setVisibility(View.VISIBLE);
-        ContextMenuManager.registerViewForTouchlessContextMenu(
-                mButton, new ContextMenuManager.EmptyDelegate() {
-                    @Override
-                    public String getContextMenuTitle() {
-                        return mButton.getResources().getString(R.string.more_articles);
-                    }
-
-                    @Override
-                    public boolean isItemSupported(@ContextMenuItemId int menuItemId) {
-                        return menuItemId == ContextMenuItemId.SEARCH
-                                || menuItemId == ContextMenuItemId.LEARN_MORE;
-                    }
-                });
-    }
-
-    @Override
-    protected void showFetchFailureMessage() {
-        Toast.makeText(itemView.getContext(), R.string.ntp_suggestions_fetch_failed,
-                     Toast.LENGTH_SHORT)
-                .show();
-    }
-
-    @Override
-    protected void showNoNewSuggestionsMessage() {
-        Toast.makeText(itemView.getContext(), R.string.ntp_suggestions_fetch_no_new_suggestions,
-                     Toast.LENGTH_SHORT)
-                .show();
-    }
-
-    @VisibleForTesting
-    View getButtonForTesting() {
-        return mButton;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessAddToHomescreenManager.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessAddToHomescreenManager.java
deleted file mode 100644
index 238d723..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessAddToHomescreenManager.java
+++ /dev/null
@@ -1,54 +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.touchless;
-
-import android.graphics.Bitmap;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.webapps.AddToHomescreenView;
-import org.chromium.chrome.browser.webapps.TouchlessAddToHomescreenDialog;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-
-/**
- * Add to homescreen manager specifically for touchless devices.
- */
-class TouchlessAddToHomescreenManager implements AddToHomescreenView.Delegate {
-    private final ChromeActivity mActivity;
-    private final ModalDialogManager mDialogManager;
-    private final String mUrl;
-    private final String mTitle;
-    private final Bitmap mIconBitmap;
-
-    public TouchlessAddToHomescreenManager(ChromeActivity activity,
-            ModalDialogManager dialogManager, String url, String title, Bitmap iconBitmap) {
-        mActivity = activity;
-        mDialogManager = dialogManager;
-        mUrl = url;
-        mTitle = title;
-        mIconBitmap = iconBitmap;
-    }
-
-    // Starts the process of showing the dialog and adding the shortcut.
-    public void start() {
-        AddToHomescreenView dialog =
-                new TouchlessAddToHomescreenDialog(mActivity, mDialogManager, this);
-        dialog.show();
-        dialog.onUserTitleAvailable(mTitle, mUrl, false);
-        dialog.onIconAvailable(mIconBitmap);
-    }
-
-    @Override
-    public void addToHomescreen(String title) {
-        ShortcutHelper.addShortcut(
-                mActivity.getActivityTab(), mUrl, mUrl, title, mIconBitmap, false, 0, "");
-    }
-
-    @Override
-    public void onNativeAppDetailsRequested() {}
-
-    @Override
-    public void onDialogDismissed() {}
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java
deleted file mode 100644
index 6db2539f..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java
+++ /dev/null
@@ -1,68 +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.touchless;
-
-import android.os.Bundle;
-import android.view.View;
-
-import androidx.annotation.LayoutRes;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder;
-import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
-import org.chromium.chrome.browser.suggestions.SuggestionsBinder;
-import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.chrome.touchless.R;
-
-/**
- * A class that represents the view for a single card snippet.
- */
-public class TouchlessArticleViewHolder extends SnippetArticleViewHolder {
-    private final Callback<View> mAsyncFocusDelegate;
-
-    /**
-     * Constructs a {@link TouchlessArticleViewHolder} item used to display snippets.
-     * @param parent The SuggestionsRecyclerView that is going to contain the newly created view.
-     * @param contextMenuManager The manager responsible for the context menu.
-     * @param uiDelegate The delegate object used to open an article, fetch thumbnails, etc.
-     * @param uiConfig The NTP UI configuration object used to adjust the article UI.
-     * @param offlinePageBridge used to determine if article is prefetched.
-     * @param asyncFocusDelegate used to request focus when views are guaranteed to be focusable.
-     */
-    public TouchlessArticleViewHolder(SuggestionsRecyclerView parent,
-            ContextMenuManager contextMenuManager, SuggestionsUiDelegate uiDelegate,
-            UiConfig uiConfig, OfflinePageBridge offlinePageBridge,
-            Callback<View> asyncFocusDelegate) {
-        super(parent, contextMenuManager, uiDelegate, uiConfig, offlinePageBridge, getLayout());
-        mAsyncFocusDelegate = asyncFocusDelegate;
-    }
-
-    @Override
-    public void requestFocusWithBundle(Bundle focusBundle) {
-        mAsyncFocusDelegate.onResult(itemView);
-    }
-
-    @Override
-    public void setOnFocusListener(Callback<Bundle> callback) {
-        itemView.setOnFocusChangeListener((View view, boolean hasFocus) -> {
-            if (hasFocus) {
-                callback.onResult(null);
-            }
-        });
-    }
-
-    @LayoutRes
-    private static int getLayout() {
-        return R.layout.touchless_content_suggestions_card;
-    }
-
-    @Override
-    protected SuggestionsBinder createBinder(SuggestionsUiDelegate uiDelegate) {
-        return new TouchlessSuggestionsBinder(itemView, uiDelegate);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessCategoryCardViewHolderFactory.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessCategoryCardViewHolderFactory.java
deleted file mode 100644
index 9eb387d..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessCategoryCardViewHolderFactory.java
+++ /dev/null
@@ -1,23 +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.touchless;
-
-import org.chromium.chrome.browser.explore_sites.CategoryCardViewHolderFactory;
-import org.chromium.chrome.touchless.R;
-
-/**
- * Factory to provide resources for touchless devices.
- */
-class TouchlessCategoryCardViewHolderFactory extends CategoryCardViewHolderFactory {
-    @Override
-    protected int getCategoryCardViewResource() {
-        return R.layout.touchless_explore_sites_category_card_view;
-    }
-
-    @Override
-    protected int getTileViewResource() {
-        return R.layout.touchless_explore_sites_tile_view_condensed;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java
deleted file mode 100644
index 97261e3b..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java
+++ /dev/null
@@ -1,257 +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.touchless;
-
-import android.graphics.Bitmap;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-
-import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ActionNames;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.DialogListItemProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Handles context menu creation for native pages on touchless devices. Utilizes functionality in
- * ContextMenuManager and Delegate to select items to show and lookup their labels.
- */
-public class TouchlessContextMenuManager extends ContextMenuManager {
-    /**
-     * Delegate for touchless-specific context menu items.
-     */
-    public interface Delegate extends ContextMenuManager.Delegate {
-        /**
-         * @return Title associated with this delegate.
-         */
-        String getTitle();
-
-        /**
-         * @return Icon associated with this delegate. Used to populate touchless shortcuts.
-         */
-        Bitmap getIconBitmap();
-    }
-
-    /**
-     * Empty implementation of Delegate to allow derived classes to only implement methods they
-     * need.
-     */
-    public static class EmptyDelegate extends ContextMenuManager.EmptyDelegate implements Delegate {
-        @Override
-        public String getTitle() {
-            return null;
-        }
-
-        @Override
-        public Bitmap getIconBitmap() {
-            return null;
-        }
-    }
-
-    private final ChromeActivity mActivity;
-    private final ModalDialogManager mDialogManager;
-    // This field should be set when showing a dialog, and nulled out when the dialog is closed. We
-    // can check if it is null to determine whether we're currently showing our dialog.
-    private PropertyModel mTouchlessMenuModel;
-    private ModalDialogManager mModalDialogManager;
-
-    public TouchlessContextMenuManager(ChromeActivity activity, ModalDialogManager dialogManager,
-            NativePageNavigationDelegate navigationDelegate,
-            TouchEnabledDelegate touchEnabledDelegate, Runnable closeContextMenuCallback,
-            String userActionPrefix) {
-        super(navigationDelegate, touchEnabledDelegate, closeContextMenuCallback, userActionPrefix);
-        mActivity = activity;
-        mDialogManager = dialogManager;
-    }
-
-    /**
-     * Creates PropertyModel for touchless context menu and displays it through modalDialogManager.
-     *
-     * @param modalDialogManager The ModalDialogManager to display context menu.
-     * @param delegate Delegate defines filter for displayed menu items and behavior for selects
-     *                 item.
-     */
-    public void showTouchlessContextMenu(
-            ModalDialogManager modalDialogManager, ContextMenuManager.Delegate delegate) {
-        // Don't create a new dialog if we're already showing one.
-        if (mTouchlessMenuModel != null) {
-            return;
-        }
-
-        ModelList menuItems = new ModelList();
-        for (@ContextMenuItemId int itemId = 0; itemId < ContextMenuItemId.NUM_ENTRIES; itemId++) {
-            if (!shouldShowItem(itemId, delegate)) continue;
-
-            // Each menu item is assigned its own instance of TouchlessItemClickListener where
-            // itemId of this item is maintained.
-            PropertyModel menuItem =
-                    buildMenuItem(itemId, new TouchlessItemClickListener(delegate, itemId));
-            menuItems.add(new ListItem(ListItemType.DEFAULT, menuItem));
-        }
-        if (menuItems.size() == 0) return;
-
-        mTouchlessMenuModel = buildMenuModel(delegate.getContextMenuTitle(), menuItems);
-        mModalDialogManager = modalDialogManager;
-        mModalDialogManager.showDialog(mTouchlessMenuModel, ModalDialogManager.ModalDialogType.APP);
-
-        notifyContextMenuShown(delegate);
-    }
-
-    @Override
-    protected @StringRes int getResourceIdForMenuItem(@ContextMenuItemId int id) {
-        if (id == ContextMenuItemId.SEARCH) {
-            return org.chromium.chrome.R.string.search_or_type_web_address;
-        }
-        if (id == ContextMenuItemId.ADD_TO_MY_APPS) {
-            return R.string.menu_add_to_apps;
-        }
-
-        return super.getResourceIdForMenuItem(id);
-    }
-
-    @Override
-    protected boolean handleMenuItemClick(
-            @ContextMenuItemId int itemId, ContextMenuManager.Delegate delegate) {
-        if (itemId == ContextMenuItemId.SEARCH) {
-            AppHooks.get().onSearchContextMenuClick();
-            return true;
-        }
-        if (itemId == ContextMenuItemId.ADD_TO_MY_APPS) {
-            Delegate touchlessDelegate = (Delegate) delegate;
-            TouchlessAddToHomescreenManager touchlessAddToHomescreenManager =
-                    new TouchlessAddToHomescreenManager(mActivity, mDialogManager,
-                            touchlessDelegate.getUrl(), touchlessDelegate.getTitle(),
-                            touchlessDelegate.getIconBitmap());
-            touchlessAddToHomescreenManager.start();
-            return true;
-        }
-        return super.handleMenuItemClick(itemId, delegate);
-    }
-
-    @Override
-    protected boolean shouldShowItem(
-            @ContextMenuItemId int itemId, ContextMenuManager.Delegate delegate) {
-        // Here we filter out any item IDs that don't make sense in touchless.
-        switch (itemId) {
-            case ContextMenuItemId.SEARCH:
-                return delegate.isItemSupported(itemId);
-            case ContextMenuItemId.REMOVE:
-                // fall through
-            case ContextMenuItemId.LEARN_MORE:
-                return super.shouldShowItem(itemId, delegate);
-            case ContextMenuItemId.SAVE_FOR_OFFLINE:
-                // fall through
-            case ContextMenuItemId.OPEN_IN_NEW_TAB:
-                // fall through
-            case ContextMenuItemId.OPEN_IN_INCOGNITO_TAB:
-                // fall through
-            case ContextMenuItemId.OPEN_IN_NEW_WINDOW:
-                return false;
-            case ContextMenuItemId.ADD_TO_MY_APPS:
-                if (delegate instanceof Delegate) {
-                    return delegate.isItemSupported(itemId);
-                } else {
-                    return false;
-                }
-        }
-
-        assert false : "Encountered unexpected touchless context menu item type";
-        return false;
-    }
-
-    /**
-     * Builds PropertyModel for individual menu item. String for item's label is loaded from
-     * resources by PropertyModel.Builder.
-     */
-    private PropertyModel buildMenuItem(@ContextMenuItemId int itemId, OnClickListener listener) {
-        return new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                .with(DialogListItemProperties.TEXT, mActivity.getResources(),
-                        getResourceIdForMenuItem(itemId))
-                .with(DialogListItemProperties.ICON, mActivity, getIconIdForMenuItem(itemId))
-                .with(DialogListItemProperties.CLICK_LISTENER, listener)
-                .build();
-    }
-
-    /** Builds PropertyModel for context menu from list of PropertyModels for individual items. */
-    private PropertyModel buildMenuModel(String title, ModelList menuItems) {
-        PropertyModel.Builder builder =
-                new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS);
-        ActionNames names = new ActionNames();
-        names.cancel = org.chromium.chrome.R.string.cancel;
-        names.select = org.chromium.chrome.R.string.select;
-        names.alt = 0;
-        builder.with(TouchlessDialogProperties.IS_FULLSCREEN, true)
-                .with(ModalDialogProperties.CONTROLLER,
-                        new ModalDialogProperties.Controller() {
-                            @Override
-                            public void onClick(PropertyModel model, int buttonType) {}
-
-                            @Override
-                            public void onDismiss(PropertyModel model, int dismissalCause) {
-                                mTouchlessMenuModel = null;
-                            }
-                        })
-                .with(TouchlessDialogProperties.ACTION_NAMES, names)
-                .with(TouchlessDialogProperties.CANCEL_ACTION, (v) -> closeTouchlessContextMenu())
-                .with(TouchlessDialogProperties.LIST_MODELS, menuItems)
-                .with(TouchlessDialogProperties.PRIORITY, TouchlessDialogProperties.Priority.HIGH)
-                .with(TouchlessDialogProperties.FORCE_SINGLE_LINE_TITLE, true);
-        if (title != null) {
-            builder.with(ModalDialogProperties.TITLE, title);
-        }
-        return builder.build();
-    }
-
-    /**
-     * Returns resource id of an icon to be displayed for menu item with given item id.
-     */
-    private @DrawableRes int getIconIdForMenuItem(@ContextMenuItemId int itemId) {
-        switch (itemId) {
-            case ContextMenuItemId.SEARCH:
-                return R.drawable.ic_search;
-            case ContextMenuItemId.REMOVE:
-                return R.drawable.ic_remove_circle_outline_24dp;
-            case ContextMenuItemId.LEARN_MORE:
-                return R.drawable.ic_help_outline_24dp;
-            case ContextMenuItemId.ADD_TO_MY_APPS:
-                return R.drawable.ic_add_circle_outline_24dp;
-            default:
-                return 0;
-        }
-    }
-
-    private void closeTouchlessContextMenu() {
-        mModalDialogManager.dismissDialog(mTouchlessMenuModel, 0);
-    }
-
-    private class TouchlessItemClickListener implements OnClickListener {
-        private final ContextMenuManager.Delegate mDelegate;
-        private final @ContextMenuItemId int mItemId;
-
-        public TouchlessItemClickListener(
-                ContextMenuManager.Delegate delegate, @ContextMenuItemId int itemId) {
-            mDelegate = delegate;
-            mItemId = itemId;
-        }
-
-        @Override
-        public void onClick(View view) {
-            closeTouchlessContextMenu();
-            handleMenuItemClick(mItemId, mDelegate);
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java
deleted file mode 100644
index 8a785e5..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java
+++ /dev/null
@@ -1,61 +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.touchless;
-
-import android.content.Context;
-
-import androidx.annotation.StringRes;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.native_page.NativePage;
-import org.chromium.chrome.browser.native_page.NativePageHost;
-import org.chromium.chrome.browser.permissions.PermissionDialogDelegate;
-import org.chromium.chrome.browser.touchless.permissions.TouchlessPermissionDialogModel;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Provides an entry point into touchless code from the rest of Chrome.
- */
-public class TouchlessDelegate {
-    public static final boolean TOUCHLESS_MODE_ENABLED = true;
-
-    public static NativePage createTouchlessNewTabPage(
-            ChromeActivity activity, NativePageHost host) {
-        return new TouchlessNewTabPage(activity, host);
-    }
-
-    public static boolean isTouchlessNewTabPage(NativePage nativePage) {
-        return nativePage instanceof TouchlessNewTabPage;
-    }
-
-    public static NativePage createTouchlessExploreSitesPage(
-            ChromeActivity activity, NativePageHost host) {
-        return new TouchlessExploreSitesPage(activity, host);
-    }
-
-    public static Class<? extends ChromeActivity> getNoTouchActivityClass() {
-        return NoTouchActivity.class;
-    }
-
-    public static Class<?> getTouchlessPreferencesClass() {
-        return TouchlessPreferences.class;
-    }
-
-    public static PropertyModel getPermissionDialogModel(
-            ModalDialogProperties.Controller controller, PermissionDialogDelegate delegate) {
-        return TouchlessPermissionDialogModel.getModel(controller, delegate);
-    }
-
-    public static PropertyModel getMissingPermissionDialogModel(Context context,
-            ModalDialogProperties.Controller controller, @StringRes int messageId) {
-        return TouchlessPermissionDialogModel.getMissingPermissionDialogModel(
-                context, controller, messageId);
-    }
-
-    public static TouchlessUiCoordinator getTouchlessUiCoordinator(ChromeActivity activity) {
-        return new TouchlessUiCoordinatorImpl(activity);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesCategoryCardView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesCategoryCardView.java
deleted file mode 100644
index 996a86d..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesCategoryCardView.java
+++ /dev/null
@@ -1,59 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.util.AttributeSet;
-
-import org.chromium.chrome.browser.explore_sites.ExploreSitesCategoryCardView;
-import org.chromium.chrome.browser.explore_sites.ExploreSitesSite;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.ui.modelutil.PropertyModel;
-
-class TouchlessExploreSitesCategoryCardView extends ExploreSitesCategoryCardView {
-
-    /**
-     * Delegate that's aware of fields necessary for the touchless context menu.
-     */
-    protected class TouchlessCategoryCardInteractionDelegate extends CategoryCardInteractionDelegate
-            implements TouchlessContextMenuManager.Delegate {
-        private PropertyModel mModel;
-
-        TouchlessCategoryCardInteractionDelegate(PropertyModel model) {
-            super(model.get(ExploreSitesSite.URL_KEY), model.get(ExploreSitesSite.TILE_INDEX_KEY));
-            mModel = model;
-        }
-
-        @Override
-        public String getTitle() {
-            return mModel.get(ExploreSitesSite.TITLE_KEY);
-        }
-
-        @Override
-        public String getContextMenuTitle() {
-            return mModel.get(ExploreSitesSite.TITLE_KEY);
-        }
-
-        @Override
-        public Bitmap getIconBitmap() {
-            return mModel.get(ExploreSitesSite.ICON_KEY);
-        }
-
-        @Override
-        public boolean isItemSupported(int menuItemId) {
-            return menuItemId == ContextMenuManager.ContextMenuItemId.REMOVE;
-        }
-    }
-
-    public TouchlessExploreSitesCategoryCardView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected CategoryCardInteractionDelegate createInteractionDelegate(PropertyModel model) {
-        return new TouchlessCategoryCardInteractionDelegate(model);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java
deleted file mode 100644
index 3bc5fdd5..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java
+++ /dev/null
@@ -1,62 +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.touchless;
-
-import android.view.View;
-
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.explore_sites.CategoryCardViewHolderFactory;
-import org.chromium.chrome.browser.explore_sites.ExploreSitesPage;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.native_page.NativePageHost;
-import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-
-/**
- * A variant of {@see ExploreSitesPage} that handles touchless context menus.
- */
-public class TouchlessExploreSitesPage extends ExploreSitesPage {
-    private final ModalDialogManager mModalDialogManager;
-    private ChromeActivity mActivity;
-    private TouchlessContextMenuManager mTouchlessContextMenuManager;
-
-    /**
-     * Create a new instance of the explore sites page.
-     */
-    public TouchlessExploreSitesPage(ChromeActivity activity, NativePageHost host) {
-        super(activity, host);
-        mModalDialogManager = activity.getModalDialogManager();
-    }
-
-    @Override
-    protected void initialize(ChromeActivity activity, final NativePageHost host) {
-        mActivity = activity;
-        super.initialize(activity, host);
-    }
-
-    @Override
-    protected ContextMenuManager createContextMenuManager(NativePageNavigationDelegate navDelegate,
-            Runnable closeContextMenuCallback, String contextMenuUserActionPrefix) {
-        mTouchlessContextMenuManager = new TouchlessContextMenuManager(mActivity,
-                mActivity.getModalDialogManager(), navDelegate,
-                (enabled) -> {}, closeContextMenuCallback, contextMenuUserActionPrefix);
-        return mTouchlessContextMenuManager;
-    }
-
-    /** Manually finds the focused view and shows the context menu dialog. */
-    public void showContextMenu() {
-        View focusedView = getView().findFocus();
-        if (focusedView == null) return;
-        ContextMenuManager.Delegate delegate =
-                ContextMenuManager.getDelegateFromFocusedView(focusedView);
-        if (delegate == null) return;
-        mTouchlessContextMenuManager.showTouchlessContextMenu(mModalDialogManager, delegate);
-    }
-
-    @Override
-    protected CategoryCardViewHolderFactory createCategoryCardViewHolderFactory() {
-        return new TouchlessCategoryCardViewHolderFactory();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java
deleted file mode 100644
index eb339ad..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java
+++ /dev/null
@@ -1,84 +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.touchless;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.touchless.R;
-
-/**
- * Normally views can simply call {@link View#requestFocus()}. However, this turns out to be
- * problematic during the measure/layout of the {@link RecyclerView}. This class tracks the layout
- * state of the RecyclerView and decides the best way to focus the given View.
- */
-public class TouchlessLayoutManager extends LinearLayoutManager {
-    private View mViewToFocus;
-    private boolean mMeasureLayoutInProgress;
-
-    public TouchlessLayoutManager(Context context) {
-        super(context);
-    }
-
-    @Override
-    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec,
-            int heightSpec) {
-        mMeasureLayoutInProgress = true;
-        super.onMeasure(recycler, state, widthSpec, heightSpec);
-    }
-
-    @Override
-    public void onLayoutCompleted(RecyclerView.State state) {
-        super.onLayoutCompleted(state);
-        if (mViewToFocus != null) {
-            mViewToFocus.requestFocus();
-            mViewToFocus = null;
-        }
-        mMeasureLayoutInProgress = false;
-    }
-
-    /**
-     * Focuses the view, either right now if we're not in the middle of layout/measure, or
-     * otherwise at the end of layout.
-     * @param view The view to focus.
-     */
-    public void setViewToFocus(View view) {
-        if (mMeasureLayoutInProgress) {
-            mViewToFocus = view;
-        } else {
-            view.requestFocus();
-        }
-    }
-
-    public Callback<View> createCallbackToSetViewToFocus() {
-        return (View view) -> setViewToFocus(view);
-    }
-
-    @Override
-    public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
-            boolean immediate, boolean focusedChildVisible) {
-        int overScroll = parent.getResources().getDimensionPixelSize(
-                R.dimen.touchless_new_tab_recycler_view_over_scroll);
-        // The origin for top/bottom is the top edge of view. Subtract overScroll to scroll higher,
-        // add to scroll lower. Min/max with the edges of the rect to ensure the entire direct child
-        // is focused. This is especially important for the above the fold view, we want the entire
-        // section to be visible when any element inside it is focused.
-        int newTop = Math.min(0, rect.top) - overScroll;
-        int newBottom = Math.max(child.getHeight(), rect.bottom) + overScroll;
-        Rect withPadding = new Rect(rect.left, newTop, rect.right, newBottom);
-        return super.requestChildRectangleOnScreen(
-                parent, child, withPadding, immediate, focusedChildVisible);
-    }
-
-    @Override
-    public boolean requestChildRectangleOnScreen(
-            RecyclerView parent, View child, Rect rect, boolean immediate) {
-        return requestChildRectangleOnScreen(parent, child, rect, immediate, false);
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessModelCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessModelCoordinator.java
deleted file mode 100644
index 7f8aa65..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessModelCoordinator.java
+++ /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.
-
-package org.chromium.chrome.browser.touchless;
-
-import android.view.KeyEvent;
-
-import org.chromium.ui.modelutil.PropertyModel;
-
-/** The Touchless Model Coordinator. */
-public interface TouchlessModelCoordinator {
-    /**
-     * Add a model to the queue to be shown.
-     * @param model The model to add.
-     */
-    default void addModelToQueue(PropertyModel model) {}
-
-    /**
-     * Remove a model from the queue to be shown.
-     * @param model The model to remove.
-     */
-    default void removeModelFromQueue(PropertyModel model) {}
-
-    /**
-     * A notification that a key event occurred.
-     * @param event The event object.
-     * @return null if event was consumed; the event to propagate, otherwise.
-     */
-    KeyEvent onKeyEvent(KeyEvent event);
-
-    /**
-     * Clean up anything that needs to be.
-     */
-    void destroy();
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java
deleted file mode 100644
index f9df8b6b..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java
+++ /dev/null
@@ -1,123 +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.touchless;
-
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.ntp.cards.ItemViewType;
-import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
-import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
-import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
-import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig;
-import org.chromium.ui.modelutil.PropertyModel;
-
-import java.util.List;
-
-/**
- * Adds touchless specific logic that needs to be attached and/or interacted with view holders.
- */
-public class TouchlessNewTabPageAdapter extends NewTabPageAdapter {
-    private final PropertyModel mModel;
-    private final FocusableComponent mFocusableOpenLastTab;
-    private final FocusableComponent mFocusableSiteSuggestions;
-    private final Callback<View> mAsyncFocusDelegate;
-
-    // Initial focus should only be set once. After that happens this sentinel is sent to false and
-    // the initial focus field should not be used.
-    private boolean mCheckInitialFocus = true;
-
-    private static final String VIEW_HOLDER_BUNDLE_KEY = "VHBK";
-    private static final String VIEW_HOLDER_TYPE_KEY = "VHTK";
-    private static final String ADAPTER_POSITION_KEY = "APK";
-
-    /**
-     * Creates the adapter that will manage all the cards to display on the NTP.
-     * @param uiDelegate used to interact with the rest of the system.
-     * @param aboveTheFoldView the layout encapsulating all the above-the-fold elements
-     *         (logo, search box, most visited tiles), or null if only suggestions should
-     *         be displayed.
-     * @param uiConfig the NTP UI configuration, to be passed to created views.
-     * @param offlinePageBridge used to determine if articles are available.
-     * @param contextMenuManager used to build context menus.
-     * @param model the model of the recycler view component.
-     * @param focusableOpenLastTab Focusable object for the last tab component.
-     * @param focusableSiteSuggestions Focusable object for the site suggestions component.
-     * @param asyncFocusDelegate Used to safely request focus for a given view.
-     */
-    public TouchlessNewTabPageAdapter(SuggestionsUiDelegate uiDelegate,
-            @Nullable View aboveTheFoldView, UiConfig uiConfig, OfflinePageBridge offlinePageBridge,
-            ContextMenuManager contextMenuManager, PropertyModel model,
-            FocusableComponent focusableOpenLastTab, FocusableComponent focusableSiteSuggestions,
-            Callback<View> asyncFocusDelegate) {
-        super(uiDelegate, aboveTheFoldView, uiConfig, offlinePageBridge, contextMenuManager);
-        mModel = model;
-        mFocusableOpenLastTab = focusableOpenLastTab;
-        mFocusableSiteSuggestions = focusableSiteSuggestions;
-        mAsyncFocusDelegate = asyncFocusDelegate;
-    }
-
-    @Override
-    public NewTabPageViewHolder onCreateViewHolder(ViewGroup parent, @ItemViewType int viewType) {
-        switch (viewType) {
-            case ItemViewType.ABOVE_THE_FOLD:
-                return new AboveTheFoldViewHolder(
-                        mAboveTheFoldView, mFocusableOpenLastTab, mFocusableSiteSuggestions);
-            case ItemViewType.ACTION:
-                return new TouchlessActionItemViewHolder(
-                        mRecyclerView, mContextMenuManager, mUiDelegate, mUiConfig);
-            case ItemViewType.SNIPPET:
-                return new TouchlessArticleViewHolder(mRecyclerView, mContextMenuManager,
-                        mUiDelegate, mUiConfig, mOfflinePageBridge, mAsyncFocusDelegate);
-            default:
-                return super.onCreateViewHolder(parent, viewType);
-        }
-    }
-
-    @Override
-    public void onBindViewHolder(NewTabPageViewHolder holder, int position, List<Object> payloads) {
-        super.onBindViewHolder(holder, position, payloads);
-        Callback<Bundle> focusCallback =
-                mModel.get(TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK);
-        if (focusCallback != null) {
-            holder.setOnFocusListener((Bundle holderBundle) -> {
-                Bundle wrappedBundle = new Bundle();
-                wrappedBundle.putInt(ADAPTER_POSITION_KEY, holder.getAdapterPosition());
-                wrappedBundle.putBundle(VIEW_HOLDER_BUNDLE_KEY, holderBundle);
-                wrappedBundle.putString(VIEW_HOLDER_TYPE_KEY, holder.getClass().getName());
-                focusCallback.onResult(wrappedBundle);
-                // If focus is changing due to user interactions, the initial focus is no longer
-                // needed. While this flag is typically flipped when the initial focus is set,
-                // if the initial focus is not restored successfully, for example when the
-                // initial focus would be on an index larger than the initial number of cards,
-                // then it needs to be cleared here.
-                invalidateFocusRestore();
-            });
-        }
-
-        Bundle focusToRestore = mModel.get(TouchlessNewTabPageProperties.INITIAL_FOCUS);
-        if (canRestoreFocus() && focusToRestore != null
-                && focusToRestore.getInt(ADAPTER_POSITION_KEY) == holder.getAdapterPosition()
-                && holder.getClass().getName().equals(
-                        focusToRestore.getString(VIEW_HOLDER_TYPE_KEY))) {
-            holder.requestFocusWithBundle(focusToRestore.getBundle(VIEW_HOLDER_BUNDLE_KEY));
-            invalidateFocusRestore();
-        }
-    }
-
-    private boolean canRestoreFocus() {
-        return mCheckInitialFocus;
-    }
-
-    private void invalidateFocusRestore() {
-        mCheckInitialFocus = false;
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java
deleted file mode 100644
index f7d6a8f..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java
+++ /dev/null
@@ -1,147 +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.touchless;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.util.Base64;
-
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.browser.ntp.NewTabPage;
-import org.chromium.chrome.browser.ntp.NewTabPageUma;
-import org.chromium.chrome.browser.suggestions.SuggestionsMetrics;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabSelectionType;
-import org.chromium.ui.modelutil.PropertyModel;
-
-class TouchlessNewTabPageMediator extends EmptyTabObserver {
-    private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = "TouchlessScrollPosition";
-    private static final String NAVIGATION_ENTRY_FOCUS_KEY = "TouchlessFocus";
-
-    private final PropertyModel mModel;
-    private final Tab mTab;
-    private long mLastShownTimeNs;
-
-    private ScrollPositionInfo mScrollPosition;
-    private Bundle mFocus;
-
-    public TouchlessNewTabPageMediator(Tab tab) {
-        mTab = tab;
-        mTab.addObserver(this);
-
-        ScrollPositionInfo initialScrollPosition = ScrollPositionInfo.deserialize(
-                NewTabPage.getStringFromNavigationEntry(tab, NAVIGATION_ENTRY_SCROLL_POSITION_KEY));
-
-        String serializedString =
-                NewTabPage.getStringFromNavigationEntry(tab, NAVIGATION_ENTRY_FOCUS_KEY);
-        Bundle initialFocus = null;
-        if (serializedString != null) {
-            Parcel parcel = Parcel.obtain();
-            byte[] bytes = Base64.decode(serializedString, Base64.DEFAULT);
-            parcel.unmarshall(bytes, 0, bytes.length);
-            parcel.setDataPosition(0);
-            initialFocus = Bundle.CREATOR.createFromParcel(parcel);
-            parcel.recycle();
-        }
-
-        mModel = new PropertyModel.Builder(TouchlessNewTabPageProperties.ALL_KEYS)
-                         .with(TouchlessNewTabPageProperties.FOCUS_CHANGE_CALLBACK,
-                                 (newFocus) -> mFocus = newFocus)
-                         .with(TouchlessNewTabPageProperties.INITIAL_FOCUS, initialFocus)
-                         .with(TouchlessNewTabPageProperties.INITIAL_SCROLL_POSITION,
-                                 initialScrollPosition)
-                         .with(TouchlessNewTabPageProperties.SCROLL_POSITION_CALLBACK,
-                                 (newScrollPosition) -> mScrollPosition = newScrollPosition)
-                         .build();
-
-        // TODO(dewittj): Track loading status of the tiles before we record shown and hidden
-        // states.
-        recordNTPShown();
-    }
-
-    @Override
-    public void onShown(Tab tab, @TabSelectionType int type) {
-        // TODO(dewittj): Track loading status of the tiles before we record shown and hidden
-        // states.
-        recordNTPShown();
-    }
-
-    @Override
-    public void onHidden(Tab tab, @Tab.TabHidingType int type) {
-        recordNTPHidden();
-    }
-
-    @Override
-    public void onContentChanged(Tab tab) {
-        // This is the main entry point for #saveStateAndRemoveObserver when loading a native page.
-        // This is still called when loading renderer pages, but after the next navigation entry is
-        // committed, see https://crbug.com/963584.
-        saveStateAndRemoveObserver(tab);
-    }
-
-    @Override
-    public void onPageLoadStarted(Tab tab, String url) {
-        // This is the main entry point for #saveStateAndRemoveObserver when loading a renderer
-        // page. This is still called when loading native pages, but after we should have completely
-        // cleaned up ourselves and observers, see https://crbug.com/963584.
-        saveStateAndRemoveObserver(tab);
-    }
-
-    public PropertyModel getModel() {
-        return mModel;
-    }
-
-    void destroy() {
-        if (!mTab.isHidden()) recordNTPHidden();
-        // Should already have been removed from mTab's observer list.
-    }
-
-    /**
-     * Records UMA for the NTP being shown. This includes a fresh page load or being brought to
-     * the foreground.
-     */
-    private void recordNTPShown() {
-        mLastShownTimeNs = System.nanoTime();
-        NewTabPageUma.recordNTPImpression(NewTabPageUma.NTP_IMPRESSION_REGULAR);
-        RecordUserAction.record("MobileNTPShown");
-        SuggestionsMetrics.recordSurfaceVisible();
-    }
-
-    /** Records UMA for the NTP being hidden and the time spent on it. */
-    private void recordNTPHidden() {
-        NewTabPageUma.recordTimeSpentOnNtp(mLastShownTimeNs);
-        SuggestionsMetrics.recordSurfaceHidden();
-    }
-
-    /**
-     * Saves focus and scroll state to the current navigation entry.
-     * @param tab The current tab.
-     */
-    private void saveStateAndRemoveObserver(Tab tab) {
-        // This method ends up being called when the NTP is loaded, so ignore those cases.
-        if (mScrollPosition == null && mFocus == null) {
-            return;
-        }
-
-        if (mScrollPosition != null) {
-            NewTabPage.saveStringToNavigationEntry(
-                    tab, NAVIGATION_ENTRY_SCROLL_POSITION_KEY, mScrollPosition.serialize());
-        }
-        if (mFocus != null) {
-            Parcel parcel = Parcel.obtain();
-            mFocus.writeToParcel(parcel, 0);
-            byte[] bytes = parcel.marshall();
-            parcel.recycle();
-            String serializedString = Base64.encodeToString(bytes, Base64.DEFAULT);
-            NewTabPage.saveStringToNavigationEntry(
-                    tab, NAVIGATION_ENTRY_FOCUS_KEY, serializedString);
-        }
-
-        // Observations need to be removed now to avoid saving state to the wrong entry when loading
-        // a renderer page from on onContentChange notification, see https://crbug.com/963584.
-        tab.removeObserver(this);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java
deleted file mode 100644
index bc91ad2..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java
+++ /dev/null
@@ -1,31 +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.touchless;
-
-import android.os.Bundle;
-
-import org.chromium.base.Callback;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-class TouchlessNewTabPageProperties {
-    public static final PropertyModel
-            .ReadableObjectPropertyKey<Callback<Bundle>> FOCUS_CHANGE_CALLBACK =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    public static final PropertyModel.ReadableObjectPropertyKey<Bundle> INITIAL_FOCUS =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    public static final PropertyModel
-            .ReadableObjectPropertyKey<ScrollPositionInfo> INITIAL_SCROLL_POSITION =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    public static final PropertyModel
-            .ReadableObjectPropertyKey<Callback<ScrollPositionInfo>> SCROLL_POSITION_CALLBACK =
-            new PropertyModel.ReadableObjectPropertyKey<>();
-
-    public static final PropertyKey[] ALL_KEYS = {FOCUS_CHANGE_CALLBACK, INITIAL_FOCUS,
-            INITIAL_SCROLL_POSITION, SCROLL_POSITION_CALLBACK};
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java
deleted file mode 100644
index 653a5dc0..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java
+++ /dev/null
@@ -1,20 +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.touchless;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.LinearLayout;
-
-/**
- * ViewGroup representing the widgets on top of the content suggestions area in the touchless NTP.
- */
-class TouchlessNewTabPageTopLayout extends LinearLayout {
-    public TouchlessNewTabPageTopLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    // TODO(dewittj): Fill in with various Explore views.
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessPreferences.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessPreferences.java
deleted file mode 100644
index 90818d7..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessPreferences.java
+++ /dev/null
@@ -1,68 +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.touchless;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v7.preference.PreferenceFragmentCompat;
-import android.support.v7.widget.RecyclerView;
-import android.view.Menu;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * The Chrome settings activity for touchless devices.
- */
-public class TouchlessPreferences extends Preferences {
-    private TouchlessModelCoordinator mTouchlessModelCoordinator;
-    private PropertyModel mDialogModel;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
-        mTouchlessModelCoordinator = AppHooks.get().createTouchlessModelCoordinator(this);
-        mDialogModel =
-                new PropertyModel.Builder(TouchlessDialogProperties.MINIMAL_DIALOG_KEYS).build();
-        if (mTouchlessModelCoordinator != null) {
-            mTouchlessModelCoordinator.addModelToQueue(mDialogModel);
-        }
-    }
-
-    /**
-     * Adds paddings for the main list in the current support library Fragment.
-     */
-    @Override
-    public void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        Fragment fragment = getMainFragment();
-        if (!(fragment instanceof PreferenceFragmentCompat)) return;
-
-        int padding = getResources().getDimensionPixelSize(
-                org.chromium.chrome.touchless.R.dimen.touchless_preferences_highlight_padding);
-        RecyclerView recyclerView = ((PreferenceFragmentCompat) fragment).getListView();
-        recyclerView.setPadding(padding, 0, padding, 0);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        TouchlessDialogProperties.ActionNames actionNames =
-                new TouchlessDialogProperties.ActionNames();
-        actionNames.select = R.string.select;
-        actionNames.cancel = R.string.back;
-        actionNames.alt = 0;
-        mDialogModel.set(TouchlessDialogProperties.ACTION_NAMES, actionNames);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        return false;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessRecyclerView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessRecyclerView.java
deleted file mode 100644
index 4a60434..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessRecyclerView.java
+++ /dev/null
@@ -1,24 +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.touchless;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-
-/**
- * Provides a TouchlessLayoutManager to the SuggestionsRecyclerView. This facilitates restoring
- * focus.
- */
-public class TouchlessRecyclerView extends SuggestionsRecyclerView {
-    public TouchlessRecyclerView(Context context, AttributeSet attrs) {
-        super(context, attrs, new TouchlessLayoutManager(context));
-    }
-
-    public TouchlessLayoutManager getTouchlessLayoutManager() {
-        return (TouchlessLayoutManager) getLinearLayoutManager();
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java
deleted file mode 100644
index 15c00a34..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java
+++ /dev/null
@@ -1,53 +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.touchless;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.widget.TextView;
-
-import org.chromium.chrome.browser.suggestions.SuggestionsBinder;
-import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.touchless.R;
-
-/** Overrides SuggestionsBinder methods to provide touchless specific values and functionality. */
-public class TouchlessSuggestionsBinder extends SuggestionsBinder {
-    private static final String TOUCHLESS_ARTICLE_AGE_FORMAT_STRING = " %s";
-
-    public TouchlessSuggestionsBinder(View cardContainerView, SuggestionsUiDelegate uiDelegate) {
-        super(cardContainerView, uiDelegate);
-    }
-
-    @Override
-    protected int getThumbnailSize() {
-        return mCardContainerView.getResources().getDimensionPixelSize(
-                R.dimen.touchless_snippets_thumbnail_size);
-    }
-
-    @Override
-    protected int getPublisherFaviconSizePx() {
-        return getPublisherIconTextView().getResources().getDimensionPixelSize(
-                R.dimen.touchless_publisher_icon_size);
-    }
-
-    @Override
-    protected String getArticleAgeFormatString() {
-        return TOUCHLESS_ARTICLE_AGE_FORMAT_STRING;
-    }
-
-    @Override
-    protected TextView getPublisherIconTextView() {
-        return mAgeTextView;
-    }
-
-    @Override
-    protected Drawable createThumbnailDrawable(Bitmap thumbnail) {
-        return ViewUtils.createRoundedBitmapDrawable(thumbnail,
-                mAgeTextView.getResources().getDimensionPixelOffset(
-                        R.dimen.default_rounded_corner_radius));
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabCreator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabCreator.java
deleted file mode 100644
index 4cf8781..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabCreator.java
+++ /dev/null
@@ -1,126 +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.touchless;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.provider.Browser;
-
-import androidx.annotation.Nullable;
-import androidx.browser.customtabs.CustomTabsIntent;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
-import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.LaunchSourceType;
-import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabIdManager;
-import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
-import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
-import org.chromium.chrome.browser.tabmodel.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelOrderController;
-import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParams;
-import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.base.WindowAndroid;
-
-/**
- * Creates Tabs for navigation originating from {@link NoTouchActivity}.
- *
- * This is the same as the parent class with exception of opening a Custom Tab instead of creating a
- * new tab in Chrome for links that open in new tabs.
- */
-public class TouchlessTabCreator extends ChromeTabCreator {
-    private final TabDelegate mAsyncTabDelegate;
-    private final TabModelOrderController mOrderController;
-
-    public TouchlessTabCreator(NoTouchActivity activity, WindowAndroid window, boolean incognito) {
-        super(activity, window, incognito);
-        mAsyncTabDelegate = new TabDelegate(incognito) {
-            @Override
-            public void createNewTab(
-                    AsyncTabCreationParams asyncParams, @TabLaunchType int type, int parentId) {
-                String url = asyncParams.getLoadUrlParams().getUrl();
-
-                int assignedTabId = TabIdManager.getInstance().generateValidId(Tab.INVALID_TAB_ID);
-                AsyncTabParamsManager.add(assignedTabId, asyncParams);
-
-                Intent intent = new CustomTabsIntent.Builder().setShowTitle(true).build().intent;
-                intent.setData(Uri.parse(url));
-                intent.putExtra(
-                        CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, true);
-                intent.putExtra(CustomTabIntentDataProvider.EXTRA_IS_OPENED_BY_CHROME, true);
-                intent.putExtra(CustomTabIntentDataProvider.EXTRA_IS_OPENED_BY_WEBAPK, false);
-                intent.putExtra(CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE,
-                        LaunchSourceType.OTHER);
-                intent.putExtra(Browser.EXTRA_APPLICATION_ID,
-                        ContextUtils.getApplicationContext().getPackageName());
-                addAsyncTabExtras(
-                        asyncParams, parentId, false /* isChromeUI */, assignedTabId, intent);
-
-                IntentHandler.startActivityForTrustedIntent(intent);
-            }
-        };
-
-        mOrderController = new TabModelOrderController() {
-            @Override
-            public int determineInsertionIndex(int type, int position, Tab newTab) {
-                return 0;
-            }
-
-            @Override
-            public int determineInsertionIndex(int type, Tab newTab) {
-                return 0;
-            }
-
-            @Override
-            public boolean willOpenInForeground(int type, boolean isNewTabIncognito) {
-                return true;
-            }
-        };
-    }
-
-    @Override
-    public boolean createTabWithWebContents(
-            @Nullable Tab parent, WebContents webContents, @TabLaunchType int type, String url) {
-        InterceptNavigationDelegateImpl delegate = parent == null ? null :
-                InterceptNavigationDelegateImpl.get(parent);
-        if (delegate != null && delegate.shouldIgnoreNewTab(url, false)) return false;
-        if (shouldRedirectToCCT(type)) {
-            return mAsyncTabDelegate.createTabWithWebContents(parent, webContents, type, url);
-        }
-        return super.createTabWithWebContents(parent, webContents, type, url);
-    }
-
-    @Override
-    public Tab createNewTab(
-            LoadUrlParams loadUrlParams, @TabLaunchType int type, Tab parent, Intent intent) {
-        InterceptNavigationDelegateImpl delegate =
-                parent == null ? null : InterceptNavigationDelegateImpl.get(parent);
-        if (delegate != null && delegate.shouldIgnoreNewTab(loadUrlParams.getUrl(), false)) {
-            return null;
-        }
-        if (shouldRedirectToCCT(type)) {
-            return mAsyncTabDelegate.createNewTab(loadUrlParams, type, parent);
-        }
-        return super.createNewTab(loadUrlParams, type, parent, intent);
-    }
-
-    private boolean shouldRedirectToCCT(@TabLaunchType int type) {
-        // Only link clicks should open in CCT.
-        return isLinkClickLaunchType(type);
-    }
-
-    private boolean isLinkClickLaunchType(@TabLaunchType int type) {
-        return type == TabLaunchType.FROM_LINK || type == TabLaunchType.FROM_LONGPRESS_FOREGROUND
-                || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND;
-    }
-
-    /* package */ void setTabModel(TabModel model) {
-        setTabModel(model, mOrderController);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabObserver.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabObserver.java
deleted file mode 100644
index c6686e4..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabObserver.java
+++ /dev/null
@@ -1,91 +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.touchless;
-
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.Tab.TabHidingType;
-import org.chromium.content_public.browser.MediaSession;
-import org.chromium.content_public.browser.MediaSessionObserver;
-import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.ui.touchless.TouchlessEventHandler;
-
-/**
- * Obsever for touchless mode.
- *
- * Bridges events to TouchlessEventHandler, and maintains the media playing state for the current
- * tab.
- */
-public class TouchlessTabObserver extends EmptyTabObserver {
-    private MediaSessionObserver mMediaSessionObserver;
-
-    /** Updated by Media Session Observer when the media state changes. */
-    private boolean mPlayingMedia;
-
-    @Override
-    public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) {
-        // Only want to observer the navigation in main frame and not fragment
-        // navigation.
-        if (navigation.isInMainFrame() && !navigation.isFragmentNavigation()) {
-            TouchlessEventHandler.onDidFinishNavigation();
-        }
-    }
-
-    @Override
-    public void onHidden(Tab tab, @TabHidingType int type) {
-        // Only want to observer the activity hidden.
-        if (type == Tab.TabHidingType.ACTIVITY_HIDDEN) {
-            TouchlessEventHandler.onActivityHidden();
-        }
-    }
-
-    @Override
-    public void onContentChanged(Tab tab) {
-        setWebContents(tab.getWebContents());
-    }
-
-    /**
-     * @return whether media is playing currently in this tab.
-     */
-    public boolean isPlayingMedia() {
-        return mPlayingMedia;
-    }
-
-    private void setWebContents(WebContents webContents) {
-        // If the web contents is set but the media session is the same, then we don't want to clear
-        // our state since we would not know if the media session is suspended or not.
-        MediaSession mediaSession = MediaSession.fromWebContents(webContents);
-        if (mMediaSessionObserver != null
-                && mediaSession == mMediaSessionObserver.getMediaSession()) {
-            return;
-        }
-
-        cleanupMediaSessionObserver();
-        if (mediaSession != null) {
-            mMediaSessionObserver = createMediaSessionObserver(mediaSession);
-        }
-    }
-
-    private MediaSessionObserver createMediaSessionObserver(MediaSession mediaSession) {
-        return new MediaSessionObserver(mediaSession) {
-            @Override
-            public void mediaSessionDestroyed() {
-                cleanupMediaSessionObserver();
-            }
-
-            @Override
-            public void mediaSessionStateChanged(boolean isControllable, boolean isSuspended) {
-                mPlayingMedia = !isSuspended;
-            }
-        };
-    }
-
-    private void cleanupMediaSessionObserver() {
-        if (mMediaSessionObserver != null) mMediaSessionObserver.stopObserving();
-        mMediaSessionObserver = null;
-        mPlayingMedia = false;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinator.java
deleted file mode 100644
index 4dccad1..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinator.java
+++ /dev/null
@@ -1,31 +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.touchless;
-
-import android.view.KeyEvent;
-
-import org.chromium.chrome.browser.snackbar.SnackbarManager;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-
-/** Coordinator for Touchless UI. */
-public interface TouchlessUiCoordinator {
-    /**
-     * @param event The KeyEvent.
-     * @return The KeyEvent to be further propagated; may be different than the
-     * given event. The return value is null if the event is handled and no
-     * further propagation is required.
-     */
-    KeyEvent processKeyEvent(KeyEvent event);
-
-    /**
-     * @return The SnackbarManager for touchless mode.
-     */
-    SnackbarManager getSnackbarManager();
-
-    /**
-     * @return The ModalDialogManager for touchless mode.
-     */
-    ModalDialogManager createModalDialogManager();
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java
deleted file mode 100644
index 2e40eef3..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java
+++ /dev/null
@@ -1,142 +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.touchless;
-
-import android.view.KeyEvent;
-import android.view.ViewGroup;
-
-import androidx.annotation.CallSuper;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.lifecycle.Destroyable;
-import org.chromium.chrome.browser.lifecycle.InflationObserver;
-import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
-import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
-import org.chromium.chrome.browser.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogPresenter;
-import org.chromium.chrome.browser.touchless.snackbar.BlackHoleSnackbarManager;
-import org.chromium.chrome.browser.touchless.ui.iph.KeyFunctionsIPHCoordinator;
-import org.chromium.chrome.browser.touchless.ui.progressbar.ProgressBarCoordinator;
-import org.chromium.chrome.browser.touchless.ui.progressbar.ProgressBarView;
-import org.chromium.chrome.browser.touchless.ui.tooltip.TooltipView;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
-
-/** A coordinator for touchless UI. */
-public class TouchlessUiCoordinatorImpl implements Destroyable, NativeInitObserver,
-                                                   InflationObserver, StartStopWithNativeObserver,
-                                                   TouchlessUiCoordinator {
-    private ChromeActivity mActivity;
-
-    private TouchlessModelCoordinator mModelCoordinator;
-    private KeyFunctionsIPHCoordinator mKeyFunctionsIPHCoordinator;
-
-    /** The snackbar manager for this activity that drops all snackbar requests. */
-    private BlackHoleSnackbarManager mSnackbarManager;
-
-    private ProgressBarCoordinator mProgressBarCoordinator;
-    private TooltipView mTooltipView;
-    private ProgressBarView mProgressBarView;
-
-    private ActivityTabProvider.ActivityTabTabObserver mOpenLastTabObserver;
-
-    /** The class that enables zooming for all websites and handles touchless zooming. */
-    private TouchlessZoomHelper mTouchlessZoomHelper;
-
-    public TouchlessUiCoordinatorImpl(ChromeActivity activity) {
-        mActivity = activity;
-        mActivity.getLifecycleDispatcher().register(this);
-        mModelCoordinator = AppHooks.get().createTouchlessModelCoordinator(mActivity);
-    }
-
-    @Override
-    public void onPreInflationStartup() {}
-
-    @Override
-    public void onPostInflationStartup() {
-        // Only NoTouchActivity wants the progress bar and tooltips.
-        if (!(mActivity instanceof NoTouchActivity)) return;
-        ViewGroup coordinatorLayout = (ViewGroup) mActivity.findViewById(R.id.coordinator);
-        mTooltipView = new TooltipView(mActivity);
-        mProgressBarView = new ProgressBarView(mActivity);
-        coordinatorLayout.addView(mTooltipView);
-        coordinatorLayout.addView(mProgressBarView);
-
-        mProgressBarCoordinator =
-                new ProgressBarCoordinator(mProgressBarView, mActivity.getActivityTabProvider());
-
-        mOpenLastTabObserver = OpenLastTabMediator.createActivityScopedObserver(
-                mActivity, mActivity.getActivityTabProvider());
-    }
-
-    @Override
-    public void onFinishNativeInitialization() {
-        // Only NoTouchActivity wants the tooltips.
-        if (mActivity instanceof NoTouchActivity) {
-            mKeyFunctionsIPHCoordinator = new KeyFunctionsIPHCoordinator(
-                    mTooltipView, mActivity.getActivityTabProvider());
-        }
-        mTouchlessZoomHelper = new TouchlessZoomHelper(mActivity.getActivityTabProvider());
-    }
-
-    public void skipShowingProgressBarOnNextActivityStart() {
-        mProgressBarCoordinator.skipShowingOnNextActivityStart();
-    }
-
-    @Override
-    public void onStartWithNative() {
-        if (mProgressBarCoordinator != null) mProgressBarCoordinator.onActivityStart();
-    }
-
-    @Override
-    public void onStopWithNative() {}
-
-    @Override
-    public KeyEvent processKeyEvent(KeyEvent event) {
-        if (mModelCoordinator == null) return event;
-        return mModelCoordinator.onKeyEvent(event);
-    }
-
-    @Override
-    public SnackbarManager getSnackbarManager() {
-        if (mSnackbarManager == null) {
-            mSnackbarManager = new BlackHoleSnackbarManager(mActivity);
-        }
-        return mSnackbarManager;
-    }
-
-    @Override
-    public ModalDialogManager createModalDialogManager() {
-        TouchlessDialogPresenter dialogPresenter =
-                new TouchlessDialogPresenter(mActivity, mModelCoordinator);
-        ModalDialogManager modalDialogManager =
-                new ModalDialogManager(dialogPresenter, ModalDialogType.APP);
-        // Some tests need a presenter for ModalDialogType.TAB. Refer to
-        // PermissionTestRule$DialogShownCriteria#isSatisfied.
-        modalDialogManager.registerPresenter(dialogPresenter, ModalDialogType.TAB);
-        return modalDialogManager;
-    }
-
-    protected TouchlessModelCoordinator getModelCoordinator() {
-        return mModelCoordinator;
-    }
-
-    protected ChromeActivity getActivity() {
-        return mActivity;
-    }
-
-    @Override
-    @CallSuper
-    public void destroy() {
-        mActivity = null;
-        if (mKeyFunctionsIPHCoordinator != null) mKeyFunctionsIPHCoordinator.destroy();
-        if (mTouchlessZoomHelper != null) mTouchlessZoomHelper.destroy();
-        if (mProgressBarCoordinator != null) mProgressBarCoordinator.destroy();
-        if (mOpenLastTabObserver != null) mOpenLastTabObserver.destroy();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUrlUtilities.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUrlUtilities.java
deleted file mode 100644
index 1cbde5e1..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUrlUtilities.java
+++ /dev/null
@@ -1,43 +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.touchless;
-
-import android.net.Uri;
-import android.text.TextUtils;
-
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.components.url_formatter.UrlFormatter;
-
-/** URL utilities used for touchless devices. **/
-public class TouchlessUrlUtilities {
-    private static String sUrlForDisplayForTest;
-
-    /**
-     * Formats a given URL for displaying in touchless. This formatting cuts the URL to its eTLD+1.
-     * For example, for "https://chromium-review.googlesource.com/dashboard/", this will return
-     * "googlesource.com".
-     **/
-    public static String getUrlForDisplay(String url) {
-        if (sUrlForDisplayForTest != null) return sUrlForDisplayForTest;
-
-        if (TextUtils.isEmpty(url)) return url;
-
-        String domainAndRegistry = UrlUtilities.getDomainAndRegistry(url, false);
-        Uri parsed = Uri.parse(url);
-        return UrlFormatter.formatUrlForSecurityDisplayOmitScheme(
-                parsed.getScheme() + "://" + domainAndRegistry);
-    }
-
-    /**
-     * Set a display url for testing. When set,
-     * {@link TouchlessUrlUtilities#getUrlForDisplay(String)} will always return this.
-     * Please ensure to reset this by passing null as part of your test teardown.
-     */
-    @VisibleForTesting
-    public static void setUrlForDisplayForTest(String urlForDisplay) {
-        sUrlForDisplayForTest = urlForDisplay;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessZoomHelper.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessZoomHelper.java
deleted file mode 100644
index cd1106e..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessZoomHelper.java
+++ /dev/null
@@ -1,49 +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.touchless;
-
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.ZoomController;
-import org.chromium.chrome.browser.accessibility.FontSizePrefs;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.ui.touchless.TouchlessEventHandler;
-import org.chromium.ui.touchless.TouchlessEventHandler.TouchlessZoomCallback;
-
-/**
- * Enables zooming for all websites. Implements {@link TouchlessZoomCallback} and performs zoom in
- * and zoom out upon {@link TouchlessEventHandler}'s request.
- */
-public class TouchlessZoomHelper
-        implements TouchlessZoomCallback, ActivityTabProvider.ActivityTabObserver {
-    private Tab mCurrentTab;
-    private ActivityTabProvider mActivityTabProvider;
-
-    public TouchlessZoomHelper(ActivityTabProvider tabProvider) {
-        mActivityTabProvider = tabProvider;
-        mActivityTabProvider.addObserverAndTrigger(this);
-        FontSizePrefs.getInstance().enableTouchlessMode();
-        TouchlessEventHandler.setZoomCallback(this);
-    }
-
-    @Override
-    public void onZoomInRequested() {
-        if (mCurrentTab != null) ZoomController.zoomIn(mCurrentTab.getWebContents());
-    }
-
-    @Override
-    public void onZoomOutRequested() {
-        if (mCurrentTab != null) ZoomController.zoomOut(mCurrentTab.getWebContents());
-    }
-
-    @Override
-    public void onActivityTabChanged(Tab tab, boolean hint) {
-        mCurrentTab = tab;
-    }
-
-    public void destroy() {
-        TouchlessEventHandler.removeZoomCallback(this);
-        mActivityTabProvider.removeObserver(this);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java
deleted file mode 100644
index 8db4736..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java
+++ /dev/null
@@ -1,257 +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.touchless.dialog;
-
-import android.app.Dialog;
-import android.graphics.drawable.Drawable;
-import android.support.v4.view.ViewCompat;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.touchless.TouchlessModelCoordinator;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.DialogListItemProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-import org.chromium.ui.modaldialog.ModalDialogManager.Presenter;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.ModelListAdapter;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-import org.chromium.ui.widget.ChromeImageView;
-
-/** A modal dialog presenter that is specific to touchless dialogs. */
-public class TouchlessDialogPresenter extends Presenter {
-    /** An activity to attach dialogs to. */
-    private final ChromeActivity mActivity;
-    private final TouchlessModelCoordinator mModelCoordinator;
-
-    /** The dialog this class abstracts. */
-    private Dialog mDialog;
-
-    /** The model change processor for the currently shown dialog. */
-    private PropertyModelChangeProcessor<PropertyModel, ViewGroup, PropertyKey>
-            mModelChangeProcessor;
-
-    public TouchlessDialogPresenter(
-            ChromeActivity activity, TouchlessModelCoordinator modelCoordinator) {
-        mActivity = activity;
-        mModelCoordinator = modelCoordinator;
-    }
-
-    @Override
-    protected void addDialogView(PropertyModel model) {
-        // If the activity's decor view is not attached to window, we don't show the dialog because
-        // the window manager might have revoked the window token for this activity. See
-        // https://crbug.com/926688.
-        Window window = mActivity.getWindow();
-        if (window == null || !ViewCompat.isAttachedToWindow(window.getDecorView())) {
-            dismissCurrentDialog(DialogDismissalCause.NOT_ATTACHED_TO_WINDOW);
-            return;
-        }
-
-        boolean fullscreen = isFullscreen(model);
-
-        // If not fullscreen don't use a predefined style.
-        if (!fullscreen) {
-            mDialog = new Dialog(mActivity);
-            mDialog.getWindow().setGravity(Gravity.BOTTOM);
-            mDialog.getWindow().setBackgroundDrawable(ApiCompatibilityUtils.getDrawable(
-                    mActivity.getResources(), R.drawable.dialog_rounded_top));
-        } else {
-            mDialog = new Dialog(mActivity, R.style.Theme_Chromium_DialogWhenLarge);
-        }
-
-        mDialog.setOnCancelListener(dialogInterface
-                -> dismissCurrentDialog(DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE));
-        mDialog.setOnShowListener(dialog -> {
-            if (mModelCoordinator != null) mModelCoordinator.addModelToQueue(model);
-        });
-        mDialog.setOnDismissListener(dialog -> {
-            if (mModelCoordinator != null) mModelCoordinator.removeModelFromQueue(model);
-        });
-        // Cancel on touch outside should be disabled by default. The ModelChangeProcessor wouldn't
-        // notify change if the property is not set during initialization.
-        mDialog.setCanceledOnTouchOutside(false);
-        mDialog.setOnKeyListener((dialog, keyCode, event) -> {
-            return mModelCoordinator != null ? (mModelCoordinator.onKeyEvent(event) == null)
-                                             : false;
-        });
-        ViewGroup dialogView = (ViewGroup) LayoutInflater.from(mDialog.getContext())
-                .inflate(R.layout.touchless_dialog_view, null);
-        mModelChangeProcessor = PropertyModelChangeProcessor.create(
-                model, dialogView, TouchlessDialogPresenter::bind);
-        mDialog.setContentView(dialogView);
-
-        // If the modal dialog is not specified to be fullscreen, wrap content and place at the
-        // bottom of the screen. This needs to be done after content is added to the dialog.
-        if (!fullscreen) {
-            mDialog.getWindow().setLayout(
-                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        }
-
-        mDialog.show();
-        dialogView.announceForAccessibility(getContentDescription(model));
-    }
-
-    private boolean isFullscreen(PropertyModel model) {
-        if (!model.getAllSetProperties().contains(TouchlessDialogProperties.IS_FULLSCREEN)) {
-            // We should have this property set. This code is meant to guard against cases
-            // where we've forgotten to add this property.
-            assert false;
-            return false;
-        }
-        return model.get(TouchlessDialogProperties.IS_FULLSCREEN);
-    }
-
-    @Override
-    protected void removeDialogView(PropertyModel model) {
-        if (mModelChangeProcessor != null) {
-            mModelChangeProcessor.destroy();
-            mModelChangeProcessor = null;
-        }
-
-        if (mDialog != null) {
-            mDialog.dismiss();
-            mDialog = null;
-        }
-    }
-
-    /**
-     * Bind a model to a touchless dialog view.
-     * @param model The model being bound.
-     * @param view The view to apply the model to.
-     * @param propertyKey The property that changed.
-     */
-    private static void bind(PropertyModel model, ViewGroup view, PropertyKey propertyKey) {
-        assert !model.get(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY);
-        assert propertyKey != ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY;
-        // TODO(mdjones): If the default buttons are used assert no list items and convert the
-        //                buttons to list items.
-        if (TouchlessDialogProperties.IS_FULLSCREEN == propertyKey) {
-            // TODO(mdjones): Implement fullscreen/non-fullscreen modes.
-        } else if (ModalDialogProperties.TITLE_ICON == propertyKey) {
-            ChromeImageView imageView = view.findViewById(R.id.touchless_dialog_icon);
-            imageView.setImageDrawable(model.get(ModalDialogProperties.TITLE_ICON));
-            imageView.setVisibility(View.VISIBLE);
-        } else if (ModalDialogProperties.TITLE == propertyKey) {
-            TextView textView = view.findViewById(R.id.touchless_dialog_title);
-            textView.setText(model.get(ModalDialogProperties.TITLE));
-            textView.setVisibility(View.VISIBLE);
-        } else if (ModalDialogProperties.MESSAGE == propertyKey) {
-            TextView textView = view.findViewById(R.id.touchless_dialog_description);
-            textView.setText(model.get(ModalDialogProperties.MESSAGE));
-            textView.setVisibility(View.VISIBLE);
-        } else if (ModalDialogProperties.CUSTOM_VIEW == propertyKey) {
-            ViewGroup customGroup = view.findViewById(R.id.custom);
-            customGroup.addView(model.get(ModalDialogProperties.CUSTOM_VIEW));
-            customGroup.setVisibility(View.VISIBLE);
-        } else if (TouchlessDialogProperties.LIST_MODELS == propertyKey) {
-            ModelListAdapter adapter =
-                    new ModelListAdapter(model.get(TouchlessDialogProperties.LIST_MODELS));
-            adapter.registerType(ListItemType.DEFAULT,
-                    () -> LayoutInflater.from(view.getContext())
-                            .inflate(R.layout.dialog_list_item, null),
-                    TouchlessDialogPresenter::bindListItem);
-            ListView dialogOptions = view.findViewById(R.id.touchless_dialog_option_list);
-            dialogOptions.setAdapter(adapter);
-            dialogOptions.setItemsCanFocus(true);
-        } else if (TouchlessDialogProperties.FORCE_SINGLE_LINE_TITLE == propertyKey) {
-            TextView textView = view.findViewById(R.id.touchless_dialog_title);
-            textView.setMaxLines(model.get(TouchlessDialogProperties.FORCE_SINGLE_LINE_TITLE)
-                            ? 1
-                            : Integer.MAX_VALUE);
-        } else if (TouchlessDialogProperties.TITLE_DIRECTION == propertyKey) {
-            TextView textView = view.findViewById(R.id.touchless_dialog_title);
-            textView.setTextDirection(model.get(TouchlessDialogProperties.TITLE_DIRECTION));
-        } else if (TouchlessDialogProperties.TITLE_ELLIPSIZE == propertyKey) {
-            TextView textView = view.findViewById(R.id.touchless_dialog_title);
-            textView.setEllipsize(model.get(TouchlessDialogProperties.TITLE_ELLIPSIZE));
-        }
-    }
-
-    /**
-     * Bind a list model item to its view.
-     * @param model The model to bind.
-     * @param view The view to be bound to.
-     * @param propertyKey The property that changed.
-     */
-    private static void bindListItem(PropertyModel model, View view, PropertyKey propertyKey) {
-        ChromeImageView imageView = view.findViewById(R.id.dialog_item_icon);
-        TextView textView = view.findViewById(R.id.dialog_item_text);
-        if (DialogListItemProperties.ICON == propertyKey) {
-            if (model.get(DialogListItemProperties.ICON) == null) {
-                imageView.setImageDrawable(null);
-            } else {
-                imageView.setVisibility(View.VISIBLE);
-                Drawable icon = model.get(DialogListItemProperties.ICON).mutate();
-                icon.clearColorFilter();
-                imageView.setImageDrawable(icon);
-            }
-        } else if (DialogListItemProperties.TEXT == propertyKey) {
-            textView.setText(model.get(DialogListItemProperties.TEXT));
-        } else if (DialogListItemProperties.CLICK_LISTENER == propertyKey) {
-            if (!(model.get(DialogListItemProperties.CLICK_LISTENER)
-                                instanceof ClickThrottlingListener)) {
-                ClickThrottlingListener listener = new ClickThrottlingListener(
-                        model.get(DialogListItemProperties.CLICK_LISTENER));
-                listener.setIsMultiClickable(model.get(DialogListItemProperties.MULTI_CLICKABLE));
-                model.set(DialogListItemProperties.CLICK_LISTENER, listener);
-                view.setOnClickListener(listener);
-            } else {
-                ClickThrottlingListener listener = (ClickThrottlingListener) model.get(
-                        DialogListItemProperties.CLICK_LISTENER);
-                listener.resetWasClicked();
-                view.setOnClickListener(listener);
-            }
-        } else if (DialogListItemProperties.MULTI_CLICKABLE == propertyKey) {
-            View.OnClickListener listener = model.get(DialogListItemProperties.CLICK_LISTENER);
-            if (listener instanceof ClickThrottlingListener) {
-                ((ClickThrottlingListener) listener)
-                        .setIsMultiClickable(model.get(DialogListItemProperties.MULTI_CLICKABLE));
-            }
-        }
-    }
-
-    /**
-     * This OnClickListener implementation ensures that
-     * {@link DialogListItemProperties.CLICK_LISTENER} is only called once for models with
-     * {@link DialogListItemProperties.MULTI_CLICKABLE} set to false.
-     */
-    private static class ClickThrottlingListener implements View.OnClickListener {
-        private View.OnClickListener mOnClickListener;
-        private boolean mWasClicked;
-        private boolean mIsMultiClickable;
-
-        private ClickThrottlingListener(View.OnClickListener onClickListener) {
-            mOnClickListener = onClickListener;
-        }
-
-        private void setIsMultiClickable(boolean isMultiClickable) {
-            mIsMultiClickable = isMultiClickable;
-        }
-
-        private void resetWasClicked() {
-            mWasClicked = false;
-        }
-
-        @Override
-        public void onClick(View view) {
-            if (mOnClickListener == null) return;
-            if (!mIsMultiClickable && mWasClicked) return;
-
-            mOnClickListener.onClick(view);
-            mWasClicked = true;
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java
deleted file mode 100644
index 52b336b..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java
+++ /dev/null
@@ -1,144 +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.touchless.dialog;
-
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.view.InputEvent;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.StringRes;
-
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModel.ReadableBooleanPropertyKey;
-import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
-import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
-import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/** The properties that define a touchless dialog. */
-public class TouchlessDialogProperties {
-    /** Possible list item types for the list of options in the dialog. */
-    @IntDef({ListItemType.DEFAULT})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ListItemType {
-        int DEFAULT = 0;
-    }
-
-    /** Possible priorities for this set of properties. */
-    @IntDef({Priority.HIGH, Priority.MEDIUM, Priority.LOW})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Priority {
-        int HIGH = 0;
-        int MEDIUM = 1;
-        int LOW = 2;
-    }
-
-    /**
-     * A click listener for dialog actions.
-     */
-    public interface OnClickListener {
-        /**
-         * Called when a view has been clicked.
-         *
-         * @param event The input event that triggered the click.
-         */
-        void onClick(InputEvent event);
-    }
-
-    /** Properties that determine how list items are displayed in the touchless dialog. */
-    public static class DialogListItemProperties {
-        /** The icon of the dialog. */
-        public static final WritableObjectPropertyKey<Drawable> ICON =
-                new WritableObjectPropertyKey<>();
-
-        /** The text shown for the list item. */
-        public static final WritableObjectPropertyKey<String> TEXT =
-                new WritableObjectPropertyKey<>();
-
-        /** Whether this item can be clicked more than one time. */
-        public static final WritableBooleanPropertyKey MULTI_CLICKABLE =
-                new WritableBooleanPropertyKey();
-
-        /** The action to be performed when the item is selected. */
-        public static final WritableObjectPropertyKey<View.OnClickListener> CLICK_LISTENER =
-                new WritableObjectPropertyKey<>();
-
-        public static final PropertyKey[] ALL_KEYS = {ICON, TEXT, MULTI_CLICKABLE, CLICK_LISTENER};
-    }
-
-    /**
-     * Struct-like class for holding the Names for the dialog actions.
-     */
-    public static class ActionNames {
-        public @StringRes int cancel;
-        public @StringRes int select;
-        public @StringRes int alt;
-    }
-
-    /**
-     * Whether the dialog is fullscreen. If false there will be a gap at the top showing the content
-     * behind the dialog.
-     */
-    public static final ReadableBooleanPropertyKey IS_FULLSCREEN = new ReadableBooleanPropertyKey();
-
-    /**
-     * The list of options to be displayed in the dialog. These models should be using the
-     * {@link DialogListItemProperties} properties.
-     */
-    public static final WritableObjectPropertyKey<ModelList> LIST_MODELS =
-            new WritableObjectPropertyKey<>();
-
-    /** The names for the Actions. */
-    public static final WritableObjectPropertyKey<ActionNames> ACTION_NAMES =
-            new WritableObjectPropertyKey<>();
-
-    /** What will happen when cancel is triggered. */
-    public static final WritableObjectPropertyKey<OnClickListener> CANCEL_ACTION =
-            new WritableObjectPropertyKey<>();
-
-    /** Do not use, this is in the process of being deleted. */
-    @Deprecated
-    public static final WritableBooleanPropertyKey IS_CANCEL_ACTION_EXTERNAL =
-            new WritableBooleanPropertyKey();
-
-    /** What will happen when alternative action is triggered. */
-    public static final WritableObjectPropertyKey<OnClickListener> ALT_ACTION =
-            new WritableObjectPropertyKey<>();
-
-    /** Do not use, this is in the process of being deleted. */
-    @Deprecated
-    public static final WritableBooleanPropertyKey IS_ALT_ACTION_EXTERNAL =
-            new WritableBooleanPropertyKey();
-
-    /** The priority for this set of properties. */
-    public static final WritableIntPropertyKey PRIORITY = new WritableIntPropertyKey();
-
-    /** Force the title to be a single line and truncate with an ellipsis. */
-    public static final WritableBooleanPropertyKey FORCE_SINGLE_LINE_TITLE =
-            new WritableBooleanPropertyKey();
-
-    /** Force the title to have a specific text direction. See {@link View#setTextDirection}. */
-    public static final WritableIntPropertyKey TITLE_DIRECTION = new WritableIntPropertyKey();
-
-    /** Set ellipsize location for the title. See {@link TextView#setEllipsize}. */
-    public static final WritableObjectPropertyKey<TextUtils.TruncateAt> TITLE_ELLIPSIZE =
-            new WritableObjectPropertyKey<>();
-
-    public static final PropertyKey[] MINIMAL_DIALOG_KEYS = {
-            ModalDialogProperties.TITLE, ACTION_NAMES, CANCEL_ACTION, ALT_ACTION, PRIORITY};
-
-    public static final PropertyKey[] ALL_DIALOG_KEYS = PropertyModel.concatKeys(
-            ModalDialogProperties.ALL_KEYS,
-            new PropertyKey[] {ACTION_NAMES, CANCEL_ACTION, ALT_ACTION, PRIORITY, IS_FULLSCREEN,
-                    LIST_MODELS, FORCE_SINGLE_LINE_TITLE, TITLE_DIRECTION, TITLE_ELLIPSIZE});
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/permissions/TouchlessPermissionDialogModel.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/permissions/TouchlessPermissionDialogModel.java
deleted file mode 100644
index ba3d5909..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/permissions/TouchlessPermissionDialogModel.java
+++ /dev/null
@@ -1,130 +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.touchless.permissions;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-
-import androidx.annotation.StringRes;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.permissions.PermissionDialogDelegate;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.ui.UiUtils;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * This class creates the model for permission dialog in touchless mode.
- */
-public class TouchlessPermissionDialogModel {
-    public static PropertyModel getModel(
-            ModalDialogProperties.Controller controller, PermissionDialogDelegate delegate) {
-        Resources resources = delegate.getTab().getActivity().getResources();
-        TouchlessDialogProperties.ActionNames names = new TouchlessDialogProperties.ActionNames();
-        names.cancel = R.string.cancel;
-        names.select = R.string.select;
-        names.alt = 0;
-        Drawable icon =
-                ApiCompatibilityUtils.getDrawable(resources, delegate.getDrawableId()).mutate();
-        icon.setColorFilter(new PorterDuffColorFilter(
-                resources.getColor(R.color.modern_grey_700), PorterDuff.Mode.SRC_ATOP));
-        String messageText = delegate.getMessageText();
-        assert !TextUtils.isEmpty(messageText);
-
-        PropertyModel model =
-                new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS)
-                        .with(TouchlessDialogProperties.IS_FULLSCREEN, false)
-                        .with(TouchlessDialogProperties.PRIORITY,
-                                TouchlessDialogProperties.Priority.HIGH)
-                        .with(TouchlessDialogProperties.ACTION_NAMES, names)
-                        .with(TouchlessDialogProperties.ALT_ACTION, null)
-                        .with(ModalDialogProperties.MESSAGE, messageText)
-                        .with(ModalDialogProperties.TITLE, delegate.getTitleText())
-                        .with(ModalDialogProperties.TITLE_ICON, icon)
-                        .with(ModalDialogProperties.CONTROLLER, controller)
-                        .with(ModalDialogProperties.CONTENT_DESCRIPTION, delegate.getMessageText())
-                        .build();
-
-        ModelList items = new ModelList();
-        items.add(new ListItem(ListItemType.DEFAULT,
-                new PropertyModel
-                        .Builder(TouchlessDialogProperties.DialogListItemProperties.ALL_KEYS)
-                        .with(TouchlessDialogProperties.DialogListItemProperties.TEXT,
-                                delegate.getPrimaryButtonText())
-                        .with(TouchlessDialogProperties.DialogListItemProperties.CLICK_LISTENER,
-                                (v)
-                                        -> controller.onClick(
-                                                model, ModalDialogProperties.ButtonType.POSITIVE))
-                        .with(TouchlessDialogProperties.DialogListItemProperties.ICON,
-                                ApiCompatibilityUtils.getDrawable(
-                                        resources, R.drawable.ic_check_circle))
-                        .build()));
-        items.add(new ListItem(ListItemType.DEFAULT,
-                new PropertyModel
-                        .Builder(TouchlessDialogProperties.DialogListItemProperties.ALL_KEYS)
-                        .with(TouchlessDialogProperties.DialogListItemProperties.TEXT,
-                                delegate.getSecondaryButtonText())
-                        .with(TouchlessDialogProperties.DialogListItemProperties.CLICK_LISTENER,
-                                (v)
-                                        -> controller.onClick(
-                                                model, ModalDialogProperties.ButtonType.NEGATIVE))
-                        .with(TouchlessDialogProperties.DialogListItemProperties.ICON,
-                                ApiCompatibilityUtils.getDrawable(
-                                        resources, R.drawable.ic_cancel_circle))
-                        .build()));
-
-        model.set(TouchlessDialogProperties.LIST_MODELS, items);
-        model.set(TouchlessDialogProperties.CANCEL_ACTION,
-                (v) -> delegate.getTab().getActivity().getModalDialogManager().dismissDialog(model,
-                        DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE));
-        return model;
-    }
-
-    public static PropertyModel getMissingPermissionDialogModel(Context context,
-            ModalDialogProperties.Controller controller, @StringRes int messageId) {
-        Resources resources = context.getResources();
-        Drawable iconDrawable = UiUtils.getTintedDrawable(
-                context, R.drawable.exclamation_triangle, R.color.default_icon_color);
-        TouchlessDialogProperties.ActionNames names = new TouchlessDialogProperties.ActionNames();
-        names.cancel = R.string.cancel;
-        names.select = R.string.select;
-        names.alt = 0;
-        PropertyModel model = new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS)
-                                      .with(TouchlessDialogProperties.IS_FULLSCREEN, false)
-                                      .with(TouchlessDialogProperties.PRIORITY,
-                                              TouchlessDialogProperties.Priority.HIGH)
-                                      .with(ModalDialogProperties.CONTROLLER, controller)
-                                      .with(ModalDialogProperties.MESSAGE, resources, messageId)
-                                      .with(ModalDialogProperties.TITLE_ICON, iconDrawable)
-                                      .with(TouchlessDialogProperties.ACTION_NAMES, names)
-                                      .with(TouchlessDialogProperties.ALT_ACTION, null)
-                                      .build();
-        ModelList items = new ModelList();
-        items.add(new ListItem(ListItemType.DEFAULT,
-                new PropertyModel
-                        .Builder(TouchlessDialogProperties.DialogListItemProperties.ALL_KEYS)
-                        .with(TouchlessDialogProperties.DialogListItemProperties.TEXT, resources,
-                                R.string.infobar_update_permissions_button_text)
-                        .with(TouchlessDialogProperties.DialogListItemProperties.ICON, context,
-                                R.drawable.ic_check_circle)
-                        .with(TouchlessDialogProperties.DialogListItemProperties.CLICK_LISTENER,
-                                (v)
-                                        -> controller.onClick(
-                                                model, ModalDialogProperties.ButtonType.POSITIVE))
-                        .build()));
-        model.set(TouchlessDialogProperties.LIST_MODELS, items);
-        return model;
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/snackbar/BlackHoleSnackbarManager.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/snackbar/BlackHoleSnackbarManager.java
deleted file mode 100644
index fb4c55d..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/snackbar/BlackHoleSnackbarManager.java
+++ /dev/null
@@ -1,29 +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.touchless.snackbar;
-
-import android.app.Activity;
-import android.view.ViewGroup;
-
-import org.chromium.chrome.browser.snackbar.Snackbar;
-import org.chromium.chrome.browser.snackbar.SnackbarManager;
-
-/** A snackbar manager that consumes all incoming requests. */
-public class BlackHoleSnackbarManager extends SnackbarManager {
-    /**
-     * @param activity The embedding activity.
-     */
-    public BlackHoleSnackbarManager(Activity activity) {
-        super(activity, new ViewGroup(activity) {
-            @Override
-            protected void onLayout(boolean changed, int left, int top, int right, int bottom) {}
-        });
-    }
-
-    @Override
-    public void showSnackbar(Snackbar snackbar) {
-        // Intentional noop.
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHCoordinator.java
deleted file mode 100644
index 4106eb0..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHCoordinator.java
+++ /dev/null
@@ -1,41 +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.touchless.ui.iph;
-
-import android.view.LayoutInflater;
-
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.touchless.ui.tooltip.TooltipView;
-import org.chromium.chrome.touchless.R;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-
-/**
- * A helper class that controls the UI for key functions In-Product Help in NoTouch mode.
- */
-public class KeyFunctionsIPHCoordinator {
-    private KeyFunctionsIPHMediator mMediator;
-
-    public KeyFunctionsIPHCoordinator(
-            TooltipView tooltipView, ActivityTabProvider activityTabProvider) {
-        PropertyModel model = new PropertyModel.Builder(KeyFunctionsIPHProperties.ALL_KEYS)
-                                      .with(KeyFunctionsIPHProperties.TOOLTIP_VIEW, tooltipView)
-                                      .build();
-        KeyFunctionsIPHView view =
-                (KeyFunctionsIPHView) LayoutInflater.from(tooltipView.getContext())
-                        .inflate(R.layout.notouch_key_functions_view, null);
-        PropertyModelChangeProcessor.create(model, view, KeyFunctionsIPHViewBinder::bind);
-        mMediator = new KeyFunctionsIPHMediator(model, activityTabProvider,
-                ChromePreferenceManager.getInstance(),
-                TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()));
-    }
-
-    public void destroy() {
-        mMediator.destroy();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediator.java
deleted file mode 100644
index accdeff4..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediator.java
+++ /dev/null
@@ -1,139 +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.touchless.ui.iph;
-
-import androidx.annotation.IntDef;
-
-import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.dom_distiller.TabDistillabilityProvider;
-import org.chromium.chrome.browser.native_page.NativePageFactory;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.components.feature_engagement.Tracker;
-import org.chromium.components.feature_engagement.Tracker.DisplayLockHandle;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.touchless.CursorObserver;
-import org.chromium.ui.touchless.TouchlessEventHandler;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.FutureTask;
-
-/**
- * Controls the UI model for key functions IPH.
- */
-public class KeyFunctionsIPHMediator implements CursorObserver {
-    private final PropertyModel mModel;
-    private final KeyFunctionsIPHTabObserver mKeyFunctionsIPHTabObserver;
-    private final ChromePreferenceManager mChromePreferenceManager;
-    private final Tracker mTracker;
-    private FutureTask mHideTask;
-    private DisplayLockHandle mDisplayLockHandle;
-    private int mPageLoadCount;
-    private boolean mIsFallbackCursorModeOn;
-    private boolean mShowedWhenPageLoadStarted;
-
-    private static final long DISPLAY_DURATION_MS = 3000;
-
-    // For the first INTRODUCTORY_SESSIONS sessions, show the IPH every INTRODUCTORY_PAGE_LOAD_CYCLE
-    // page loads.
-    static final int INTRODUCTORY_SESSIONS = 6;
-    static final int INTRODUCTORY_PAGE_LOAD_CYCLE = 3;
-
-    @IntDef({DisplayCause.PAGE_LOAD_STARTED, DisplayCause.PAGE_LOAD_FINISHED})
-    @Retention(RetentionPolicy.SOURCE)
-    private @interface DisplayCause {
-        int PAGE_LOAD_STARTED = 0;
-        int PAGE_LOAD_FINISHED = 1;
-    }
-
-    KeyFunctionsIPHMediator(PropertyModel model, ActivityTabProvider activityTabProvider,
-            ChromePreferenceManager chromePreferenceManager, Tracker tracker) {
-        mModel = model;
-        mKeyFunctionsIPHTabObserver = new KeyFunctionsIPHTabObserver(activityTabProvider);
-        mChromePreferenceManager = chromePreferenceManager;
-        mTracker = tracker;
-        TouchlessEventHandler.addCursorObserver(this);
-    }
-
-    @Override
-    public void onCursorVisibilityChanged(boolean isCursorVisible) {}
-
-    @Override
-    public void onFallbackCursorModeToggled(boolean isOn) {
-        mIsFallbackCursorModeOn = isOn;
-        mModel.set(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE, mIsFallbackCursorModeOn);
-    }
-
-    private void show(@DisplayCause int displayCause) {
-        if (displayCause == DisplayCause.PAGE_LOAD_STARTED) {
-            mShowedWhenPageLoadStarted = false;
-            int totalSessionCount = mChromePreferenceManager.readInt(
-                    ChromePreferenceManager.TOUCHLESS_BROWSING_SESSION_COUNT);
-            if (totalSessionCount <= INTRODUCTORY_SESSIONS
-                    && mPageLoadCount % INTRODUCTORY_PAGE_LOAD_CYCLE != 1) {
-                return;
-            }
-            if (totalSessionCount > INTRODUCTORY_SESSIONS && mPageLoadCount > 1) return;
-        } else if (mShowedWhenPageLoadStarted && displayCause == DisplayCause.PAGE_LOAD_FINISHED) {
-            // If we have already shown the IPH when page load started, we should avoid showing it
-            // again when page load is finished.
-            return;
-        }
-
-        // If we are already showing this IPH, we should release the lock.
-        if (mDisplayLockHandle != null) mDisplayLockHandle.release();
-        mDisplayLockHandle = mTracker.acquireDisplayLock();
-        // If another IPH UI is currently shown, return.
-        if (mDisplayLockHandle == null) return;
-
-        if (displayCause == DisplayCause.PAGE_LOAD_STARTED) mShowedWhenPageLoadStarted = true;
-
-        if (mHideTask != null) mHideTask.cancel(false);
-        mHideTask = new FutureTask<Void>(() -> {
-            mModel.set(KeyFunctionsIPHProperties.IS_VISIBLE, false);
-            mDisplayLockHandle.release();
-            mDisplayLockHandle = null;
-            return null;
-        });
-        PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, mHideTask, DISPLAY_DURATION_MS);
-        mModel.set(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE, mIsFallbackCursorModeOn);
-        mModel.set(KeyFunctionsIPHProperties.IS_VISIBLE, true);
-    }
-
-    void destroy() {
-        TouchlessEventHandler.removeCursorObserver(this);
-        mKeyFunctionsIPHTabObserver.destroy();
-        if (mHideTask != null) mHideTask.cancel(false);
-    }
-
-    private class KeyFunctionsIPHTabObserver extends ActivityTabProvider.ActivityTabTabObserver {
-        KeyFunctionsIPHTabObserver(ActivityTabProvider tabProvider) {
-            super(tabProvider);
-        }
-
-        @Override
-        public void onPageLoadStarted(Tab tab, String url) {
-            if (NativePageFactory.isNativePageUrl(url, tab.isIncognito())) return;
-
-            mPageLoadCount++;
-            show(DisplayCause.PAGE_LOAD_STARTED);
-        }
-
-        @Override
-        public void onPageLoadFinished(Tab tab, String url) {
-            if (NativePageFactory.isNativePageUrl(url, tab.isIncognito())) return;
-
-            TabDistillabilityProvider distillabilityProvider = TabDistillabilityProvider.get(tab);
-            if (distillabilityProvider != null
-                    && distillabilityProvider.isDistillabilityDetermined()
-                    && !distillabilityProvider.isMobileOptimized()) {
-                show(DisplayCause.PAGE_LOAD_FINISHED);
-            }
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHProperties.java
deleted file mode 100644
index 18c6b95..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHProperties.java
+++ /dev/null
@@ -1,25 +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.touchless.ui.iph;
-
-import org.chromium.chrome.browser.touchless.ui.tooltip.TooltipView;
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * This class holds property keys used in key functions IPH {@link PropertyModel}.
- */
-public class KeyFunctionsIPHProperties {
-    public static final PropertyModel.WritableBooleanPropertyKey IS_CURSOR_VISIBLE =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel.WritableObjectPropertyKey<TooltipView> TOOLTIP_VIEW =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyKey[] ALL_KEYS = {IS_CURSOR_VISIBLE, IS_VISIBLE, TOOLTIP_VIEW};
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHView.java
deleted file mode 100644
index af40f68..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHView.java
+++ /dev/null
@@ -1,53 +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.touchless.ui.iph;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import org.chromium.chrome.browser.touchless.ui.tooltip.TooltipView;
-import org.chromium.chrome.touchless.R;
-
-/**
- * View responsible for displaying key functions IPH.
- */
-public class KeyFunctionsIPHView extends FrameLayout {
-    private TooltipView mTooltipView;
-    private ImageView mNavigationModeImageView;
-
-    public KeyFunctionsIPHView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public KeyFunctionsIPHView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mNavigationModeImageView = findViewById(R.id.navigation_mode_image);
-    }
-
-    void setTooltipView(TooltipView hostView) {
-        mTooltipView = hostView;
-    }
-
-    void show() {
-        mTooltipView.show(this);
-    }
-
-    void setCursorVisibility(boolean isCursorVisible) {
-        mNavigationModeImageView.setImageResource(isCursorVisible
-                        ? R.drawable.ic_spatial_navigation
-                        : R.drawable.ic_cursor_navigation);
-    }
-
-    void hide() {
-        mTooltipView.hide();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHViewBinder.java
deleted file mode 100644
index c55fa29..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHViewBinder.java
+++ /dev/null
@@ -1,29 +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.touchless.ui.iph;
-
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * This class binds the key functions IPH UI model and view.
- */
-public class KeyFunctionsIPHViewBinder {
-    public static void bind(
-            PropertyModel model, KeyFunctionsIPHView keyFunctionsIPHView, PropertyKey propertyKey) {
-        if (KeyFunctionsIPHProperties.TOOLTIP_VIEW == propertyKey) {
-            keyFunctionsIPHView.setTooltipView(model.get(KeyFunctionsIPHProperties.TOOLTIP_VIEW));
-        } else if (KeyFunctionsIPHProperties.IS_VISIBLE == propertyKey) {
-            if (model.get(KeyFunctionsIPHProperties.IS_VISIBLE)) {
-                keyFunctionsIPHView.show();
-            } else {
-                keyFunctionsIPHView.hide();
-            }
-        } else if (KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE == propertyKey) {
-            keyFunctionsIPHView.setCursorVisibility(
-                    model.get(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE));
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/PillProgressBarView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/PillProgressBarView.java
deleted file mode 100644
index 13dfeba..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/PillProgressBarView.java
+++ /dev/null
@@ -1,76 +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.touchless.ui.progressbar;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.drawable.ClipDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.widget.ProgressBar;
-
-import org.chromium.chrome.browser.util.MathUtils;
-import org.chromium.chrome.touchless.R;
-
-/**
- * A pill shaped progress bar. This view is blank for the most part, except for the bottom
- * R.dimen.notouch_progressbar_fill_height where the progress is shown.
- */
-@TargetApi(Build.VERSION_CODES.M)
-public class PillProgressBarView extends ProgressBar {
-    // The start and the end of the progress bar will be hidden behind the corner radius. This
-    // variable holds the offset progress that is hidden.
-    private int mDispalyableProgressOffset;
-
-    // ClipDrawable's max is a fixed constant 10000.
-    // http://developer.android.com/reference/android/graphics/drawable/ClipDrawable.html
-    private static final int CLIP_DRAWABLE_MAX = 10000;
-
-    public PillProgressBarView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        Drawable pillDrawable = getResources().getDrawable(R.drawable.notouch_progress_bar_pill);
-        setBackground(pillDrawable);
-        setForeground(new ClipDrawable(pillDrawable, Gravity.TOP, ClipDrawable.VERTICAL));
-        setProgressDrawable(getResources().getDrawable(R.drawable.notouch_progress_bar_drawable));
-    }
-
-    @Override
-    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        // The height of the portion of the progress bar that is visible.
-        float progressFillHeight =
-                getResources().getDimension(R.dimen.notouch_progressbar_fill_height);
-        // The radius of pill's curved corners.
-        float radius = getResources().getDimension(R.dimen.notouch_progressbar_radius);
-
-        // Clip the white foreground to only show progressFillHeight of progress bar at the bottom.
-        int clipLevel = (int) (CLIP_DRAWABLE_MAX * (getMeasuredHeight() - progressFillHeight)
-                / getMeasuredHeight());
-        getForeground().setLevel(clipLevel);
-
-        // Because of the corner radius, a portion of the progress bar is obscured from left and
-        // right by the white overlay. We should calculate this offset in order to scale the
-        // progress value accordingly.
-        float dispalyableProgressOffsetPx = radius
-                - (float) Math.sqrt(Math.pow(radius, 2) - Math.pow(radius - progressFillHeight, 2));
-        mDispalyableProgressOffset =
-                (int) ((dispalyableProgressOffsetPx * getMax()) / getMeasuredWidth());
-    }
-
-    // public synchronized methods cause a lint warning, but this needs to be synchronized because
-    // of the super method.
-    @SuppressLint("NoSynchronizedMethodCheck")
-    @Override
-    public synchronized void setProgress(int progress) {
-        // Scale progress from [0, getMax()] to
-        // [mDispalyableProgressOffset, getMax() - mDispalyableProgressOffset].
-        int scaledProgress = (int) MathUtils.map(progress, 0, getMax(), mDispalyableProgressOffset,
-                getMax() - mDispalyableProgressOffset);
-        super.setProgress(scaledProgress);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
deleted file mode 100644
index d047362..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
+++ /dev/null
@@ -1,42 +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.touchless.ui.progressbar;
-
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-
-/**
- * A class to manage the touchless progress bar UI element.
- */
-public class ProgressBarCoordinator {
-    private final ProgressBarMediator mMediator;
-
-    /**
-     * @param activityTabProvider Progress will be displayed for {@link Tab}s that are added to
-     * this {@link ActivityTabProvider}.
-     * @param progressBarView {@link ProgressBarView} used for displaying current progress and
-     * eTLD+1.
-     */
-    public ProgressBarCoordinator(
-            ProgressBarView progressBarView, ActivityTabProvider activityTabProvider) {
-        PropertyModel model = new PropertyModel.Builder(ProgressBarProperties.ALL_KEYS).build();
-        PropertyModelChangeProcessor.create(model, progressBarView, ProgressBarViewBinder::bind);
-        mMediator = new ProgressBarMediator(model, activityTabProvider);
-    }
-
-    public void onActivityStart() {
-        mMediator.onActivityStart();
-    }
-
-    public void skipShowingOnNextActivityStart() {
-        mMediator.skipShowingOnNextActivityStart();
-    }
-
-    public void destroy() {
-        mMediator.destroy();
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
deleted file mode 100644
index 1ca16cd..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
+++ /dev/null
@@ -1,171 +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.touchless.ui.progressbar;
-
-import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.native_page.NativePageFactory;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.touchless.TouchlessUrlUtilities;
-import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.ui.modelutil.PropertyModel;
-
-import java.util.concurrent.FutureTask;
-
-/**
- * This part of the touchless progress bar component controls the UI model based on the status of
- * the current tab and key events.
- */
-public class ProgressBarMediator {
-    private final PropertyModel mModel;
-    private final ProgressBarTabObserver mProgressBarTabObserver;
-    private FutureTask mHideTask;
-    private boolean mCanHideProgressBar;
-    private boolean mWasDisplayedForMinimumDuration;
-    private boolean mSkipShowingOnNextActivityStart;
-
-    private static final int MINIMUM_DISPLAY_DURATION_MS = 3 * 1000;
-    private static final int MAXIMUM_PROGRESS = 100;
-
-    ProgressBarMediator(PropertyModel model, ActivityTabProvider activityTabProvider) {
-        mProgressBarTabObserver = new ProgressBarTabObserver(activityTabProvider);
-        mModel = model;
-    }
-
-    void skipShowingOnNextActivityStart() {
-        mSkipShowingOnNextActivityStart = true;
-    }
-
-    void onActivityStart() {
-        if (mSkipShowingOnNextActivityStart) {
-            mSkipShowingOnNextActivityStart = false;
-            return;
-        }
-
-        if (mModel.get(ProgressBarProperties.IS_ENABLED)) show();
-    }
-
-    private void show() {
-        if (mHideTask != null) mHideTask.cancel(false);
-        mHideTask = new FutureTask<Void>(() -> {
-            mWasDisplayedForMinimumDuration = true;
-            hide();
-            return null;
-        });
-        PostTask.postDelayedTask(
-                UiThreadTaskTraits.DEFAULT, mHideTask, MINIMUM_DISPLAY_DURATION_MS);
-        mModel.set(ProgressBarProperties.IS_VISIBLE, true);
-    }
-
-    private void hide() {
-        if (!mCanHideProgressBar || !mWasDisplayedForMinimumDuration) return;
-
-        mModel.set(ProgressBarProperties.IS_VISIBLE, false);
-    }
-
-    private void startLoadProgress() {
-        mWasDisplayedForMinimumDuration = false;
-        mCanHideProgressBar = false;
-
-        mModel.set(ProgressBarProperties.PROGRESS_FRACTION, 0f);
-        show();
-    }
-
-    private void finishLoadProgress() {
-        mCanHideProgressBar = true;
-        hide();
-    }
-
-    private void updateLoadProgress(int progress) {
-        mModel.set(ProgressBarProperties.PROGRESS_FRACTION, progress / ((float) MAXIMUM_PROGRESS));
-        if (progress == MAXIMUM_PROGRESS) finishLoadProgress();
-    }
-
-    void destroy() {
-        if (mHideTask != null) mHideTask.cancel(false);
-        mProgressBarTabObserver.destroy();
-    }
-
-    // This class follows the same logic used in ToolbarManager#mTabObserver for updating the shown
-    // URL as well as updating the progress bar.
-    private class ProgressBarTabObserver extends ActivityTabProvider.ActivityTabTabObserver {
-        ProgressBarTabObserver(ActivityTabProvider tabProvider) {
-            super(tabProvider);
-        }
-
-        @Override
-        public void onDidStartNavigation(Tab tab, NavigationHandle navigation) {
-            if (!navigation.isInMainFrame()) return;
-
-            if (tab.getWebContents() != null
-                    && tab.getWebContents().getNavigationController() != null
-                    && tab.getWebContents().getNavigationController().isInitialNavigation()) {
-                updateUrl(tab);
-            }
-
-            if (navigation.isSameDocument()) return;
-
-            if (NativePageFactory.isNativePageUrl(navigation.getUrl(), tab.isIncognito())) {
-                mModel.set(ProgressBarProperties.IS_ENABLED, false);
-                finishLoadProgress();
-                return;
-            }
-
-            mModel.set(ProgressBarProperties.IS_ENABLED, true);
-            startLoadProgress();
-            updateLoadProgress(tab.getProgress());
-        }
-
-        @Override
-        public void onUrlUpdated(Tab tab) {
-            updateUrl(tab);
-        }
-
-        @Override
-        public void onLoadStarted(Tab tab, boolean toDifferentDocument) {
-            updateUrl(tab);
-        }
-
-        @Override
-        public void onLoadStopped(Tab tab, boolean toDifferentDocument) {
-            if (!toDifferentDocument) return;
-
-            // If we made some progress, fast-forward to complete.
-            if (tab.getProgress() < MAXIMUM_PROGRESS) {
-                updateLoadProgress(MAXIMUM_PROGRESS);
-            } else {
-                finishLoadProgress();
-            }
-        }
-
-        @Override
-        public void onLoadProgressChanged(Tab tab, int progress) {
-            if (NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncognito())) return;
-
-            updateLoadProgress(progress);
-        }
-
-        @Override
-        public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {
-            if (!didStartLoad) return;
-
-            updateUrl(tab);
-            if (didFinishLoad) finishLoadProgress();
-        }
-
-        @Override
-        public void onCrash(Tab tab) {
-            finishLoadProgress();
-        }
-
-        private void updateUrl(Tab tab) {
-            if (NativePageFactory.isNativePageUrl(tab.getUrl(), tab.isIncognito())) return;
-
-            mModel.set(ProgressBarProperties.URL,
-                    TouchlessUrlUtilities.getUrlForDisplay(tab.getUrl()));
-        }
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java
deleted file mode 100644
index 2bc0035..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.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.touchless.ui.progressbar;
-
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * This class holds property keys used in the Loading Bar {@link PropertyModel}.
- */
-public class ProgressBarProperties {
-    public static final PropertyModel.WritableFloatPropertyKey PROGRESS_FRACTION =
-            new PropertyModel.WritableFloatPropertyKey();
-
-    public static final PropertyModel.WritableBooleanPropertyKey IS_ENABLED =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
-            new PropertyModel.WritableBooleanPropertyKey();
-
-    public static final PropertyModel.WritableObjectPropertyKey<String> URL =
-            new PropertyModel.WritableObjectPropertyKey<>();
-
-    public static final PropertyKey[] ALL_KEYS = {PROGRESS_FRACTION, IS_ENABLED, IS_VISIBLE, URL};
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java
deleted file mode 100644
index ee3b76e..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java
+++ /dev/null
@@ -1,65 +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.touchless.ui.progressbar;
-
-import android.content.Context;
-import android.support.design.widget.CoordinatorLayout;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import org.chromium.chrome.touchless.R;
-
-/**
- * View responsible for displaying touchless progress bar UI. It displays the progress and current
- * eTLD+1.
- */
-public class ProgressBarView extends RelativeLayout {
-    private TextView mUrlTextView;
-    private PillProgressBarView mProgressBar;
-
-    public ProgressBarView(Context context) {
-        super(context);
-        init();
-    }
-
-    public ProgressBarView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public ProgressBarView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        init();
-    }
-
-    private void init() {
-        CoordinatorLayout.LayoutParams layoutParams =
-                new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.WRAP_CONTENT,
-                        CoordinatorLayout.LayoutParams.WRAP_CONTENT);
-        layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
-        setLayoutParams(layoutParams);
-
-        inflate(getContext(), R.layout.notouch_progress_bar_view, this);
-        mProgressBar = findViewById(R.id.notouch_progress_bar_view);
-        mUrlTextView = findViewById(R.id.notouch_url_text_view);
-
-        setVisibility(false);
-    }
-
-    void setProgress(float progressFraction) {
-        assert progressFraction >= 0f && progressFraction <= 1f;
-        mProgressBar.setProgress((int) (progressFraction * mProgressBar.getMax()));
-    }
-
-    void setUrlText(String text) {
-        mUrlTextView.setText(text);
-    }
-
-    void setVisibility(boolean isVisible) {
-        setVisibility(isVisible ? VISIBLE : GONE);
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java
deleted file mode 100644
index 84b7292..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java
+++ /dev/null
@@ -1,33 +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.touchless.ui.progressbar;
-
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * This class binds the touchless progress bar {@link PropertyModel} to {@link ProgressBarView}.
- */
-public class ProgressBarViewBinder {
-    public static void bind(
-            PropertyModel model, ProgressBarView progressBarView, PropertyKey propertyKey) {
-        if (ProgressBarProperties.PROGRESS_FRACTION == propertyKey) {
-            progressBarView.setProgress(model.get(ProgressBarProperties.PROGRESS_FRACTION));
-        } else if (ProgressBarProperties.IS_ENABLED == propertyKey) {
-            if (!model.get(ProgressBarProperties.IS_ENABLED)) {
-                progressBarView.setVisibility(false);
-            } else if (model.getAllProperties().contains(ProgressBarProperties.IS_VISIBLE)) {
-                progressBarView.setVisibility(model.get(ProgressBarProperties.IS_VISIBLE));
-            }
-        } else if (ProgressBarProperties.IS_VISIBLE == propertyKey) {
-            if (!model.getAllProperties().contains(ProgressBarProperties.IS_ENABLED)
-                    || model.get(ProgressBarProperties.IS_ENABLED)) {
-                progressBarView.setVisibility(model.get(ProgressBarProperties.IS_VISIBLE));
-            }
-        } else if (ProgressBarProperties.URL == propertyKey) {
-            progressBarView.setUrlText(model.get(ProgressBarProperties.URL));
-        }
-    }
-}
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/tooltip/TooltipView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/tooltip/TooltipView.java
deleted file mode 100644
index ffe39b0f..0000000
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/tooltip/TooltipView.java
+++ /dev/null
@@ -1,60 +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.touchless.ui.tooltip;
-
-import android.content.Context;
-import android.support.design.widget.CoordinatorLayout;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import org.chromium.chrome.touchless.R;
-
-/**
- * Responsible for displaying tooltips in NoTouch mode.
- */
-public class TooltipView extends FrameLayout {
-    private ViewGroup mContainerView;
-
-    public TooltipView(Context context) {
-        super(context);
-        init();
-    }
-
-    public TooltipView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public TooltipView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        init();
-    }
-
-    private void init() {
-        CoordinatorLayout.LayoutParams layoutParams =
-                new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.WRAP_CONTENT,
-                        CoordinatorLayout.LayoutParams.WRAP_CONTENT);
-        layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
-        layoutParams.bottomMargin =
-                (int) getResources().getDimension(R.dimen.notouch_tooltip_margin_bottom);
-        setLayoutParams(layoutParams);
-        mContainerView = (ViewGroup) inflate(getContext(), R.layout.notouch_tooltip_view, null);
-        mContainerView.setVisibility(GONE);
-        addView(mContainerView);
-    }
-
-    public void show(View view) {
-        mContainerView.removeAllViews();
-        mContainerView.addView(view);
-        mContainerView.setVisibility(VISIBLE);
-    }
-
-    public void hide() {
-        mContainerView.setVisibility(GONE);
-    }
-}
diff --git a/chrome/android/touchless/java/strings/touchless_strings.grd b/chrome/android/touchless/java/strings/touchless_strings.grd
deleted file mode 100644
index 5636a9a..0000000
--- a/chrome/android/touchless/java/strings/touchless_strings.grd
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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. -->
-
-<grit base_dir="." latest_public_release="0" current_release="1"
-      source_lang_id="en" enc_check="möl">
-  <outputs>
-    <output filename="values/touchless_strings.xml" lang="en" type="android" />
-    <output filename="values-am/touchless_strings.xml" lang="am" type="android" />
-    <output filename="values-ar/touchless_strings.xml" lang="ar" type="android" />
-    <output filename="values-bg/touchless_strings.xml" lang="bg" type="android" />
-    <output filename="values-bn/touchless_strings.xml" lang="bn" type="android" />
-    <output filename="values-ca/touchless_strings.xml" lang="ca" type="android" />
-    <output filename="values-cs/touchless_strings.xml" lang="cs" type="android" />
-    <output filename="values-da/touchless_strings.xml" lang="da" type="android" />
-    <output filename="values-de/touchless_strings.xml" lang="de" type="android" />
-    <output filename="values-el/touchless_strings.xml" lang="el" type="android" />
-    <output filename="values-en-rGB/touchless_strings.xml" lang="en-GB" type="android" />
-    <output filename="values-es/touchless_strings.xml" lang="es" type="android" />
-    <output filename="values-es-rUS/touchless_strings.xml" lang="es-419" type="android" />
-    <output filename="values-et/touchless_strings.xml" lang="et" type="android" />
-    <output filename="values-fa/touchless_strings.xml" lang="fa" type="android" />
-    <output filename="values-fi/touchless_strings.xml" lang="fi" type="android" />
-    <output filename="values-tl/touchless_strings.xml" lang="fil" type="android" />
-    <output filename="values-fr/touchless_strings.xml" lang="fr" type="android" />
-    <output filename="values-gu/touchless_strings.xml" lang="gu" type="android" />
-    <output filename="values-hi/touchless_strings.xml" lang="hi" type="android" />
-    <output filename="values-hr/touchless_strings.xml" lang="hr" type="android" />
-    <output filename="values-hu/touchless_strings.xml" lang="hu" type="android" />
-    <output filename="values-in/touchless_strings.xml" lang="id" type="android" />
-    <output filename="values-it/touchless_strings.xml" lang="it" type="android" />
-    <output filename="values-iw/touchless_strings.xml" lang="iw" type="android" />
-    <output filename="values-ja/touchless_strings.xml" lang="ja" type="android" />
-    <output filename="values-kn/touchless_strings.xml" lang="kn" type="android" />
-    <output filename="values-ko/touchless_strings.xml" lang="ko" type="android" />
-    <output filename="values-lt/touchless_strings.xml" lang="lt" type="android" />
-    <output filename="values-lv/touchless_strings.xml" lang="lv" type="android" />
-    <output filename="values-ml/touchless_strings.xml" lang="ml" type="android" />
-    <output filename="values-mr/touchless_strings.xml" lang="mr" type="android" />
-    <output filename="values-ms/touchless_strings.xml" lang="ms" type="android" />
-    <output filename="values-nl/touchless_strings.xml" lang="nl" type="android" />
-    <output filename="values-nb/touchless_strings.xml" lang="no" type="android" />
-    <output filename="values-pl/touchless_strings.xml" lang="pl" type="android" />
-    <output filename="values-pt-rBR/touchless_strings.xml" lang="pt-BR" type="android" />
-    <output filename="values-pt-rPT/touchless_strings.xml" lang="pt-PT" type="android" />
-    <output filename="values-ro/touchless_strings.xml" lang="ro" type="android" />
-    <output filename="values-ru/touchless_strings.xml" lang="ru" type="android" />
-    <output filename="values-sk/touchless_strings.xml" lang="sk" type="android" />
-    <output filename="values-sl/touchless_strings.xml" lang="sl" type="android" />
-    <output filename="values-sr/touchless_strings.xml" lang="sr" type="android" />
-    <output filename="values-sv/touchless_strings.xml" lang="sv" type="android" />
-    <output filename="values-sw/touchless_strings.xml" lang="sw" type="android" />
-    <output filename="values-ta/touchless_strings.xml" lang="ta" type="android" />
-    <output filename="values-te/touchless_strings.xml" lang="te" type="android" />
-    <output filename="values-th/touchless_strings.xml" lang="th" type="android" />
-    <output filename="values-tr/touchless_strings.xml" lang="tr" type="android" />
-    <output filename="values-uk/touchless_strings.xml" lang="uk" type="android" />
-    <output filename="values-vi/touchless_strings.xml" lang="vi" type="android" />
-    <output filename="values-zh-rCN/touchless_strings.xml" lang="zh-CN" type="android" />
-    <output filename="values-zh-rTW/touchless_strings.xml" lang="zh-TW" type="android" />
-  </outputs>
-  <translations>
-    <file lang="am" path="translations/touchless_strings_am.xtb" />
-    <file lang="ar" path="translations/touchless_strings_ar.xtb" />
-    <file lang="bg" path="translations/touchless_strings_bg.xtb" />
-    <file lang="bn" path="translations/touchless_strings_bn.xtb" />
-    <file lang="ca" path="translations/touchless_strings_ca.xtb" />
-    <file lang="cs" path="translations/touchless_strings_cs.xtb" />
-    <file lang="da" path="translations/touchless_strings_da.xtb" />
-    <file lang="de" path="translations/touchless_strings_de.xtb" />
-    <file lang="el" path="translations/touchless_strings_el.xtb" />
-    <file lang="en-GB" path="translations/touchless_strings_en-GB.xtb" />
-    <file lang="es" path="translations/touchless_strings_es.xtb" />
-    <file lang="es-419" path="translations/touchless_strings_es-419.xtb" />
-    <file lang="et" path="translations/touchless_strings_et.xtb" />
-    <file lang="fa" path="translations/touchless_strings_fa.xtb" />
-    <file lang="fi" path="translations/touchless_strings_fi.xtb" />
-    <file lang="fil" path="translations/touchless_strings_fil.xtb" />
-    <file lang="fr" path="translations/touchless_strings_fr.xtb" />
-    <file lang="gu" path="translations/touchless_strings_gu.xtb" />
-    <file lang="hi" path="translations/touchless_strings_hi.xtb" />
-    <file lang="hr" path="translations/touchless_strings_hr.xtb" />
-    <file lang="hu" path="translations/touchless_strings_hu.xtb" />
-    <file lang="id" path="translations/touchless_strings_id.xtb" />
-    <file lang="it" path="translations/touchless_strings_it.xtb" />
-    <file lang="iw" path="translations/touchless_strings_iw.xtb" />
-    <file lang="ja" path="translations/touchless_strings_ja.xtb" />
-    <file lang="ko" path="translations/touchless_strings_ko.xtb" />
-    <file lang="kn" path="translations/touchless_strings_kn.xtb" />
-    <file lang="lt" path="translations/touchless_strings_lt.xtb" />
-    <file lang="lv" path="translations/touchless_strings_lv.xtb" />
-    <file lang="ml" path="translations/touchless_strings_ml.xtb" />
-    <file lang="mr" path="translations/touchless_strings_mr.xtb" />
-    <file lang="ms" path="translations/touchless_strings_ms.xtb" />
-    <file lang="nl" path="translations/touchless_strings_nl.xtb" />
-    <file lang="no" path="translations/touchless_strings_no.xtb" />
-    <file lang="pl" path="translations/touchless_strings_pl.xtb" />
-    <file lang="pt-BR" path="translations/touchless_strings_pt-BR.xtb" />
-    <file lang="pt-PT" path="translations/touchless_strings_pt-PT.xtb" />
-    <file lang="ro" path="translations/touchless_strings_ro.xtb" />
-    <file lang="ru" path="translations/touchless_strings_ru.xtb" />
-    <file lang="sk" path="translations/touchless_strings_sk.xtb" />
-    <file lang="sl" path="translations/touchless_strings_sl.xtb" />
-    <file lang="sr" path="translations/touchless_strings_sr.xtb" />
-    <file lang="sv" path="translations/touchless_strings_sv.xtb" />
-    <file lang="sw" path="translations/touchless_strings_sw.xtb" />
-    <file lang="ta" path="translations/touchless_strings_ta.xtb" />
-    <file lang="te" path="translations/touchless_strings_te.xtb" />
-    <file lang="th" path="translations/touchless_strings_th.xtb" />
-    <file lang="tr" path="translations/touchless_strings_tr.xtb" />
-    <file lang="uk" path="translations/touchless_strings_uk.xtb" />
-    <file lang="vi" path="translations/touchless_strings_vi.xtb" />
-    <file lang="zh-CN" path="translations/touchless_strings_zh-CN.xtb" />
-    <file lang="zh-TW" path="translations/touchless_strings_zh-TW.xtb" />
-  </translations>
-  <release seq="1">
-    <messages fallback_to_english="true">
-      <message name="IDS_OPEN_LAST_TAB_JUST_NOW" desc="The present time or moment (noun). Used instead of a timestamp when the site was visited less than a minute ago. [CHAR_LIMIT=12]">
-        Now
-      </message>
-      <message name="IDS_NTP_ALL_APPS" desc="Text to accompany icon that will navigate to a page showing a categorized view of different applications or sites">
-        Explore apps
-      </message>
-      <message name="IDS_MORE_ARTICLES" desc="Message at the bottom of a list of news items prompting the user to load more.">
-        More articles
-      </message>
-      <!-- TODO(crbug.com/957789): Remove this from downstream. -->
-      <message name="IDS_MENU_ADD_TO_APPS" desc="Text to accompany icon that will navigate to a page showing a categorized view of different applications or sites">
-        Add to My apps
-      </message>
-      <message name="IDS_DINO_GAME_TITLE" desc="Title for the offline dino game that will appear as an icon in the launcher" translateable="false">
-        Chrome Fun
-      </message>
-    </messages>
-  </release>
-</grit>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_am.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_am.xtb
deleted file mode 100644
index 6de1c40..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_am.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="am">
-<translation id="146329143005354472">ወደ የእኔ መተግበሪያዎች አክል</translation>
-<translation id="2169830938017475061">አሁን</translation>
-<translation id="3669009212293447190">ተጨማሪ ጽሑፎች</translation>
-<translation id="6664816932026096408">መተግበሪያዎችን ያስሱ</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ar.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ar.xtb
deleted file mode 100644
index aaeda58b..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ar.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ar">
-<translation id="146329143005354472">إضافة هذا الموقع إلى "تطبيقاتي"</translation>
-<translation id="2169830938017475061">الآن</translation>
-<translation id="3669009212293447190">مقالات أخرى</translation>
-<translation id="6664816932026096408">التعرّف على التطبيقات</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_bg.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_bg.xtb
deleted file mode 100644
index f948850..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_bg.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="bg">
-<translation id="146329143005354472">Добавяне към „Моите приложения“</translation>
-<translation id="2169830938017475061">Сега</translation>
-<translation id="3669009212293447190">Още статии</translation>
-<translation id="6664816932026096408">Разглеждане на приложения</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_bn.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_bn.xtb
deleted file mode 100644
index 9323fd7..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_bn.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="bn">
-<translation id="146329143005354472">আমার অ্যাপে যোগ করুন</translation>
-<translation id="2169830938017475061">এখনই</translation>
-<translation id="3669009212293447190">আরও নিবন্ধ</translation>
-<translation id="6664816932026096408">কী কী অ্যাপ আছে দেখুন</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ca.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ca.xtb
deleted file mode 100644
index 32ca371..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ca.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ca">
-<translation id="146329143005354472">Afegeix a Les meves aplicacions</translation>
-<translation id="2169830938017475061">Ara</translation>
-<translation id="3669009212293447190">Més articles</translation>
-<translation id="6664816932026096408">Explora les aplicacions</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_cs.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_cs.xtb
deleted file mode 100644
index 1906e65..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_cs.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="cs">
-<translation id="146329143005354472">Přidat do seznamu Moje aplikace</translation>
-<translation id="2169830938017475061">Teď</translation>
-<translation id="3669009212293447190">Další články</translation>
-<translation id="6664816932026096408">Prozkoumat aplikace</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_da.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_da.xtb
deleted file mode 100644
index 9e2bed3..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_da.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="da">
-<translation id="146329143005354472">Føj til Mine apps</translation>
-<translation id="2169830938017475061">Nu</translation>
-<translation id="3669009212293447190">Flere artikler</translation>
-<translation id="6664816932026096408">Se flere apps</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_de.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_de.xtb
deleted file mode 100644
index 6414171..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_de.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="de">
-<translation id="146329143005354472">Zu "Meine Apps" hinzufügen</translation>
-<translation id="2169830938017475061">Jetzt</translation>
-<translation id="3669009212293447190">Weitere Artikel</translation>
-<translation id="6664816932026096408">Apps entdecken</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_el.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_el.xtb
deleted file mode 100644
index 622f583..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_el.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="el">
-<translation id="146329143005354472">Προσθήκη στη λίστα Οι εφαρμογές μου</translation>
-<translation id="2169830938017475061">Τώρα</translation>
-<translation id="3669009212293447190">Περισσότερα άρθρα</translation>
-<translation id="6664816932026096408">Εξερεύνηση εφαρμογών</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_en-GB.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_en-GB.xtb
deleted file mode 100644
index 6d923f0..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_en-GB.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="en-GB">
-<translation id="146329143005354472">Add to My apps</translation>
-<translation id="2169830938017475061">Now</translation>
-<translation id="3669009212293447190">More articles</translation>
-<translation id="6664816932026096408">Explore apps</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_en.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_en.xtb
deleted file mode 100644
index e0336b5..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_en.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="en"></translationbundle>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_es-419.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_es-419.xtb
deleted file mode 100644
index b47b24a..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_es-419.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="es-419">
-<translation id="146329143005354472">Agregar a Mis apps</translation>
-<translation id="2169830938017475061">Ahora</translation>
-<translation id="3669009212293447190">Más artículos</translation>
-<translation id="6664816932026096408">Explorar las apps</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_es.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_es.xtb
deleted file mode 100644
index 3cecf31..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_es.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="es">
-<translation id="146329143005354472">Añadir a Mis aplicaciones</translation>
-<translation id="2169830938017475061">Ahora</translation>
-<translation id="3669009212293447190">Más artículos</translation>
-<translation id="6664816932026096408">Explorar aplicaciones</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_et.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_et.xtb
deleted file mode 100644
index 7da4e82..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_et.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="et">
-<translation id="146329143005354472">Lisa jaotisesse Minu rakendused</translation>
-<translation id="2169830938017475061">Kohe</translation>
-<translation id="3669009212293447190">Veel artikleid</translation>
-<translation id="6664816932026096408">Avastage rakendusi</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_fa.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_fa.xtb
deleted file mode 100644
index 5142039..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_fa.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="fa">
-<translation id="146329143005354472">افزودن به برنامه‌های من</translation>
-<translation id="2169830938017475061">اکنون</translation>
-<translation id="3669009212293447190">مقاله‌های بیشتر</translation>
-<translation id="6664816932026096408">کاوش برنامه‌ها</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_fi.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_fi.xtb
deleted file mode 100644
index 0787173..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_fi.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="fi">
-<translation id="146329143005354472">Lisää Omiin sovelluksiin</translation>
-<translation id="2169830938017475061">Nyt</translation>
-<translation id="3669009212293447190">Lisää artikkeleja</translation>
-<translation id="6664816932026096408">Tutustu sovelluksiin</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb
deleted file mode 100644
index 025d9fc6..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_fil.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="fil">
-<translation id="146329143005354472">Idagdag sa Aking mga app</translation>
-<translation id="2169830938017475061">Ngayon</translation>
-<translation id="3669009212293447190">Higit pang artikulo</translation>
-<translation id="6664816932026096408">I-explore ang mga app</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_fr.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_fr.xtb
deleted file mode 100644
index 3bed61a6..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_fr.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="fr">
-<translation id="146329143005354472">Ajouter à mes applications</translation>
-<translation id="2169830938017475061">Maintenant</translation>
-<translation id="3669009212293447190">Autres articles</translation>
-<translation id="6664816932026096408">Découvrir des applications</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_gu.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_gu.xtb
deleted file mode 100644
index e36c124..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_gu.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="gu">
-<translation id="146329143005354472">મારી ઍપમાં ઉમેરો</translation>
-<translation id="2169830938017475061">હમણાં</translation>
-<translation id="3669009212293447190">વધુ લેખો</translation>
-<translation id="6664816932026096408">ઍપ વિશે જાણકારી મેળવો</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_hi.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_hi.xtb
deleted file mode 100644
index e317dd0..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_hi.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="hi">
-<translation id="146329143005354472">मेरे ऐप्लिकेशन में जोड़ें</translation>
-<translation id="2169830938017475061">अभी</translation>
-<translation id="3669009212293447190">ज़्यादा लेख</translation>
-<translation id="6664816932026096408">ऐप्लिकेशन खोजें</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_hr.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_hr.xtb
deleted file mode 100644
index 517f8d4..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_hr.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="hr">
-<translation id="146329143005354472">Dodaj u Moje aplikacije</translation>
-<translation id="2169830938017475061">Sad</translation>
-<translation id="3669009212293447190">Više članaka</translation>
-<translation id="6664816932026096408">Istražite aplikacije</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_hu.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_hu.xtb
deleted file mode 100644
index 3a7c348..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_hu.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="hu">
-<translation id="146329143005354472">Hozzáadás a saját alkalmazásokhoz</translation>
-<translation id="2169830938017475061">Most</translation>
-<translation id="3669009212293447190">További cikkek</translation>
-<translation id="6664816932026096408">Alkalmazások felfedezése</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_id.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_id.xtb
deleted file mode 100644
index a752d9f..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_id.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="id">
-<translation id="146329143005354472">Tambahkan ke Aplikasi saya</translation>
-<translation id="2169830938017475061">Sekarang</translation>
-<translation id="3669009212293447190">Artikel lainnya</translation>
-<translation id="6664816932026096408">Temukan aplikasi</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_in.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_in.xtb
deleted file mode 100644
index b7e5530..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_in.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="in"></translationbundle>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_it.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_it.xtb
deleted file mode 100644
index 26eaa44d..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_it.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="it">
-<translation id="146329143005354472">Aggiungi a Le mie app</translation>
-<translation id="2169830938017475061">Ora</translation>
-<translation id="3669009212293447190">Altri articoli</translation>
-<translation id="6664816932026096408">Esplora le app</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_iw.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_iw.xtb
deleted file mode 100644
index 6fab6baea..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_iw.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="iw">
-<translation id="146329143005354472">הוספה לאפליקציות שלי</translation>
-<translation id="2169830938017475061">עכשיו</translation>
-<translation id="3669009212293447190">מאמרים נוספים</translation>
-<translation id="6664816932026096408">הכרת אפליקציות</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ja.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ja.xtb
deleted file mode 100644
index bfccf74..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ja.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ja">
-<translation id="146329143005354472">マイアプリに追加</translation>
-<translation id="2169830938017475061">たった今</translation>
-<translation id="3669009212293447190">その他の記事</translation>
-<translation id="6664816932026096408">アプリを探す</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_kn.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_kn.xtb
deleted file mode 100644
index 80fc0a5b..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_kn.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="kn">
-<translation id="146329143005354472">ನನ್ನ ಆ್ಯಪ್‌ಗಳಿಗೆ ಸೇರಿಸಿ</translation>
-<translation id="2169830938017475061">ಈಗ</translation>
-<translation id="3669009212293447190">ಇನ್ನಷ್ಟು ಲೇಖನಗಳು</translation>
-<translation id="6664816932026096408">ಆ್ಯಪ್‌ಗಳನ್ನು ಎಕ್ಸ್‌ಪ್ಲೋರ್ ಮಾಡಿ</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ko.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ko.xtb
deleted file mode 100644
index e096c3b6..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ko.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ko">
-<translation id="146329143005354472">내 앱에 추가</translation>
-<translation id="2169830938017475061">방금</translation>
-<translation id="3669009212293447190">더보기</translation>
-<translation id="6664816932026096408">앱 살펴보기</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_lt.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_lt.xtb
deleted file mode 100644
index ec4865e..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_lt.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="lt">
-<translation id="146329143005354472">Pridėti prie skilties „Mano programos“</translation>
-<translation id="2169830938017475061">Dabar</translation>
-<translation id="3669009212293447190">Daugiau straipsnių</translation>
-<translation id="6664816932026096408">Naršyti programas</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_lv.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_lv.xtb
deleted file mode 100644
index c896012..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_lv.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="lv">
-<translation id="146329143005354472">Pievienot sadaļai Manas lietotnes</translation>
-<translation id="2169830938017475061">Tikko</translation>
-<translation id="3669009212293447190">Citi raksti</translation>
-<translation id="6664816932026096408">Izpētīt lietotnes</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ml.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ml.xtb
deleted file mode 100644
index 114e9a2..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ml.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ml">
-<translation id="146329143005354472">എൻ്റെ ആപ്പുകളിലേക്ക് ചേർക്കുക</translation>
-<translation id="2169830938017475061">ഇപ്പോൾ</translation>
-<translation id="3669009212293447190">കൂടുതൽ ലേഖനങ്ങൾ</translation>
-<translation id="6664816932026096408">ആപ്പുകൾ അടുത്തറിയുക</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_mr.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_mr.xtb
deleted file mode 100644
index 5ea9b4c..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_mr.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="mr">
-<translation id="146329143005354472">माझी अ‍ॅप्स मध्ये जोडा</translation>
-<translation id="2169830938017475061">आता</translation>
-<translation id="3669009212293447190">आणखी लेख</translation>
-<translation id="6664816932026096408">अ‍ॅप्स एक्सप्लोर करा</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ms.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ms.xtb
deleted file mode 100644
index e9b5b8c..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ms.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ms">
-<translation id="146329143005354472">Tambahkan pada Apl saya</translation>
-<translation id="2169830938017475061">Sekarang</translation>
-<translation id="3669009212293447190">Lagi artikel</translation>
-<translation id="6664816932026096408">Terokai apl</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_nb.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_nb.xtb
deleted file mode 100644
index 35c11a7..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_nb.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="nb"></translationbundle>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_nl.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_nl.xtb
deleted file mode 100644
index 255bb60..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_nl.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="nl">
-<translation id="146329143005354472">Toevoegen aan 'Mijn apps'</translation>
-<translation id="2169830938017475061">Nu</translation>
-<translation id="3669009212293447190">Meer artikelen</translation>
-<translation id="6664816932026096408">Apps ontdekken</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_no.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_no.xtb
deleted file mode 100644
index b52704c..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_no.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="no">
-<translation id="146329143005354472">Legg til i Mine apper</translation>
-<translation id="2169830938017475061">Nå</translation>
-<translation id="3669009212293447190">Flere artikler</translation>
-<translation id="6664816932026096408">Utforsk apper</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_pl.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_pl.xtb
deleted file mode 100644
index c95a87f..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_pl.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="pl">
-<translation id="146329143005354472">Dodaj do Moich aplikacji</translation>
-<translation id="2169830938017475061">Przed chwilą</translation>
-<translation id="3669009212293447190">Więcej artykułów</translation>
-<translation id="6664816932026096408">Poznaj aplikacje</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_pt-BR.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_pt-BR.xtb
deleted file mode 100644
index 502db572..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_pt-BR.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="pt-BR">
-<translation id="146329143005354472">Adicionar a "Meus apps"</translation>
-<translation id="2169830938017475061">Agora</translation>
-<translation id="3669009212293447190">Mais artigos</translation>
-<translation id="6664816932026096408">Conheça os apps</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_pt-PT.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_pt-PT.xtb
deleted file mode 100644
index 461610a..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_pt-PT.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="pt-PT">
-<translation id="146329143005354472">Adicionar a As minhas aplicações</translation>
-<translation id="2169830938017475061">Agora</translation>
-<translation id="3669009212293447190">Mais artigos</translation>
-<translation id="6664816932026096408">Explorar aplicações</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_pt.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_pt.xtb
deleted file mode 100644
index e77f7c96..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_pt.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="pt"></translationbundle>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ro.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ro.xtb
deleted file mode 100644
index 798c4dd..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ro.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ro">
-<translation id="146329143005354472">Adaugă în Aplicațiile mele</translation>
-<translation id="2169830938017475061">Acum</translation>
-<translation id="3669009212293447190">Mai multe articole</translation>
-<translation id="6664816932026096408">Explorează aplicațiile</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ru.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ru.xtb
deleted file mode 100644
index 66415e4..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ru.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ru">
-<translation id="146329143005354472">Добавить в "Мои приложения"</translation>
-<translation id="2169830938017475061">Сейчас</translation>
-<translation id="3669009212293447190">Ещё статьи</translation>
-<translation id="6664816932026096408">Открыть каталог</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_sk.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_sk.xtb
deleted file mode 100644
index 5508aec..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_sk.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="sk">
-<translation id="146329143005354472">Pridať do Mojich aplikácií</translation>
-<translation id="2169830938017475061">Teraz</translation>
-<translation id="3669009212293447190">Ďalšie články</translation>
-<translation id="6664816932026096408">Preskúmať aplikácie</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_sl.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_sl.xtb
deleted file mode 100644
index 0c8286be..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_sl.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="sl">
-<translation id="146329143005354472">Dodaj v Moje aplikacije</translation>
-<translation id="2169830938017475061">Zdaj</translation>
-<translation id="3669009212293447190">Več člankov</translation>
-<translation id="6664816932026096408">Raziskovanje aplikacij</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_sr.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_sr.xtb
deleted file mode 100644
index bb17ebed..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_sr.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="sr">
-<translation id="146329143005354472">Додај у Моје апликације</translation>
-<translation id="2169830938017475061">Сада</translation>
-<translation id="3669009212293447190">Још чланака</translation>
-<translation id="6664816932026096408">Истражите апликације</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_sv.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_sv.xtb
deleted file mode 100644
index f401858c..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_sv.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="sv">
-<translation id="146329143005354472">Lägg till i Mina appar</translation>
-<translation id="2169830938017475061">Nyss</translation>
-<translation id="3669009212293447190">Fler artiklar</translation>
-<translation id="6664816932026096408">Upptäck nya appar</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_sw.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_sw.xtb
deleted file mode 100644
index fdb7eed..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_sw.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="sw">
-<translation id="146329143005354472">Ongeza kwenye 'Programu zangu'</translation>
-<translation id="2169830938017475061">Sasa</translation>
-<translation id="3669009212293447190">Makala zaidi</translation>
-<translation id="6664816932026096408">Gundua programu</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_ta.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_ta.xtb
deleted file mode 100644
index a590619..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_ta.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="ta">
-<translation id="146329143005354472">எனது ஆப்ஸில் சேர்</translation>
-<translation id="2169830938017475061">இப்போது</translation>
-<translation id="3669009212293447190">மேலும் செய்திகள்</translation>
-<translation id="6664816932026096408">மேலும் பல ஆப்ஸ்</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_te.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_te.xtb
deleted file mode 100644
index 52a2aa06..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_te.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="te">
-<translation id="146329143005354472">నా యాప్‌లకు జోడించు</translation>
-<translation id="2169830938017475061">ఇప్పుడే</translation>
-<translation id="3669009212293447190">మరిన్ని కథనాలు</translation>
-<translation id="6664816932026096408">యాప్‌లను అన్వేషించండి</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_th.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_th.xtb
deleted file mode 100644
index 75bfdfc5..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_th.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="th">
-<translation id="146329143005354472">เพิ่มลงในแอปของฉัน</translation>
-<translation id="2169830938017475061">ตอนนี้</translation>
-<translation id="3669009212293447190">บทความเพิ่มเติม</translation>
-<translation id="6664816932026096408">สำรวจแอป</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_tl.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_tl.xtb
deleted file mode 100644
index 2f8ad7d..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_tl.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="tl"></translationbundle>
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_tr.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_tr.xtb
deleted file mode 100644
index 0291e201..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_tr.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="tr">
-<translation id="146329143005354472">Uygulamalarım'a ekle</translation>
-<translation id="2169830938017475061">Şimdi</translation>
-<translation id="3669009212293447190">Daha fazla makale</translation>
-<translation id="6664816932026096408">Uygulamaları keşfedin</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_uk.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_uk.xtb
deleted file mode 100644
index d074c7fe..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_uk.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="uk">
-<translation id="146329143005354472">Внести в список "Мої додатки"</translation>
-<translation id="2169830938017475061">Щойно</translation>
-<translation id="3669009212293447190">Більше статей</translation>
-<translation id="6664816932026096408">Огляд додатків</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_vi.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_vi.xtb
deleted file mode 100644
index b1269c1..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_vi.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="vi">
-<translation id="146329143005354472">Thêm vào Ứng dụng của tôi</translation>
-<translation id="2169830938017475061">Bây giờ</translation>
-<translation id="3669009212293447190">Bài viết khác</translation>
-<translation id="6664816932026096408">Khám phá ứng dụng</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_zh-CN.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_zh-CN.xtb
deleted file mode 100644
index dae7849..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_zh-CN.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="zh-CN">
-<translation id="146329143005354472">添加到“我的应用”</translation>
-<translation id="2169830938017475061">刚刚</translation>
-<translation id="3669009212293447190">更多报道</translation>
-<translation id="6664816932026096408">浏览应用</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_zh-TW.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_zh-TW.xtb
deleted file mode 100644
index 64c4631..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_zh-TW.xtb
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="zh-TW">
-<translation id="146329143005354472">新增至我的應用程式</translation>
-<translation id="2169830938017475061">剛剛</translation>
-<translation id="3669009212293447190">更多報導</translation>
-<translation id="6664816932026096408">瀏覽應用程式</translation>
-</translationbundle>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/strings/translations/touchless_strings_zh.xtb b/chrome/android/touchless/java/strings/translations/touchless_strings_zh.xtb
deleted file mode 100644
index 619e44fa..0000000
--- a/chrome/android/touchless/java/strings/translations/touchless_strings_zh.xtb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><!DOCTYPE translationbundle><translationbundle lang="zh"></translationbundle>
diff --git a/chrome/android/touchless/javatests/DEPS b/chrome/android/touchless/javatests/DEPS
deleted file mode 100644
index d64b6e3..0000000
--- a/chrome/android/touchless/javatests/DEPS
+++ /dev/null
@@ -1,9 +0,0 @@
-include_rules = [
-  "+content/public/android/java/src/org/chromium/content_public",
-]
-
-specific_include_rules = {
-  "NoTouchActivityTest\.java": [
-    "+components/safe_browsing",
-  ]
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/DinoActivityTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/DinoActivityTest.java
deleted file mode 100644
index 0d2849c..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/DinoActivityTest.java
+++ /dev/null
@@ -1,89 +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.touchless;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.net.test.EmbeddedTestServer;
-
-/**
- * Tests for DinoActivity.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class DinoActivityTest {
-    @Rule
-    public ChromeActivityTestRule<DinoActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(DinoActivity.class);
-
-    private EmbeddedTestServer mTestServer;
-    private DinoActivity mActivity;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-    }
-
-    @After
-    public void tearDown() {
-        mTestServer.stopAndDestroyServer();
-    }
-
-    /**
-     * Tests that the Dino game is launchable.
-     */
-    @Test
-    @MediumTest
-    public void testDinoGameIsLaunchable() throws Throwable {
-        Intent i = new Intent();
-        i.setAction(Intent.ACTION_MAIN);
-        i.addCategory(Intent.CATEGORY_LAUNCHER);
-        i.setClassName(InstrumentationRegistry.getTargetContext().getPackageName(),
-                NoTouchActivity.DINOSAUR_GAME_INTENT);
-        mActivityTestRule.startMainActivityFromIntent(i, null);
-        mActivity = mActivityTestRule.getActivity();
-        Assert.assertFalse(mActivity.getActivityTab().isNativePage());
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals("chrome://dino/",
-                    mActivity.getActivityTab().getWebContents().getLastCommittedUrl());
-        });
-    }
-
-    /**
-     * Tests that the Dino ACTION but with different URL loads dino.
-     */
-    @Test
-    @MediumTest
-    public void testDinoGameOnlyLoadsDino() throws Throwable {
-        Intent i = new Intent();
-        i.setAction(Intent.ACTION_MAIN);
-        i.addCategory(Intent.CATEGORY_LAUNCHER);
-        i.setClassName(InstrumentationRegistry.getTargetContext().getPackageName(),
-                NoTouchActivity.DINOSAUR_GAME_INTENT);
-        i.setData(Uri.parse("https://www.google.com"));
-        mActivityTestRule.startMainActivityFromIntent(i, null);
-        mActivity = mActivityTestRule.getActivity();
-        Assert.assertFalse(mActivity.getActivityTab().isNativePage());
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals("chrome://dino/",
-                    mActivity.getActivityTab().getWebContents().getLastCommittedUrl());
-        });
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
deleted file mode 100644
index 7081d86c..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
+++ /dev/null
@@ -1,148 +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.
-
-package org.chromium.chrome.browser.touchless;
-
-import static org.chromium.chrome.browser.ChromeInactivityTracker.NTP_LAUNCH_DELAY_IN_MINS_PARAM;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.ChromeInactivityTracker;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ApplicationTestUtils;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.content_public.browser.test.util.CriteriaHelper;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.net.test.EmbeddedTestServer;
-
-/**
- * Tests for NoTouchActivity.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class NoTouchActivityTest {
-    private static final String TEST_PATH = "/chrome/test/data/android/simple.html";
-    private static final String TEST_PATH_2 = "/chrome/test/data/android/test.html";
-
-    @Rule
-    public ChromeActivityTestRule<NoTouchActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(NoTouchActivity.class);
-
-    private EmbeddedTestServer mTestServer;
-    private NoTouchActivity mActivity;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-    }
-
-    @After
-    public void tearDown() {
-        mTestServer.stopAndDestroyServer();
-    }
-
-    /**
-     * Tests that the NoTouchActivity starts up to the NTP.
-     */
-    @Test
-    @MediumTest
-    public void testStartsUpToNewTabPage() throws Throwable {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-        Assert.assertTrue(
-                mActivity.getActivityTab().getNativePage() instanceof TouchlessNewTabPage);
-    }
-
-    /**
-     * Tests that the Tab persists through recreation.
-     */
-    @Test
-    @MediumTest
-    public void testRecreateWithTabHistory() throws Throwable {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-
-        mActivityTestRule.loadUrl(mTestServer.getURL(TEST_PATH));
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals(mActivity.getActivityTab().getWebContents().getLastCommittedUrl(),
-                    mTestServer.getURL(TEST_PATH));
-        });
-        mActivity = ApplicationTestUtils.recreateActivity(mActivity);
-        mActivityTestRule.setActivity(mActivity);
-        mActivityTestRule.waitForActivityNativeInitializationComplete();
-        ChromeTabUtils.waitForTabPageLoaded(
-                mActivity.getActivityTab(), mTestServer.getURL(TEST_PATH));
-        TestThreadUtils.runOnUiThreadBlocking(() -> mActivity.onBackPressed());
-        CriteriaHelper.pollUiThread(
-                () -> mActivity.getActivityTab().getNativePage() instanceof TouchlessNewTabPage);
-    }
-
-    /**
-     * Tests that the tab does not persist after recreation, if enough time has passed.
-     *
-     * This test configures the time delay to be 0 minutes, which should always cause the inactivity
-     * threshold to be reached upon recreation.
-     */
-    @Test
-    @MediumTest
-    @CommandLineFlags.
-    Add({"enable-features=" + ChromeInactivityTracker.FEATURE_NAME + "<FakeStudyName",
-            "force-fieldtrials=FakeStudyName/Enabled",
-            "force-fieldtrial-params=FakeStudyName.Enabled:" + NTP_LAUNCH_DELAY_IN_MINS_PARAM
-                    + "/0"})
-    public void
-    testRecreateWithTabHistoryAfterInactivity() throws Throwable {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-        mActivityTestRule.loadUrl(mTestServer.getURL(TEST_PATH));
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals(mActivity.getActivityTab().getWebContents().getLastCommittedUrl(),
-                    mTestServer.getURL(TEST_PATH));
-        });
-
-        ApplicationTestUtils.fireHomeScreenIntent(mActivityTestRule.getActivity());
-        ApplicationTestUtils.launchChrome(mActivityTestRule.getActivity());
-        CriteriaHelper.pollUiThread(
-                () -> mActivity.getActivityTab().getNativePage() instanceof TouchlessNewTabPage);
-    }
-
-    @Test
-    @MediumTest
-    @CommandLineFlags.
-    Add({"enable-features=" + ChromeInactivityTracker.FEATURE_NAME + "<FakeStudyName",
-            "force-fieldtrials=FakeStudyName/Enabled",
-            "force-fieldtrial-params=FakeStudyName.Enabled:" + NTP_LAUNCH_DELAY_IN_MINS_PARAM
-                    + "/0"})
-    public void
-    testViewUrlAfterInactivity() throws Throwable {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-        mActivityTestRule.loadUrl(mTestServer.getURL(TEST_PATH));
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals(mActivity.getActivityTab().getWebContents().getLastCommittedUrl(),
-                    mTestServer.getURL(TEST_PATH));
-        });
-
-        ApplicationTestUtils.fireHomeScreenIntent(mActivityTestRule.getActivity());
-
-        String alternateUrl = mTestServer.getURL(TEST_PATH_2);
-        mActivityTestRule.startMainActivityWithURL(alternateUrl);
-
-        CriteriaHelper.pollUiThread(
-                ()
-                        -> alternateUrl.equals(
-                                mActivity.getActivityTab().getWebContents().getLastCommittedUrl()));
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNavigationRecorderTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNavigationRecorderTest.java
deleted file mode 100644
index 6ec505f..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNavigationRecorderTest.java
+++ /dev/null
@@ -1,102 +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.touchless;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.Callback;
-import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.suggestions.NavigationRecorder;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.net.test.EmbeddedTestServer;
-
-import java.util.concurrent.TimeoutException;
-
-/**
- * Instrumentation tests for {@link NavigationRecorder} run in the context of a SingleTabActivity.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class TouchlessNavigationRecorderTest {
-    @Rule
-    public ChromeActivityTestRule<NoTouchActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(NoTouchActivity.class);
-
-    private EmbeddedTestServer mTestServer;
-    private String mNavUrl;
-    private Tab mInitialTab;
-
-    private NoTouchActivity mActivity;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-        mNavUrl = mTestServer.getURL("/chrome/test/data/android/google.html");
-
-        mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> Assert.assertEquals(
-                                mActivity.getActivityTab().getWebContents().getLastCommittedUrl(),
-                                UrlConstants.NTP_URL));
-
-        mInitialTab = mActivityTestRule.getActivity().getActivityTab();
-    }
-
-    @After
-    public void tearDown() {
-        // If setUp() fails, tearDown() still needs to be able to execute without exceptions.
-        if (mTestServer != null) {
-            mTestServer.stopAndDestroyServer();
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testRecordVisitOnDestroy() throws InterruptedException, TimeoutException {
-        final CallbackHelper callback = new CallbackHelper();
-        loadUrlAndRecordVisit(mNavUrl, (NavigationRecorder.VisitData visit) -> {
-            // While we are navigation back to the NTP, NavigationRecorder always passed null as
-            // the URL unless a 'back 'navigation is performed.
-            Assert.assertEquals(null, visit.endUrl);
-            callback.notifyCalled();
-        });
-
-        ChromeTabUtils.waitForTabPageLoaded(mInitialTab, (String) null);
-
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            // This will trigger an intent and use PageTransition.FROM_API.
-            mActivityTestRule.getActivity().getTabCreator(false).launchNTP();
-        });
-        callback.waitForCallback(0);
-    }
-
-    /** Loads the provided URL in the current tab and sets up navigation recording for it. */
-    private void loadUrlAndRecordVisit(
-            final String url, Callback<NavigationRecorder.VisitData> visitCallback) {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mInitialTab.loadUrl(new LoadUrlParams(url)); });
-        NavigationRecorder.record(mInitialTab, visitCallback);
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediatorTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediatorTest.java
deleted file mode 100644
index 06c454c..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediatorTest.java
+++ /dev/null
@@ -1,90 +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.touchless;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.Callback;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.NavigationController;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.net.test.EmbeddedTestServer;
-
-/**
- * Instrumentation tests for {@link TouchlessNewTabPageMediator}.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class TouchlessNewTabPageMediatorTest {
-    @Rule
-    public ChromeActivityTestRule<NoTouchActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(NoTouchActivity.class);
-
-    private EmbeddedTestServer mTestServer;
-    private Tab mInitialTab;
-    private NavigationController mNavigationController;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-        mInitialTab = mActivityTestRule.getActivity().getActivityTab();
-        mNavigationController = mInitialTab.getWebContents().getNavigationController();
-
-        // NTP is going to load by default.
-        ChromeTabUtils.waitForTabPageLoaded(mInitialTab, (String) null);
-    }
-
-    @After
-    public void tearDown() {
-        // If setUp() fails, tearDown() still needs to be able to execute without exceptions.
-        if (mTestServer != null) {
-            mTestServer.stopAndDestroyServer();
-        }
-    }
-
-    @Test
-    @SmallTest
-    public void testRendererPageLoad() throws InterruptedException {
-        String rendererUrl = mTestServer.getURL("/chrome/test/data/android/google.html");
-        verifyScrollPosition((String pos) -> Assert.assertEquals("", pos));
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mInitialTab.loadUrl(new LoadUrlParams(rendererUrl)); });
-        ChromeTabUtils.waitForTabPageLoaded(mInitialTab, (String) null);
-        verifyScrollPosition((String pos) -> Assert.assertNotEquals("", pos));
-    }
-
-    @Test
-    @SmallTest
-    public void testNativePageLoad() throws InterruptedException {
-        verifyScrollPosition((String pos) -> Assert.assertEquals("", pos));
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mInitialTab.loadUrl(new LoadUrlParams(UrlConstants.EXPLORE_URL)); });
-        ChromeTabUtils.waitForTabPageLoaded(mInitialTab, (String) null);
-        verifyScrollPosition((String pos) -> Assert.assertNotEquals("", pos));
-    }
-
-    private void verifyScrollPosition(Callback<String> verification) {
-        TestThreadUtils.runOnUiThreadBlocking(
-                ()
-                        -> verification.onResult(mNavigationController.getEntryExtraData(
-                                0, "TouchlessScrollPosition")));
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessPreferencesTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessPreferencesTest.java
deleted file mode 100644
index 8d8b87d..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessPreferencesTest.java
+++ /dev/null
@@ -1,79 +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.touchless;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.view.ViewGroup;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.preferences.PreferencesTest;
-import org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences;
-import org.chromium.chrome.browser.preferences.website.SiteSettingsCategory;
-import org.chromium.chrome.browser.preferences.website.SiteSettingsPreferences;
-import org.chromium.chrome.browser.preferences.website.SiteSettingsTestUtils;
-import org.chromium.chrome.test.ChromeBrowserTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.Features;
-
-/**
- * This class tests touchless-specific modifications that were applied to preferences.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@Features.EnableFeatures(ChromeFeatureList.CAPTION_SETTINGS)
-public class TouchlessPreferencesTest {
-    @Rule
-    public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
-
-    @Test
-    @SmallTest
-    @Feature({"Preferences"})
-    public void testOptionsMenu() throws Exception {
-        final Preferences activity =
-                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
-                        SiteSettingsPreferences.class.getName());
-        Assert.assertTrue(activity instanceof TouchlessPreferences);
-
-        ViewGroup actionBarView = activity.findViewById(R.id.action_bar);
-        Assert.assertEquals("Options menu should not have any items in touchless mode", 0,
-                ((ViewGroup) actionBarView.getChildAt(1)).getChildCount());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Preferences"})
-    public void testNoClipboardInSiteSettings() throws Exception {
-        final Preferences activity =
-                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
-                        SiteSettingsPreferences.class.getName());
-        Assert.assertTrue(activity instanceof TouchlessPreferences);
-
-        SiteSettingsPreferences preferences = (SiteSettingsPreferences) activity.getMainFragment();
-        Assert.assertNull(preferences.findPreference(
-                SiteSettingsCategory.preferenceKey(SiteSettingsCategory.Type.CLIPBOARD)));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Preferences"})
-    public void testNoThirdPartyCookiesInSiteSettings() throws Exception {
-        final Preferences activity =
-                SiteSettingsTestUtils.startSiteSettingsCategory(SiteSettingsCategory.Type.COOKIES);
-        Assert.assertTrue(activity instanceof TouchlessPreferences);
-
-        SingleCategoryPreferences cookiesPreferences =
-                (SingleCategoryPreferences) activity.getMainFragment();
-        Assert.assertNull(cookiesPreferences.findPreference(
-                SingleCategoryPreferences.THIRD_PARTY_COOKIES_TOGGLE_KEY));
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenterTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenterTest.java
deleted file mode 100644
index ebb40ef..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenterTest.java
+++ /dev/null
@@ -1,139 +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.touchless.dialog;
-
-import static org.chromium.chrome.browser.touchless.dialog.TouchlessDialogTestUtils.showDialog;
-
-import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
-import android.view.View;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.touchless.NoTouchActivity;
-import org.chromium.chrome.test.ChromeActivityTestRule;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Tests for {@link TouchlessDialogPresenter}.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class TouchlessDialogPresenterTest {
-    @Rule
-    public ChromeActivityTestRule<NoTouchActivity> mActivityTestRule =
-            new ChromeActivityTestRule<>(NoTouchActivity.class);
-    private NoTouchActivity mActivity;
-    private ModalDialogManager mManager;
-    private UiDevice mUiDevice;
-
-    private static final int TIMEOUT_MS = 500;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        mActivityTestRule.startMainActivityOnBlankPage();
-        mActivity = mActivityTestRule.getActivity();
-        mManager = mActivity.getModalDialogManager();
-        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TouchlessModalDialog"})
-    public void testItemSelection() throws Exception {
-        CallbackHelper item1Callback = new CallbackHelper();
-        CallbackHelper item2Callback = new CallbackHelper();
-        PropertyModel dialog = TouchlessDialogTestUtils.createDialog("dialog", false,
-                new String[] {"1", "2"},
-                new View.OnClickListener[] {
-                        (v) -> item1Callback.notifyCalled(), (v) -> item2Callback.notifyCalled()});
-
-        // Enable 'keyboard mode' by sending a key press event.
-        // Doing so, the first item will be focused when the dialog appears.
-        mUiDevice.pressDPadDown();
-        showDialog(mManager, dialog);
-        mUiDevice.wait(Until.findObject(By.text("dialog")), TIMEOUT_MS);
-
-        UiObject2 firstItem = mUiDevice.findObject(By.text("1")).getParent();
-        UiObject2 secondItem = mUiDevice.findObject(By.text("2")).getParent();
-
-        Assert.assertTrue("First item is not selected", firstItem.isFocused());
-        Assert.assertFalse("Second item is selected", secondItem.isFocused());
-
-        Assert.assertEquals(0, item1Callback.getCallCount());
-        mUiDevice.pressDPadCenter();
-        item1Callback.waitForCallback(0, 1);
-
-        mUiDevice.pressDPadDown();
-        secondItem.wait(Until.focused(true), TIMEOUT_MS);
-        Assert.assertFalse("First item is selected", firstItem.isFocused());
-
-        Assert.assertEquals(0, item2Callback.getCallCount());
-        mUiDevice.pressDPadCenter();
-        item2Callback.waitForCallback(0, 1);
-        Assert.assertEquals(1, item1Callback.getCallCount());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TouchlessModalDialog"})
-    public void testFullscreen() throws Exception {
-        PropertyModel dialog = TouchlessDialogTestUtils.createDialog("dialog", true);
-
-        Rect visibleRect = new Rect();
-        mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleRect);
-
-        showDialog(mManager, dialog);
-        mUiDevice.wait(Until.findObject(By.text("dialog")), TIMEOUT_MS);
-        UiObject2 dialogObject = mUiDevice.findObject(By.text("dialog")).getParent();
-        Assert.assertEquals(visibleRect, dialogObject.getVisibleBounds());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TouchlessModalDialog"})
-    public void testNotFullscreen() throws Exception {
-        PropertyModel dialog = TouchlessDialogTestUtils.createDialog("dialog", false);
-
-        Rect visibleRect = new Rect();
-        mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleRect);
-
-        showDialog(mManager, dialog);
-        mUiDevice.wait(Until.findObject(By.text("dialog")), TIMEOUT_MS);
-        UiObject2 dialogObject = mUiDevice.findObject(By.text("dialog")).getParent();
-        Assert.assertNotEquals(visibleRect, dialogObject.getVisibleBounds());
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"TouchlessModalDialog"})
-    public void testDismiss() throws Exception {
-        PropertyModel dialog = TouchlessDialogTestUtils.createDialog("dialog");
-        UiObject dialogUiObject = mUiDevice.findObject(new UiSelector().text("dialog"));
-
-        showDialog(mManager, dialog);
-        dialogUiObject.waitForExists(TIMEOUT_MS);
-
-        mUiDevice.pressBack();
-        dialogUiObject.waitUntilGone(TIMEOUT_MS);
-    }
-}
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogTestUtils.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogTestUtils.java
deleted file mode 100644
index 8bbc84a2..0000000
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogTestUtils.java
+++ /dev/null
@@ -1,75 +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.touchless.dialog;
-
-import android.view.View;
-
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.DialogListItemProperties;
-import org.chromium.chrome.browser.touchless.dialog.TouchlessDialogProperties.ListItemType;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.modelutil.PropertyModel;
-
-import java.util.concurrent.ExecutionException;
-
-/**
- * Utility methods for testing touchless modal dialogs.
- */
-public class TouchlessDialogTestUtils {
-    public static void showDialog(ModalDialogManager manager, PropertyModel model) {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> manager.showDialog(model, ModalDialogManager.ModalDialogType.APP));
-    }
-
-    public static PropertyModel createDialog(String title) throws ExecutionException {
-        return createDialog(title, false);
-    }
-
-    public static PropertyModel createDialog(String title, boolean isFullscreen)
-            throws ExecutionException {
-        return createDialog(title, isFullscreen, null, null);
-    }
-
-    public static PropertyModel createDialog(String title, boolean isFullscreen, String[] items,
-            View.OnClickListener[] itemListeners) throws ExecutionException {
-        return TestThreadUtils.runOnUiThreadBlocking(() -> {
-            ModalDialogProperties.Controller controller = new ModalDialogProperties.Controller() {
-                @Override
-                public void onClick(PropertyModel model, int buttonType) {}
-
-                @Override
-                public void onDismiss(PropertyModel model, int dismissalCause) {}
-            };
-
-            PropertyModel model =
-                    new PropertyModel.Builder(TouchlessDialogProperties.ALL_DIALOG_KEYS)
-                            .with(ModalDialogProperties.CONTROLLER, controller)
-                            .with(ModalDialogProperties.TITLE, title)
-                            .with(TouchlessDialogProperties.IS_FULLSCREEN, isFullscreen)
-                            .build();
-            if (items != null && itemListeners != null) {
-                model.set(
-                        TouchlessDialogProperties.LIST_MODELS, generateItems(items, itemListeners));
-            }
-            return model;
-        });
-    }
-
-    private static ModelList generateItems(
-            String[] itemTitles, View.OnClickListener[] itemListeners) {
-        ModelList items = new ModelList();
-        for (int i = 0; i < itemTitles.length; i++) {
-            items.add(new ListItem(ListItemType.DEFAULT,
-                    new PropertyModel.Builder(DialogListItemProperties.ALL_KEYS)
-                            .with(DialogListItemProperties.TEXT, itemTitles[i])
-                            .with(DialogListItemProperties.CLICK_LISTENER, itemListeners[i])
-                            .build()));
-        }
-        return items;
-    }
-}
diff --git a/chrome/android/touchless/junit/DEPS b/chrome/android/touchless/junit/DEPS
deleted file mode 100644
index 81c3f45e..0000000
--- a/chrome/android/touchless/junit/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+components/feature_engagement/public",
-  "+content/public/android/java/src/org/chromium/content_public",
-]
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java
deleted file mode 100644
index 04733d8d..0000000
--- a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java
+++ /dev/null
@@ -1,66 +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.touchless;
-
-import android.support.v7.widget.RecyclerView;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/**
- * Unit tests for the ScrollPositionInfo class.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class ScrollPositionInfoTest {
-    @Test
-    public void roundTripSimple() {
-        ScrollPositionInfo original = new ScrollPositionInfo(12, 34);
-        ScrollPositionInfo roundTripped = ScrollPositionInfo.deserialize(original.serialize());
-        Assert.assertEquals(original.index, roundTripped.index);
-        Assert.assertEquals(original.offset, roundTripped.offset);
-    }
-
-    @Test
-    public void roundTripNegative() {
-        ScrollPositionInfo original = new ScrollPositionInfo(-12, -34);
-        ScrollPositionInfo roundTripped = ScrollPositionInfo.deserialize(original.serialize());
-        Assert.assertEquals(original.index, roundTripped.index);
-        Assert.assertEquals(original.offset, roundTripped.offset);
-    }
-
-    @Test
-    public void roundTripZero() {
-        ScrollPositionInfo original = new ScrollPositionInfo(0, 0);
-        ScrollPositionInfo roundTripped = ScrollPositionInfo.deserialize(original.serialize());
-        Assert.assertEquals(original.index, roundTripped.index);
-        Assert.assertEquals(original.offset, roundTripped.offset);
-    }
-
-    @Test
-    public void deserializeFailure() {
-        ScrollPositionInfo position = ScrollPositionInfo.deserialize("invalid");
-        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
-        Assert.assertEquals(0, position.offset);
-    }
-
-    @Test
-    public void deserializeEmpty() {
-        ScrollPositionInfo position = ScrollPositionInfo.deserialize("");
-        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
-        Assert.assertEquals(0, position.offset);
-    }
-
-    @Test
-    public void deserializeNull() {
-        ScrollPositionInfo position = ScrollPositionInfo.deserialize(null);
-        Assert.assertEquals(RecyclerView.NO_POSITION, position.index);
-        Assert.assertEquals(0, position.offset);
-    }
-}
\ No newline at end of file
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolderTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolderTest.java
deleted file mode 100644
index 8cd6d98..0000000
--- a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolderTest.java
+++ /dev/null
@@ -1,109 +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.touchless;
-
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowToast;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.native_page.ContextMenuManager;
-import org.chromium.chrome.browser.ntp.cards.ActionItem;
-import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo;
-import org.chromium.chrome.browser.ntp.cards.SuggestionsSection;
-import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
-import org.chromium.chrome.browser.suggestions.ContentSuggestionsAdditionalAction;
-import org.chromium.chrome.browser.suggestions.SuggestionsEventReporter;
-import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
-import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
-import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
-import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils;
-
-/**
- * Unit tests for the TouchlessActionItemViewHolder class.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class TouchlessActionItemViewHolderTest {
-    @Mock
-    private ContextMenuManager mContextMenuManager;
-
-    @Mock
-    private SuggestionsUiDelegate mUiDelegate;
-
-    @Mock
-    private UiConfig mUiConfig;
-
-    @Mock
-    private SuggestionsSection mSection;
-
-    @Mock
-    private SuggestionsRanker mRanker;
-
-    @Mock
-    private SuggestionsEventReporter mSuggestionsEventReporter;
-
-    @Captor
-    private ArgumentCaptor<Runnable> mCallbackCaptor;
-
-    private TouchlessActionItemViewHolder mViewHolder;
-
-    @Before
-    public void setUp() throws InterruptedException {
-        MockitoAnnotations.initMocks(this);
-
-        SuggestionsRecyclerView recyclerView =
-                new SuggestionsRecyclerView(RuntimeEnvironment.application);
-        mViewHolder = new TouchlessActionItemViewHolder(
-                recyclerView, mContextMenuManager, mUiDelegate, mUiConfig);
-        SuggestionsCategoryInfo info =
-                new ContentSuggestionsTestUtils.CategoryInfoBuilder(KnownCategories.ARTICLES)
-                        .withAction(ContentSuggestionsAdditionalAction.FETCH)
-                        .showIfEmpty()
-                        .build();
-        Mockito.when(mSection.getCategoryInfo()).thenReturn(info);
-        Mockito.when(mUiDelegate.getEventReporter()).thenReturn(mSuggestionsEventReporter);
-    }
-
-    @Test
-    @SmallTest
-    public void testOnFailureToast() {
-        mViewHolder.onBindViewHolder(new ActionItem(mSection, mRanker));
-        mViewHolder.getButtonForTesting().performClick();
-        Assert.assertEquals(0, ShadowToast.shownToastCount());
-        Mockito.verify(mSection).fetchSuggestions(/*onFailure*/
-                mCallbackCaptor.capture(), /*onNoNewSuggestions*/ Mockito.any(Runnable.class));
-        mCallbackCaptor.getValue().run();
-
-        Mockito.verify(mUiDelegate, Mockito.never()).getSnackbarManager();
-        Assert.assertEquals(1, ShadowToast.shownToastCount());
-    }
-
-    @Test
-    @SmallTest
-    public void testOnNoNewSuggestionsToast() {
-        mViewHolder.onBindViewHolder(new ActionItem(mSection, mRanker));
-        mViewHolder.getButtonForTesting().performClick();
-        Assert.assertEquals(0, ShadowToast.shownToastCount());
-        Mockito.verify(mSection).fetchSuggestions(/*onFailure*/
-                Mockito.any(Runnable.class), /*onNoNewSuggestions*/ mCallbackCaptor.capture());
-        mCallbackCaptor.getValue().run();
-
-        Mockito.verify(mUiDelegate, Mockito.never()).getSnackbarManager();
-        Assert.assertEquals(1, ShadowToast.shownToastCount());
-    }
-}
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediatorTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediatorTest.java
deleted file mode 100644
index a251625..0000000
--- a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediatorTest.java
+++ /dev/null
@@ -1,121 +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.touchless.ui.iph;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.task.test.ShadowPostTask;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
-import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.components.feature_engagement.Tracker;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Unit tests for the {@link KeyFunctionsIPHMediator} class.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, shadows = {ShadowPostTask.class})
-public class KeyFunctionsIPHMediatorTest {
-    private static final String SAMPLE_URL = "https://google.com/chrome/";
-
-    private PropertyModel mModel;
-    private ArgumentCaptor<TabObserver> mTabObserver;
-    private Tab mTab;
-    private ChromePreferenceManager mChromePreferenceManager;
-    private Tracker mTracker;
-    private KeyFunctionsIPHMediator mKeyFunctionsIPHMediator;
-
-    @Before
-    public void setUp() {
-        mTab = mock(Tab.class);
-        mChromePreferenceManager = mock(ChromePreferenceManager.class);
-        mTracker = mock(Tracker.class);
-        mTabObserver = ArgumentCaptor.forClass(TabObserver.class);
-        mModel = spy(new PropertyModel.Builder(KeyFunctionsIPHProperties.ALL_KEYS).build());
-        ActivityTabProvider activityTabProvider = spy(ActivityTabProvider.class);
-
-        TrackerFactory.setTrackerForTests(mTracker);
-        when(mTracker.acquireDisplayLock()).thenReturn(mock(Tracker.DisplayLockHandle.class));
-        when(activityTabProvider.get()).thenReturn(mTab);
-        when(mChromePreferenceManager.readInt(
-                     ChromePreferenceManager.TOUCHLESS_BROWSING_SESSION_COUNT))
-                .thenReturn(0);
-        mKeyFunctionsIPHMediator = spy(new KeyFunctionsIPHMediator(
-                mModel, activityTabProvider, mChromePreferenceManager, mTracker));
-        verify(mTab).addObserver(mTabObserver.capture());
-    }
-
-    @Test
-    public void visibilityTest() {
-        when(mTab.getUrl()).thenReturn(SAMPLE_URL);
-        mTabObserver.getValue().onPageLoadStarted(mTab, SAMPLE_URL);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE), false);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), true);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-
-        for (int i = 1; i < KeyFunctionsIPHMediator.INTRODUCTORY_PAGE_LOAD_CYCLE; i++) {
-            mTabObserver.getValue().onPageLoadStarted(mTab, SAMPLE_URL);
-            Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-        }
-
-        mTabObserver.getValue().onPageLoadStarted(mTab, SAMPLE_URL);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), true);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-
-        when(mChromePreferenceManager.readInt(
-                     ChromePreferenceManager.TOUCHLESS_BROWSING_SESSION_COUNT))
-                .thenReturn(KeyFunctionsIPHMediator.INTRODUCTORY_SESSIONS + 1);
-        for (int i = 0; i <= KeyFunctionsIPHMediator.INTRODUCTORY_PAGE_LOAD_CYCLE; i++) {
-            mTabObserver.getValue().onPageLoadStarted(mTab, SAMPLE_URL);
-            Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-        }
-    }
-
-    @Test
-    public void cursorVisibilityToggleTest() {
-        // Toggling cursor mode does not trigger the IPH, but should update the model.
-        mKeyFunctionsIPHMediator.onFallbackCursorModeToggled(true);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE), true);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-
-        mKeyFunctionsIPHMediator.onFallbackCursorModeToggled(false);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_CURSOR_VISIBLE), false);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-    }
-
-    @Test
-    public void otherIPHShowingTest() {
-        // Toggling cursor mode does not trigger the IPH.
-        when(mTracker.acquireDisplayLock()).thenReturn(null);
-        mKeyFunctionsIPHMediator.onFallbackCursorModeToggled(true);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-
-        when(mTracker.acquireDisplayLock()).thenReturn(mock(Tracker.DisplayLockHandle.class));
-        mKeyFunctionsIPHMediator.onFallbackCursorModeToggled(false);
-        Assert.assertEquals(mModel.get(KeyFunctionsIPHProperties.IS_VISIBLE), false);
-    }
-
-    @After
-    public void tearDown() {
-        TrackerFactory.setTrackerForTests(null);
-    }
-}
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java
deleted file mode 100644
index 1950806d..0000000
--- a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java
+++ /dev/null
@@ -1,131 +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.touchless.ui.progressbar;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.task.test.ShadowPostTask;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.touchless.TouchlessUrlUtilities;
-import org.chromium.chrome.browser.util.UrlConstants;
-import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Unit tests for the {@link ProgressBarMediator} class.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, shadows = {ShadowPostTask.class})
-public class ProgressBarMediatorTest {
-    private static final String SAMPLE_URL = "https://www.google.com/chrome";
-    private static final String SAMPLE_URL_SHORT = "google.com";
-
-    private ProgressBarMediator mProgressBarMediator;
-    private PropertyModel mModel;
-    private ArgumentCaptor<TabObserver> mTabObserver;
-    private Tab mTab;
-
-    @Before
-    public void setUp() {
-        TouchlessUrlUtilities.setUrlForDisplayForTest(SAMPLE_URL_SHORT);
-        mModel = new PropertyModel.Builder(ProgressBarProperties.ALL_KEYS).build();
-        mTabObserver = ArgumentCaptor.forClass(TabObserver.class);
-        mTab = mock(Tab.class);
-        ActivityTabProvider activityTabProvider = spy(ActivityTabProvider.class);
-        when(activityTabProvider.get()).thenReturn(mTab);
-        mProgressBarMediator = new ProgressBarMediator(mModel, activityTabProvider);
-        verify(mTab).addObserver(mTabObserver.capture());
-    }
-
-    @After
-    public void tearDown() {
-        TouchlessUrlUtilities.setUrlForDisplayForTest(null);
-    }
-
-    @Test
-    public void visibilityTest() {
-        NavigationHandle navigationHandle = mock(NavigationHandle.class);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), false);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
-
-        when(navigationHandle.isInMainFrame()).thenReturn(true);
-        when(navigationHandle.getUrl()).thenReturn(SAMPLE_URL);
-        mTabObserver.getValue().onDidStartNavigation(mTab, navigationHandle);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
-
-        // Mock page load finish, but not display timeout. The progress bar should still be visible.
-        mTabObserver.getValue().onLoadStopped(mTab, true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
-
-        // Mock display timeout. The progress bar should not be visible at this point.
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
-
-        // The progress bar should be shown on activity start.
-        mProgressBarMediator.onActivityStart();
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
-
-        // And should disappear after the timeout.
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
-
-        // The progress bar should be disabled for native pages.
-        when(navigationHandle.getUrl()).thenReturn(UrlConstants.NTP_URL);
-        mTabObserver.getValue().onDidStartNavigation(mTab, navigationHandle);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), false);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
-
-        // Mock display timeout before page load finish.
-        when(navigationHandle.getUrl()).thenReturn(SAMPLE_URL);
-        mTabObserver.getValue().onDidStartNavigation(mTab, navigationHandle);
-        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
-    }
-
-    @Test
-    public void progressAndUrlTest() {
-        Assert.assertNull(mModel.get(ProgressBarProperties.URL));
-
-        NavigationHandle navigationHandle = mock(NavigationHandle.class);
-        when(navigationHandle.isInMainFrame()).thenReturn(true);
-        when(navigationHandle.getUrl()).thenReturn(SAMPLE_URL);
-        when(mTab.getUrl()).thenReturn(SAMPLE_URL);
-        mTabObserver.getValue().onDidStartNavigation(mTab, navigationHandle);
-
-        mTabObserver.getValue().onUrlUpdated(mTab);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.URL), SAMPLE_URL_SHORT);
-
-        mTabObserver.getValue().onLoadProgressChanged(mTab, 10);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.PROGRESS_FRACTION), .1, .001);
-
-        // Progress and URL should not be updated for native pages.
-        when(mTab.getUrl()).thenReturn(UrlConstants.NTP_URL);
-        mTabObserver.getValue().onLoadProgressChanged(mTab, 20);
-        mTabObserver.getValue().onUrlUpdated(mTab);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.PROGRESS_FRACTION), .1, .001);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.URL), SAMPLE_URL_SHORT);
-    }
-}
diff --git a/chrome/android/touchless/touchless_java_sources.gni b/chrome/android/touchless/touchless_java_sources.gni
deleted file mode 100644
index 05cd5780..0000000
--- a/chrome/android/touchless/touchless_java_sources.gni
+++ /dev/null
@@ -1,94 +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.
-
-touchless_java_sources = [
-  "touchless/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/AboveTheFoldViewHolder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ContentSuggestionsViewBinder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/FocusableComponent.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabMediator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabProperties.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabViewBinder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/OpenLastTabView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/QuantizedSizeIconView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchTabDelegateFactory.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ScrollPositionInfo.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsLayoutManager.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsRecyclerView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsViewHolderFactory.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessAddToHomescreenManager.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessArticleViewHolder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessCategoryCardViewHolderFactory.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessContextMenuManager.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesCategoryCardView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessExploreSitesPage.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessLayoutManager.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessModelCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageAdapter.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageProperties.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageTopLayout.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessPreferences.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessRecyclerView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessSuggestionsBinder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabCreator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabObserver.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUrlUtilities.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessZoomHelper.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/permissions/TouchlessPermissionDialogModel.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/snackbar/BlackHoleSnackbarManager.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHProperties.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHViewBinder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/PillProgressBarView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarProperties.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarView.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarViewBinder.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/ui/tooltip/TooltipView.java",
-]
-
-touchless_test_java_sources = [
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/DinoActivityTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNavigationRecorderTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPageMediatorTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/TouchlessPreferencesTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenterTest.java",
-  "touchless/javatests/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogTestUtils.java",
-]
-
-touchless_junit_test_java_sources = [
-  "touchless/junit/src/org/chromium/chrome/browser/touchless/ScrollPositionInfoTest.java",
-  "touchless/junit/src/org/chromium/chrome/browser/touchless/TouchlessActionItemViewHolderTest.java",
-  "touchless/junit/src/org/chromium/chrome/browser/touchless/ui/iph/KeyFunctionsIPHMediatorTest.java",
-  "touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java",
-]
-
-touchess_fallback_java_sources = [
-  "touchless/fallback/java/src/org/chromium/chrome/browser/download/TouchlessDownloadActivity.java",
-  "touchless/fallback/java/src/org/chromium/chrome/browser/touchless/TouchlessDelegate.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessModelCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinator.java",
-  "touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java",
-]
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6d83f8a6..95b89b3 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1069,6 +1069,8 @@
     "password_manager/password_manager_util_win.h",
     "password_manager/password_store_factory.cc",
     "password_manager/password_store_factory.h",
+    "password_manager/password_store_utils.cc",
+    "password_manager/password_store_utils.h",
     "password_manager/reauth_purpose.h",
     "payments/payment_handler_permission_context.cc",
     "payments/payment_handler_permission_context.h",
@@ -2587,7 +2589,7 @@
       "android/oom_intervention/oom_intervention_tab_helper.h",
       "android/partner_browser_customizations.cc",
       "android/partner_browser_customizations.h",
-      "android/password_change_delegate.h",
+      "android/password_edit_delegate.h",
       "android/password_editing_bridge.cc",
       "android/password_editing_bridge.h",
       "android/password_ui_view_android.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a1aff32..a5c44a6a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1890,6 +1890,9 @@
      flag_descriptions::kZeroCopyDescription, kOsAll,
      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableZeroCopy,
                                switches::kDisableZeroCopy)},
+    {"enable-vulkan", flag_descriptions::kEnableVulkanName,
+     flag_descriptions::kEnableVulkanDescription, kOsLinux | kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kVulkan)},
 #if defined(OS_MACOSX)
     {"disable-hosted-app-shim-creation",
      flag_descriptions::kHostedAppShimCreationName,
diff --git a/chrome/browser/accessibility/accessibility_ui.cc b/chrome/browser/accessibility/accessibility_ui.cc
index 5300590..8165c1d 100644
--- a/chrome/browser/accessibility/accessibility_ui.cc
+++ b/chrome/browser/accessibility/accessibility_ui.cc
@@ -5,7 +5,9 @@
 #include "chrome/browser/accessibility/accessibility_ui.h"
 
 #include <memory>
+#include <string>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -47,30 +49,43 @@
 
 static const char kTargetsDataFile[] = "targets-data.json";
 
+static const char kAccessibilityModeField[] = "a11yMode";
+static const char kBrowsersField[] = "browsers";
+static const char kEnabledField[] = "enabled";
+static const char kErrorField[] = "error";
+static const char kFaviconUrlField[] = "faviconUrl";
+static const char kFlagNameField[] = "flagName";
+static const char kImprovementsEnabledField[] = "improvementsEnabled";
+static const char kModeIdField[] = "modeId";
+static const char kNameField[] = "name";
+static const char kPagesField[] = "pages";
+static const char kPidField[] = "pid";
 static const char kProcessIdField[] = "processId";
+static const char kRequestTypeField[] = "requestType";
 static const char kRouteIdField[] = "routeId";
 static const char kSessionIdField[] = "sessionId";
-static const char kUrlField[] = "url";
-static const char kNameField[] = "name";
-static const char kFaviconUrlField[] = "favicon_url";
-static const char kPidField[] = "pid";
-static const char kAccessibilityModeField[] = "a11y_mode";
+static const char kShouldRequestTreeField[] = "shouldRequestTree";
+static const char kTreeField[] = "tree";
 static const char kTypeField[] = "type";
-static const char kImprovementsEnabled[] = "improvementsEnabled";
+static const char kUrlField[] = "url";
 
 // Global flags
-static const char kInternal[] = "internal";
-static const char kNative[] = "native";
-static const char kWeb[] = "web";
-static const char kText[] = "text";
-static const char kScreenReader[] = "screenreader";
+static const char kBrowser[] = "browser";
+static const char kCopyTree[] = "copyTree";
 static const char kHTML[] = "html";
-static const char kLabelImages[] = "label_images";
+static const char kInternal[] = "internal";
+static const char kLabelImages[] = "labelImages";
+static const char kNative[] = "native";
+static const char kPage[] = "page";
+static const char kScreenReader[] = "screenreader";
+static const char kShowTree[] = "showTree";
+static const char kText[] = "text";
+static const char kWeb[] = "web";
 
 // Possible global flag values
+static const char kDisabled[] = "disabled";
 static const char kOff[] = "off";
 static const char kOn[] = "on";
-static const char kDisabled[] = "disabled";
 
 namespace {
 
@@ -91,7 +106,7 @@
   target_data->SetInteger(kPidField, base::GetProcId(handle));
   target_data->SetString(kFaviconUrlField, favicon_url.spec());
   target_data->SetInteger(kAccessibilityModeField, accessibility_mode.mode());
-  target_data->SetString(kTypeField, "page");
+  target_data->SetString(kTypeField, kPage);
   return target_data;
 }
 
@@ -133,7 +148,7 @@
   target_data->SetInteger(kSessionIdField, browser->session_id().id());
   target_data->SetString(kNameField,
                          browser->GetWindowTitleForCurrentTab(false));
-  target_data->SetString(kTypeField, "browser");
+  target_data->SetString(kTypeField, kBrowser);
   return target_data;
 }
 #endif  // !defined(OS_ANDROID)
@@ -175,7 +190,7 @@
                  is_web_enabled ? (screenreader ? kOn : kOff) : kDisabled);
   data.SetString(kHTML, is_web_enabled ? (html ? kOn : kOff) : kDisabled);
 
-  // The "label_images" flag works only if "web" is enabled, the current profile
+  // The "labelImages" flag works only if "web" is enabled, the current profile
   // has the kAccessibilityImageLabelsEnabled preference set and the appropriate
   // command line switch has been used.
   bool are_accessibility_image_labels_enabled =
@@ -220,7 +235,7 @@
                            are_accessibility_image_labels_enabled);
     rvh_list->Append(std::move(descriptor));
   }
-  data.Set("pages", std::move(rvh_list));
+  data.Set(kPagesField, std::move(rvh_list));
 
   std::unique_ptr<base::ListValue> browser_list(new base::ListValue());
 #if !defined(OS_ANDROID)
@@ -228,9 +243,9 @@
     browser_list->Append(BuildTargetDescriptor(browser));
   }
 #endif  // !defined(OS_ANDROID)
-  data.Set("browsers", std::move(browser_list));
+  data.Set(kBrowsersField, std::move(browser_list));
 
-  data.SetBoolean(kImprovementsEnabled, improvements_enabled);
+  data.SetBoolean(kImprovementsEnabledField, improvements_enabled);
 
   std::string json_string;
   base::JSONWriter::Write(data, &json_string);
@@ -269,6 +284,11 @@
   }
 }
 
+std::string Validate(const std::string* str) {
+  CHECK(str);
+  return *str;
+}
+
 }  // namespace
 
 AccessibilityUI::AccessibilityUI(content::WebUI* web_ui)
@@ -332,22 +352,13 @@
 
 void AccessibilityUIMessageHandler::ToggleAccessibility(
     const base::ListValue* args) {
-  std::string process_id_str;
-  std::string route_id_str;
-  std::string should_request_tree_str;
-  int process_id;
-  int route_id;
-  int mode;
-  bool should_request_tree;
-  CHECK_EQ(4U, args->GetSize());
-  CHECK(args->GetString(0, &process_id_str));
-  CHECK(args->GetString(1, &route_id_str));
-  // TODO(695247): We should pass each ax flag seperately
-  CHECK(args->GetInteger(2, &mode));
-  CHECK(args->GetString(3, &should_request_tree_str));
-  CHECK(base::StringToInt(process_id_str, &process_id));
-  CHECK(base::StringToInt(route_id_str, &route_id));
-  should_request_tree = (should_request_tree_str == "true");
+  const base::DictionaryValue* data;
+  CHECK(args->GetDictionary(0, &data));
+
+  int process_id = *data->FindIntPath(kProcessIdField);
+  int route_id = *data->FindIntPath(kRouteIdField);
+  int mode = *data->FindIntPath(kModeIdField);
+  bool should_request_tree = *data->FindBoolPath(kShouldRequestTreeField);
 
   AllowJavascript();
   content::RenderViewHost* rvh =
@@ -379,10 +390,12 @@
   web_contents->SetAccessibilityMode(current_mode);
 
   if (should_request_tree) {
+    base::DictionaryValue request_data;
+    request_data.SetIntPath(kProcessIdField, process_id);
+    request_data.SetIntPath(kRouteIdField, route_id);
+    request_data.SetStringPath(kRequestTypeField, kShowTree);
     base::ListValue request_args;
-    request_args.Append(std::make_unique<base::Value>(process_id_str));
-    request_args.Append(std::make_unique<base::Value>(route_id_str));
-    request_args.Append(std::make_unique<base::Value>("showTree"));
+    request_args.Append(std::move(request_data));
     RequestWebContentsTree(&request_args);
   } else {
     // Call accessibility.showTree without a 'tree' field so the row's
@@ -394,11 +407,11 @@
 }
 
 void AccessibilityUIMessageHandler::SetGlobalFlag(const base::ListValue* args) {
-  std::string flag_name_str;
-  bool enabled;
-  CHECK_EQ(2U, args->GetSize());
-  CHECK(args->GetString(0, &flag_name_str));
-  CHECK(args->GetBoolean(1, &enabled));
+  const base::DictionaryValue* data;
+  CHECK(args->GetDictionary(0, &data));
+
+  std::string flag_name_str = Validate(data->FindStringPath(kFlagNameField));
+  bool enabled = *data->FindBoolPath(kEnabledField);
 
   AllowJavascript();
   if (flag_name_str == kInternal) {
@@ -452,25 +465,20 @@
 
 void AccessibilityUIMessageHandler::RequestWebContentsTree(
     const base::ListValue* args) {
-  std::string process_id_str;
-  std::string route_id_str;
-  int process_id;
-  int route_id;
-  std::string request_type;
-  std::string allow;
-  std::string allow_empty;
-  std::string deny;
-  CHECK_EQ(6U, args->GetSize());
-  CHECK(args->GetString(0, &process_id_str));
-  CHECK(args->GetString(1, &route_id_str));
-  CHECK(base::StringToInt(process_id_str, &process_id));
-  CHECK(base::StringToInt(route_id_str, &route_id));
-  CHECK(args->GetString(2, &request_type));
-  CHECK(request_type == "showTree" || request_type == "copyTree");
+  const base::DictionaryValue* data;
+  CHECK(args->GetDictionary(0, &data));
+
+  int process_id = *data->FindIntPath(kProcessIdField);
+  int route_id = *data->FindIntPath(kRouteIdField);
+
+  std::string request_type = Validate(data->FindStringPath(kRequestTypeField));
+  CHECK(request_type == kShowTree || request_type == kCopyTree);
   request_type = "accessibility." + request_type;
-  CHECK(args->GetString(3, &allow));
-  CHECK(args->GetString(4, &allow_empty));
-  CHECK(args->GetString(5, &deny));
+
+  std::string allow = Validate(data->FindStringPath("filters.allow"));
+  std::string allow_empty =
+      Validate(data->FindStringPath("filters.allowEmpty"));
+  std::string deny = Validate(data->FindStringPath("filters.deny"));
 
   AllowJavascript();
   content::RenderViewHost* rvh =
@@ -479,7 +487,7 @@
     std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
     result->SetInteger(kProcessIdField, process_id);
     result->SetInteger(kRouteIdField, route_id);
-    result->SetString("error", "Renderer no longer exists.");
+    result->SetString(kErrorField, "Renderer no longer exists.");
     CallJavascriptFunction(request_type, *(result.get()));
     return;
   }
@@ -507,21 +515,20 @@
   bool internal = pref->GetBoolean(prefs::kShowInternalAccessibilityTree);
   base::string16 accessibility_contents_utf16 =
       web_contents->DumpAccessibilityTree(internal, property_filters);
-  result->SetString("tree", base::UTF16ToUTF8(accessibility_contents_utf16));
-  result->SetBoolean(kImprovementsEnabled, improvements_enabled_);
+  result->SetString(kTreeField,
+                    base::UTF16ToUTF8(accessibility_contents_utf16));
+  result->SetBoolean(kImprovementsEnabledField, improvements_enabled_);
   CallJavascriptFunction(request_type, *(result.get()));
 }
 
 void AccessibilityUIMessageHandler::RequestNativeUITree(
     const base::ListValue* args) {
-  std::string session_id_str;
-  int session_id;
-  std::string request_type;
-  CHECK_EQ(2U, args->GetSize());
-  CHECK(args->GetString(0, &session_id_str));
-  CHECK(base::StringToInt(session_id_str, &session_id));
-  CHECK(args->GetString(1, &request_type));
-  CHECK(request_type == "showTree" || request_type == "copyTree");
+  const base::DictionaryValue* data;
+  CHECK(args->GetDictionary(0, &data));
+
+  int session_id = *data->FindIntPath(kSessionIdField);
+  std::string request_type = Validate(data->FindStringPath(kRequestTypeField));
+  CHECK(request_type == kShowTree || request_type == kCopyTree);
   request_type = "accessibility." + request_type;
 
   AllowJavascript();
@@ -534,7 +541,7 @@
       gfx::NativeWindow native_window = browser->window()->GetNativeWindow();
       ui::AXPlatformNode* node =
           ui::AXPlatformNode::FromNativeWindow(native_window);
-      result->SetKey("tree",
+      result->SetKey(kTreeField,
                      base::Value(RecursiveDumpAXPlatformNodeAsString(node, 0)));
       CallJavascriptFunction(request_type, *(result.get()));
       return;
@@ -544,8 +551,8 @@
   // No browser with the specified |session_id| was found.
   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
   result->SetInteger(kSessionIdField, session_id);
-  result->SetString(kTypeField, "browser");
-  result->SetString("error", "Browser no longer exists.");
+  result->SetString(kTypeField, kBrowser);
+  result->SetString(kErrorField, "Browser no longer exists.");
   CallJavascriptFunction(request_type, *(result.get()));
 }
 
diff --git a/chrome/browser/android/customtabs/detached_resource_request.cc b/chrome/browser/android/customtabs/detached_resource_request.cc
index 2b94bc8..d487e2be 100644
--- a/chrome/browser/android/customtabs/detached_resource_request.cc
+++ b/chrome/browser/android/customtabs/detached_resource_request.cc
@@ -20,6 +20,7 @@
 #include "net/url_request/url_request_job.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -125,7 +126,7 @@
 
 void DetachedResourceRequest::OnRedirectCallback(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   redirects_++;
 }
diff --git a/chrome/browser/android/customtabs/detached_resource_request.h b/chrome/browser/android/customtabs/detached_resource_request.h
index 662bddc..9d5f8891 100644
--- a/chrome/browser/android/customtabs/detached_resource_request.h
+++ b/chrome/browser/android/customtabs/detached_resource_request.h
@@ -13,6 +13,7 @@
 #include "base/callback.h"
 #include "base/time/time.h"
 #include "net/url_request/url_request.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -25,7 +26,6 @@
 
 namespace network {
 class SimpleURLLoader;
-struct ResourceResponseHead;
 }  // namespace network
 
 namespace customtabs {
@@ -70,7 +70,7 @@
   static void Start(std::unique_ptr<DetachedResourceRequest> request,
                     content::BrowserContext* browser_context);
   void OnRedirectCallback(const net::RedirectInfo& redirect_info,
-                          const network::ResourceResponseHead& response_head,
+                          const network::mojom::URLResponseHead& response_head,
                           std::vector<std::string>* to_be_removed_headers);
   void OnResponseCallback(std::unique_ptr<std::string> response_body);
 
diff --git a/chrome/browser/android/feature_utilities.cc b/chrome/browser/android/feature_utilities.cc
index 60030c3..a86ac3d 100644
--- a/chrome/browser/android/feature_utilities.cc
+++ b/chrome/browser/android/feature_utilities.cc
@@ -40,11 +40,6 @@
   return Java_FeatureUtilities_isDownloadAutoResumptionEnabledInNative(env);
 }
 
-bool IsNoTouchModeEnabled() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  return Java_FeatureUtilities_isNoTouchModeEnabled(env);
-}
-
 std::string GetReachedCodeProfilerTrialGroup() {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jstring> group =
diff --git a/chrome/browser/android/feature_utilities.h b/chrome/browser/android/feature_utilities.h
index 606b6ee..6d950cdd 100644
--- a/chrome/browser/android/feature_utilities.h
+++ b/chrome/browser/android/feature_utilities.h
@@ -24,8 +24,6 @@
 
 bool IsDownloadAutoResumptionEnabledInNative();
 
-bool IsNoTouchModeEnabled();
-
 // Returns a finch group name currently used for the reached code profiler.
 // Returns an empty string if the group isn't specified.
 std::string GetReachedCodeProfilerTrialGroup();
diff --git a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
index 3f1be7e..935e034 100644
--- a/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
+++ b/chrome/browser/android/image_fetcher/image_fetcher_bridge.cc
@@ -14,9 +14,9 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/image_fetcher/image_fetcher_service_factory.h"
+#include "chrome/browser/image_fetcher/jni_headers/ImageFetcherBridge_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
-#include "chrome/lib/image_fetcher/public/android/jni_headers/ImageFetcherBridge_jni.h"
 #include "components/image_fetcher/core/cache/image_cache.h"
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/image_fetcher/core/image_fetcher_metrics_reporter.h"
diff --git a/chrome/browser/android/password_change_delegate.h b/chrome/browser/android/password_change_delegate.h
deleted file mode 100644
index 2a1c78a..0000000
--- a/chrome/browser/android/password_change_delegate.h
+++ /dev/null
@@ -1,15 +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 CHROME_BROWSER_ANDROID_PASSWORD_CHANGE_DELEGATE_H_
-#define CHROME_BROWSER_ANDROID_PASSWORD_CHANGE_DELEGATE_H_
-
-// An interface used by the native side to launch the entry editor and
-// perform a change on a credential record.
-class PasswordChangeDelegate {
- public:
-  virtual ~PasswordChangeDelegate() = default;
-};
-
-#endif  // CHROME_BROWSER_ANDROID_PASSWORD_CHANGE_DELEGATE_H_
diff --git a/chrome/browser/android/password_edit_delegate.h b/chrome/browser/android/password_edit_delegate.h
new file mode 100644
index 0000000..6e840cce
--- /dev/null
+++ b/chrome/browser/android/password_edit_delegate.h
@@ -0,0 +1,27 @@
+// 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_BROWSER_ANDROID_PASSWORD_EDIT_DELEGATE_H_
+#define CHROME_BROWSER_ANDROID_PASSWORD_EDIT_DELEGATE_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+
+// The delegate, which is created and destroyed together with the bridge, holds
+// all the information about the password form that was loaded and edited in the
+// PasswordEntryEditor.
+class PasswordEditDelegate {
+ public:
+  PasswordEditDelegate() = default;
+  virtual ~PasswordEditDelegate() = default;
+
+  // The method edits a password form held by the delegate. |new_username| and
+  // |new_password| are user input from the PasswordEntryEditor.
+  virtual void EditSavedPassword(const base::string16& new_username,
+                                 const base::string16& new_password) = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(PasswordEditDelegate);
+};
+
+#endif  // CHROME_BROWSER_ANDROID_PASSWORD_EDIT_DELEGATE_H_
diff --git a/chrome/browser/android/password_editing_bridge.cc b/chrome/browser/android/password_editing_bridge.cc
index f001e13..58fbe6f 100644
--- a/chrome/browser/android/password_editing_bridge.cc
+++ b/chrome/browser/android/password_editing_bridge.cc
@@ -6,7 +6,7 @@
 
 #include "base/android/jni_string.h"
 #include "chrome/android/chrome_jni_headers/PasswordEditingBridge_jni.h"
-#include "chrome/browser/android/password_change_delegate.h"
+#include "chrome/browser/android/password_edit_delegate.h"
 #include "chrome/browser/android/password_update_delegate.h"
 
 using base::android::ConvertUTF16ToJavaString;
@@ -28,13 +28,13 @@
 void PasswordEditingBridge::LaunchPasswordEntryEditor(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& context,
-    password_manager::PasswordStore* store,
+    Profile* profile,
     const autofill::PasswordForm& password_form) {
   // PasswordEditingBridge will destroy itself when the UI is gone on the Java
   // side.
   PasswordEditingBridge* password_editing_bridge = new PasswordEditingBridge();
-  password_editing_bridge->password_change_delegate_ =
-      std::make_unique<PasswordUpdateDelegate>(store, password_form);
+  password_editing_bridge->password_edit_delegate_ =
+      std::make_unique<PasswordUpdateDelegate>(profile, password_form);
   Java_PasswordEditingBridge_showEditingUI(
       base::android::AttachCurrentThread(),
       password_editing_bridge->java_object_, context,
@@ -42,3 +42,13 @@
       ConvertUTF16ToJavaString(env, password_form.username_value),
       ConvertUTF16ToJavaString(env, password_form.password_value));
 }
+
+void PasswordEditingBridge::HandleEditSavedPasswordEntry(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& object,
+    const JavaParamRef<jstring>& new_username,
+    const JavaParamRef<jstring>& new_password) {
+  password_edit_delegate_->EditSavedPassword(
+      ConvertJavaStringToUTF16(env, new_username),
+      ConvertJavaStringToUTF16(env, new_password));
+}
diff --git a/chrome/browser/android/password_editing_bridge.h b/chrome/browser/android/password_editing_bridge.h
index 9a5a8cce..362f4f7 100644
--- a/chrome/browser/android/password_editing_bridge.h
+++ b/chrome/browser/android/password_editing_bridge.h
@@ -17,7 +17,8 @@
 struct PasswordForm;
 }
 
-class PasswordChangeDelegate;
+class PasswordEditDelegate;
+class Profile;
 
 // A bridge that allows communication between Android UI and the native
 // side. It can be used to launch the password editing activity from the
@@ -36,15 +37,21 @@
   static void LaunchPasswordEntryEditor(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& context,
-      password_manager::PasswordStore* store,
+      Profile* profile,
       const autofill::PasswordForm& password_form);
 
+  void HandleEditSavedPasswordEntry(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& object,
+      const base::android::JavaParamRef<jstring>& new_username,
+      const base::android::JavaParamRef<jstring>& new_password);
+
  private:
   // The corresponding java object.
   base::android::ScopedJavaGlobalRef<jobject> java_object_;
 
   // The delegate belonging to the bridge.
-  std::unique_ptr<PasswordChangeDelegate> password_change_delegate_;
+  std::unique_ptr<PasswordEditDelegate> password_edit_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(PasswordEditingBridge);
 };
diff --git a/chrome/browser/android/password_ui_view_android.cc b/chrome/browser/android/password_ui_view_android.cc
index a532f53..2c4ebc5f 100644
--- a/chrome/browser/android/password_ui_view_android.cc
+++ b/chrome/browser/android/password_ui_view_android.cc
@@ -196,10 +196,7 @@
     const JavaParamRef<jobject>& context,
     int index) {
   PasswordEditingBridge::LaunchPasswordEntryEditor(
-      env, context,
-      PasswordStoreFactory::GetForProfile(GetProfile(),
-                                          ServiceAccessType::EXPLICIT_ACCESS)
-          .get(),
+      env, context, GetProfile(),
       *password_manager_presenter_.GetPassword(index));
 }
 
diff --git a/chrome/browser/android/password_update_delegate.cc b/chrome/browser/android/password_update_delegate.cc
index 56f2c82..0cad922e 100644
--- a/chrome/browser/android/password_update_delegate.cc
+++ b/chrome/browser/android/password_update_delegate.cc
@@ -4,9 +4,40 @@
 
 #include "chrome/browser/android/password_update_delegate.h"
 
+#include "base/stl_util.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/password_manager/password_store_utils.h"
+#include "components/password_manager/core/browser/password_store.h"
+
 PasswordUpdateDelegate::PasswordUpdateDelegate(
-    password_manager::PasswordStore* store,
+    Profile* profile,
     const autofill::PasswordForm& password_form)
-    : password_form_(password_form) {}
+    : profile_(profile), password_form_(password_form) {}
 
 PasswordUpdateDelegate::~PasswordUpdateDelegate() = default;
+
+void PasswordUpdateDelegate::EditSavedPassword(
+    const base::string16& new_username,
+    const base::string16& new_password) {
+  DCHECK(!new_password.empty()) << "The password is empty.";
+
+  new_username_ = new_username;
+  new_password_ = new_password;
+  PasswordStoreFactory::GetForProfile(profile_,
+                                      ServiceAccessType::EXPLICIT_ACCESS)
+      ->GetLogins(password_manager::PasswordStore::FormDigest(password_form_),
+                  this);
+}
+
+void PasswordUpdateDelegate::OnGetPasswordStoreResults(
+    std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
+  // Banned password credentials and the ones with invalid origin won't be
+  // edited through this delegate.
+  base::EraseIf(results, [](const auto& form) {
+    return form->blacklisted_by_user || form->IsFederatedCredential();
+  });
+
+  EditSavedPasswords(profile_, results, password_form_.username_value,
+                     password_form_.signon_realm, new_username_,
+                     &new_password_);
+}
diff --git a/chrome/browser/android/password_update_delegate.h b/chrome/browser/android/password_update_delegate.h
index ca74f3f..988b738 100644
--- a/chrome/browser/android/password_update_delegate.h
+++ b/chrome/browser/android/password_update_delegate.h
@@ -6,24 +6,37 @@
 #define CHROME_BROWSER_ANDROID_PASSWORD_UPDATE_DELEGATE_H_
 
 #include <memory>
+#include <vector>
 
-#include "chrome/browser/android/password_change_delegate.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/android/password_edit_delegate.h"
 #include "chrome/browser/android/password_editing_bridge.h"
 #include "components/autofill/core/common/password_form.h"
-#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/password_store_consumer.h"
 
-// An interface used for launching the entry editor and performing a
-// change on a credential record that already exists in the password store.
-class PasswordUpdateDelegate : public PasswordChangeDelegate {
+class Profile;
+
+// An interface used for launching the entry editor and editing a credential
+// record that already exists in the password store.
+class PasswordUpdateDelegate : public PasswordEditDelegate,
+                               public password_manager::PasswordStoreConsumer {
  public:
-  PasswordUpdateDelegate(password_manager::PasswordStore* store,
+  PasswordUpdateDelegate(Profile* profile,
                          const autofill::PasswordForm& password_form);
   ~PasswordUpdateDelegate() override;
 
- private:
-  autofill::PasswordForm password_form_;
+  void EditSavedPassword(const base::string16& new_username,
+                         const base::string16& new_password) override;
 
-  DISALLOW_COPY_AND_ASSIGN(PasswordUpdateDelegate);
+ private:
+  // PasswordStoreConsumer:
+  void OnGetPasswordStoreResults(
+      std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
+
+  Profile* profile_ = nullptr;
+  autofill::PasswordForm password_form_;
+  base::string16 new_username_;
+  base::string16 new_password_;
 };
 
 #endif  // CHROME_BROWSER_ANDROID_PASSWORD_UPDATE_DELEGATE_H_
diff --git a/chrome/browser/android/password_update_delegate_unittest.cc b/chrome/browser/android/password_update_delegate_unittest.cc
new file mode 100644
index 0000000..3295e01e
--- /dev/null
+++ b/chrome/browser/android/password_update_delegate_unittest.cc
@@ -0,0 +1,189 @@
+// 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/android/password_update_delegate.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/strings/strcat.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/android/password_update_delegate.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using testing::ElementsAre;
+using testing::Pair;
+
+namespace {
+
+constexpr char kExampleCom[] = "https://example.com/";
+constexpr char kExampleOrg[] = "https://example.org/";
+constexpr char kNewPass[] = "new pass";
+constexpr char kNewUser[] = "new user";
+constexpr char kPassword[] = "pass";
+constexpr char kPassword2[] = "pass2";
+constexpr char kUsername[] = "user";
+constexpr char kUsername2[] = "user2";
+
+std::vector<std::pair<std::string, std::string>> GetUsernamesAndPasswords(
+    const std::vector<autofill::PasswordForm>& forms) {
+  std::vector<std::pair<std::string, std::string>> result;
+  result.reserve(forms.size());
+  for (const auto& form : forms) {
+    result.emplace_back(base::UTF16ToUTF8(form.username_value),
+                        base::UTF16ToUTF8(form.password_value));
+  }
+
+  return result;
+}
+
+autofill::PasswordForm MakeSavedForm(const GURL& origin,
+                                     base::StringPiece username,
+                                     base::StringPiece password) {
+  autofill::PasswordForm form;
+  form.origin = origin;
+  form.signon_realm = origin.GetOrigin().spec();
+  form.username_element = base::ASCIIToUTF16("Email");
+  form.username_value = base::ASCIIToUTF16(username);
+  form.password_element = base::ASCIIToUTF16("Passwd");
+  form.password_value = base::ASCIIToUTF16(password);
+  return form;
+}
+
+}  // namespace
+
+class PasswordUpdateDelegateTest : public testing::Test {
+ protected:
+  PasswordUpdateDelegateTest() {}
+
+  ~PasswordUpdateDelegateTest() override {
+    store_->ShutdownOnUIThread();
+    task_environment_.RunUntilIdle();
+  }
+
+  std::unique_ptr<PasswordUpdateDelegate> CreateTestDelegate(
+      const GURL& origin,
+      base::StringPiece username,
+      base::StringPiece password) {
+    return std::make_unique<PasswordUpdateDelegate>(
+        &profile_, MakeSavedForm(origin, username, password));
+  }
+
+  const std::vector<autofill::PasswordForm>& GetStoredPasswordsForRealm(
+      base::StringPiece signon_realm) {
+    const auto& stored_passwords =
+        static_cast<const password_manager::TestPasswordStore&>(*store_)
+            .stored_passwords();
+    auto for_realm_it = stored_passwords.find(signon_realm);
+    return for_realm_it->second;
+  }
+
+  password_manager::PasswordStore* GetStore() { return store_.get(); }
+
+  void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  TestingProfile profile_;
+  scoped_refptr<password_manager::PasswordStore> store_ =
+      base::WrapRefCounted(static_cast<password_manager::PasswordStore*>(
+          PasswordStoreFactory::GetInstance()
+              ->SetTestingFactoryAndUse(
+                  &profile_,
+                  base::BindRepeating(&password_manager::BuildPasswordStore<
+                                      content::BrowserContext,
+                                      password_manager::TestPasswordStore>))
+              .get()));
+};
+
+TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditPassword) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername),
+                                              base::ASCIIToUTF16(kNewPass));
+  RunUntilIdle();
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+              ElementsAre(Pair(kUsername, kNewPass)));
+}
+
+TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditUsername) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
+                                              base::ASCIIToUTF16(kPassword));
+  RunUntilIdle();
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+              ElementsAre(Pair(kNewUser, kPassword)));
+}
+
+TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_EditUsernameAndPassword) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
+                                              base::ASCIIToUTF16(kNewPass));
+  RunUntilIdle();
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+              ElementsAre(Pair(kNewUser, kNewPass)));
+}
+
+TEST_F(PasswordUpdateDelegateTest,
+       EditSavedPassword_RejectSameUsernameForSameRealm) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
+  GetStore()->AddLogin(
+      MakeSavedForm(GURL(kExampleCom), kUsername2, kPassword2));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername2),
+                                              base::ASCIIToUTF16(kPassword));
+  RunUntilIdle();
+  EXPECT_THAT(
+      GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+      ElementsAre(Pair(kUsername, kPassword), Pair(kUsername2, kPassword2)));
+}
+
+TEST_F(PasswordUpdateDelegateTest,
+       EditSavedPassword_DontRejectSameUsernameForDifferentRealm) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(kExampleCom), kUsername, kPassword));
+  GetStore()->AddLogin(
+      MakeSavedForm(GURL(kExampleOrg), kUsername2, kPassword2));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kUsername2),
+                                              base::ASCIIToUTF16(kPassword2));
+  RunUntilIdle();
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+              ElementsAre(Pair(kUsername2, kPassword2)));
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleOrg)),
+              ElementsAre(Pair(kUsername2, kPassword2)));
+}
+
+TEST_F(PasswordUpdateDelegateTest, EditSavedPassword_UpdateDuplicates) {
+  GetStore()->AddLogin(MakeSavedForm(GURL(base::StrCat({kExampleCom, "pathA"})),
+                                     kUsername, kPassword));
+  GetStore()->AddLogin(MakeSavedForm(GURL(base::StrCat({kExampleCom, "pathB"})),
+                                     kUsername, kPassword));
+  RunUntilIdle();
+  std::unique_ptr<PasswordUpdateDelegate> password_update_delegate =
+      CreateTestDelegate(GURL(kExampleCom), kUsername, kPassword);
+  password_update_delegate->EditSavedPassword(base::ASCIIToUTF16(kNewUser),
+                                              base::ASCIIToUTF16(kNewPass));
+  RunUntilIdle();
+  EXPECT_THAT(GetUsernamesAndPasswords(GetStoredPasswordsForRealm(kExampleCom)),
+              ElementsAre(Pair(kNewUser, kNewPass), Pair(kNewUser, kNewPass)));
+}
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc
index 337bcc202..b5cb6fd16 100644
--- a/chrome/browser/android/shortcut_helper.cc
+++ b/chrome/browser/android/shortcut_helper.cc
@@ -116,8 +116,7 @@
       java_short_name, java_best_primary_icon_url, java_bitmap,
       is_icon_maskable, info.display, info.orientation, info.source,
       OptionalSkColorToJavaColor(info.theme_color),
-      OptionalSkColorToJavaColor(info.background_color), callback_pointer,
-      false /* isShortcutAsWebapp */);
+      OptionalSkColorToJavaColor(info.background_color), callback_pointer);
 }
 
 // Adds a shortcut which opens in a browser tab to the launcher.
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
index bcf79f9..e189ad0f 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.cc
@@ -38,13 +38,11 @@
   void StartBlobRequest(chrome::mojom::MediaDataSource::ReadCallback callback,
                         int64_t position,
                         int64_t length) {
-    BlobReader* reader = new BlobReader(  // BlobReader is self-deleting.
-        browser_context_, blob_uuid_,
-        base::BindRepeating(&BlobMediaDataSource::OnBlobReaderDone,
-                            weak_factory_.GetWeakPtr(),
-                            base::Passed(&callback)));
-    reader->SetByteRange(position, length);
-    reader->Start();
+    BlobReader::Read(browser_context_, blob_uuid_,
+                     base::BindRepeating(&BlobMediaDataSource::OnBlobReaderDone,
+                                         weak_factory_.GetWeakPtr(),
+                                         base::Passed(&callback)),
+                     position, length);
   }
 
   void OnBlobReaderDone(chrome::mojom::MediaDataSource::ReadCallback callback,
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index 85bc6c3..63d027a 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -628,13 +628,10 @@
     const std::string& blob_uuid) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  // BlobReader is self-deleting.
-  BlobReader* reader =
-      new BlobReader(GetProfile(), blob_uuid,
-                     base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata,
-                                this, metadata_type, blob_uuid));
-  reader->SetByteRange(0, net::kMaxBytesToSniff);
-  reader->Start();
+  BlobReader::Read(GetProfile(), blob_uuid,
+                   base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata,
+                              this, metadata_type, blob_uuid),
+                   0, net::kMaxBytesToSniff);
 }
 
 void MediaGalleriesGetMetadataFunction::GetMetadata(
diff --git a/chrome/browser/availability/availability_prober.h b/chrome/browser/availability/availability_prober.h
index ae15d10..364bacf 100644
--- a/chrome/browser/availability/availability_prober.h
+++ b/chrome/browser/availability/availability_prober.h
@@ -26,7 +26,7 @@
 #include "net/http/http_request_headers.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
-#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 #if defined(OS_ANDROID)
@@ -65,7 +65,7 @@
     // delegate returns true, no more probes would be attempted until there is a
     // change in the network or |SendNowIfInactive| is called.
     virtual bool IsResponseSuccess(net::Error net_error,
-                                   const network::ResourceResponseHead* head,
+                                   const network::mojom::URLResponseHead* head,
                                    std::unique_ptr<std::string> body) = 0;
   };
 
diff --git a/chrome/browser/availability/availability_prober_browsertest.cc b/chrome/browser/availability/availability_prober_browsertest.cc
index 57e35db..98b7d0d 100644
--- a/chrome/browser/availability/availability_prober_browsertest.cc
+++ b/chrome/browser/availability/availability_prober_browsertest.cc
@@ -44,7 +44,7 @@
   bool ShouldSendNextProbe() override { return should_send_next_probe_; }
 
   bool IsResponseSuccess(net::Error net_error,
-                         const network::ResourceResponseHead* head,
+                         const network::mojom::URLResponseHead* head,
                          std::unique_ptr<std::string> body) override {
     got_head_ = head;
     return net_error == net::OK && head &&
diff --git a/chrome/browser/availability/availability_prober_unittest.cc b/chrome/browser/availability/availability_prober_unittest.cc
index c97d0f7b..0a35827 100644
--- a/chrome/browser/availability/availability_prober_unittest.cc
+++ b/chrome/browser/availability/availability_prober_unittest.cc
@@ -18,8 +18,8 @@
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/test/test_network_connection_tracker.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "services/network/test/test_utils.h"
@@ -38,7 +38,7 @@
   bool ShouldSendNextProbe() override { return should_send_next_probe_; }
 
   bool IsResponseSuccess(net::Error net_error,
-                         const network::ResourceResponseHead* head,
+                         const network::mojom::URLResponseHead* head,
                          std::unique_ptr<std::string> body) override {
     return net_error == net::OK && head &&
            head->headers->response_code() == net::HTTP_OK;
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index e79f2bd..219a2ab 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -966,11 +966,11 @@
       net::HttpResponseInfo info;
       info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
           net::HttpUtil::AssembleRawHeaders(headers));
-      network::ResourceResponseHead response;
-      response.headers = info.headers;
-      response.headers->GetMimeType(&response.mime_type);
-      response.encoded_data_length = 0;
-      params->client->OnReceiveRedirect(redirect_info, response);
+      auto response = network::mojom::URLResponseHead::New();
+      response->headers = info.headers;
+      response->headers->GetMimeType(&response->mime_type);
+      response->encoded_data_length = 0;
+      params->client->OnReceiveRedirect(redirect_info, std::move(response));
     }
 
     if (behind_captive_portal_) {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 93ddb4cc..6b495d9 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2446,6 +2446,17 @@
   return allow;
 }
 
+bool ChromeContentBrowserClient::DoesSchemeAllowCrossOriginSharedWorker(
+    const std::string& scheme) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // Extensions are allowed to start cross-origin shared workers.
+  if (scheme == extensions::kExtensionScheme)
+    return true;
+#endif
+
+  return false;
+}
+
 bool ChromeContentBrowserClient::AllowSignedExchange(
     content::BrowserContext* browser_context) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -4227,10 +4238,6 @@
     throttles.push_back(std::move(google_password_manager_throttle));
 #endif
 
-  std::unique_ptr<content::NavigationThrottle> previews_lite_page_throttle =
-      PreviewsLitePageDecider::MaybeCreateThrottleFor(handle);
-  if (previews_lite_page_throttle)
-    throttles.push_back(std::move(previews_lite_page_throttle));
   if (base::FeatureList::IsEnabled(safe_browsing::kCommittedSBInterstitials)) {
     throttles.push_back(
         std::make_unique<safe_browsing::SafeBrowsingNavigationThrottle>(
@@ -4240,7 +4247,7 @@
 #if defined(OS_WIN) || defined(OS_MACOSX) || \
     (defined(OS_LINUX) && !defined(OS_CHROMEOS))
   std::unique_ptr<content::NavigationThrottle> browser_switcher_throttle =
-      browser_switcher::BrowserSwitcherNavigationThrottle ::
+      browser_switcher::BrowserSwitcherNavigationThrottle::
           MaybeCreateThrottleFor(handle);
   if (browser_switcher_throttle)
     throttles.push_back(std::move(browser_switcher_throttle));
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index bfd0d86..4b251ce 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -238,6 +238,8 @@
                          content::BrowserContext* context,
                          int render_process_id,
                          int render_frame_id) override;
+  bool DoesSchemeAllowCrossOriginSharedWorker(
+      const std::string& scheme) override;
   bool AllowSignedExchange(content::BrowserContext* browser_context) override;
   void AllowWorkerFileSystem(
       const GURL& url,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index e4c9e8a..a05d61a0 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -108,6 +108,8 @@
     "//chromeos/dbus/cryptohome:cryptohome_proto",
     "//chromeos/dbus/cryptohome:cryptohome_signkey_proto",
     "//chromeos/dbus/cups_proxy",
+    "//chromeos/dbus/dlcservice",
+    "//chromeos/dbus/dlcservice:dlcservice_proto",
     "//chromeos/dbus/kerberos",
     "//chromeos/dbus/kerberos:kerberos_proto",
     "//chromeos/dbus/machine_learning",
@@ -2096,6 +2098,8 @@
     "system_logs/single_log_file_log_source.h",
     "system_logs/touch_log_source.cc",
     "system_logs/touch_log_source.h",
+    "system_token_cert_db_initializer.cc",
+    "system_token_cert_db_initializer.h",
     "tether/fake_tether_service.cc",
     "tether/fake_tether_service.h",
     "tether/tether_service.cc",
@@ -2902,6 +2906,7 @@
     "//chromeos/dbus/auth_policy",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:attestation_proto",
+    "//chromeos/dbus/dlcservice:test_support",
     "//chromeos/dbus/power",
     "//chromeos/dbus/services:test_support",
     "//chromeos/dbus/session_manager",
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index e7935bd..0bc5a1b 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -23,8 +23,6 @@
 #include "base/linux_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -110,6 +108,7 @@
 #include "chrome/browser/chromeos/startup_settings_cache.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/browser/chromeos/system/user_removal_manager.h"
+#include "chrome/browser/chromeos/system_token_cert_db_initializer.h"
 #include "chrome/browser/chromeos/ui/gnubby_notification.h"
 #include "chrome/browser/chromeos/ui/low_disk_notification.h"
 #include "chrome/browser/chromeos/usb/cros_usb_detector.h"
@@ -143,7 +142,6 @@
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/constants/cryptohome_key_delegate_constants.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
@@ -182,14 +180,10 @@
 #include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/scoped_nss_types.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "net/base/network_change_notifier.h"
 #include "net/base/network_change_notifier_posix.h"
-#include "net/cert/nss_cert_database.h"
-#include "net/cert/nss_cert_database_chromeos.h"
 #include "printing/backend/print_backend.h"
 #include "rlz/buildflags/buildflags.h"
 #include "services/audio/public/cpp/sounds/sounds_manager.h"
@@ -241,50 +235,6 @@
   }
 }
 
-// Called on UI Thread when the system slot has been retrieved.
-void GotSystemSlotOnUIThread(
-    base::Callback<void(crypto::ScopedPK11Slot)> callback_ui_thread,
-    crypto::ScopedPK11Slot system_slot) {
-  callback_ui_thread.Run(std::move(system_slot));
-}
-
-// Called on IO Thread when the system slot has been retrieved.
-void GotSystemSlotOnIOThread(
-    base::Callback<void(crypto::ScopedPK11Slot)> callback_ui_thread,
-    crypto::ScopedPK11Slot system_slot) {
-  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
-                 base::BindOnce(&GotSystemSlotOnUIThread, callback_ui_thread,
-                                std::move(system_slot)));
-}
-
-// Called on IO Thread, initiates retrieval of system slot. |callback_ui_thread|
-// will be executed on the UI thread when the system slot has been retrieved.
-void GetSystemSlotOnIOThread(
-    base::Callback<void(crypto::ScopedPK11Slot)> callback_ui_thread) {
-  auto callback =
-      base::BindRepeating(&GotSystemSlotOnIOThread, callback_ui_thread);
-  crypto::ScopedPK11Slot system_nss_slot =
-      crypto::GetSystemNSSKeySlot(callback);
-  if (system_nss_slot) {
-    callback.Run(std::move(system_nss_slot));
-  }
-}
-
-// Decides if on start we shall signal to the platform that it can attempt
-// owning the TPM.
-// For official Chrome builds, send this signal if EULA has been accepted
-// already (i.e. the user has started OOBE) to make sure we are not stuck with
-// uninitialized TPM after an interrupted OOBE process.
-// For Chromium builds, don't send it here. Instead, rely on this signal being
-// sent after each successful login.
-bool ShallAttemptTpmOwnership() {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  return StartupUtils::IsEulaAccepted();
-#else
-  return false;
-#endif
-}
-
 }  // namespace
 
 namespace internal {
@@ -459,97 +409,6 @@
   DISALLOW_COPY_AND_ASSIGN(DBusServices);
 };
 
-// Initializes a global NSSCertDatabase for the system token and starts
-// NetworkCertLoader with that database. Note that this is triggered from
-// PreMainMessageLoopRun, which is executed after PostMainMessageLoopStart,
-// where NetworkCertLoader is initialized. We can thus assume that
-// NetworkCertLoader is initialized.
-class SystemTokenCertDBInitializer {
- public:
-  SystemTokenCertDBInitializer() {}
-  ~SystemTokenCertDBInitializer() {}
-
-  // Entry point, called on UI thread.
-  void Initialize() {
-    // Only start loading the system token once cryptohome is available and only
-    // if the TPM is ready (available && owned && not being owned).
-    CryptohomeClient::Get()->WaitForServiceToBeAvailable(
-        base::Bind(&SystemTokenCertDBInitializer::OnCryptohomeAvailable,
-                   weak_ptr_factory_.GetWeakPtr()));
-  }
-
- private:
-  // Called once the cryptohome service is available.
-  void OnCryptohomeAvailable(bool available) {
-    if (!available) {
-      LOG(ERROR) << "SystemTokenCertDBInitializer: Failed to wait for "
-                    "cryptohome to become available.";
-      return;
-    }
-
-    VLOG(1) << "SystemTokenCertDBInitializer: Cryptohome available.";
-    CryptohomeClient::Get()->TpmIsReady(
-        base::Bind(&SystemTokenCertDBInitializer::OnGotTpmIsReady,
-                   weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  // This is a callback for the cryptohome TpmIsReady query. Note that this is
-  // not a listener which would be called once TPM becomes ready if it was not
-  // ready on startup (e.g. after device enrollment), see crbug.com/725500.
-  void OnGotTpmIsReady(base::Optional<bool> tpm_is_ready) {
-    if (!tpm_is_ready.has_value() || !tpm_is_ready.value()) {
-      VLOG(1) << "SystemTokenCertDBInitializer: TPM is not ready - not loading "
-                 "system token.";
-      if (ShallAttemptTpmOwnership()) {
-        // Signal to cryptohome that it can attempt TPM ownership, if it
-        // haven't done that yet. The previous signal from EULA dialogue could
-        // have been lost if initialization was interrupted.
-        // We don't care about the result, and don't block waiting for it.
-        LOG(WARNING) << "Request attempting TPM ownership.";
-        CryptohomeClient::Get()->TpmCanAttemptOwnership(
-            EmptyVoidDBusMethodCallback());
-      }
-
-      return;
-    }
-    VLOG(1)
-        << "SystemTokenCertDBInitializer: TPM is ready, loading system token.";
-    TPMTokenLoader::Get()->EnsureStarted();
-    base::Callback<void(crypto::ScopedPK11Slot)> callback =
-        base::BindRepeating(&SystemTokenCertDBInitializer::InitializeDatabase,
-                            weak_ptr_factory_.GetWeakPtr());
-    base::PostTask(FROM_HERE, {content::BrowserThread::IO},
-                   base::BindOnce(&GetSystemSlotOnIOThread, callback));
-  }
-
-  // Initializes the global system token NSSCertDatabase with |system_slot|.
-  // Also starts NetworkCertLoader with the system token database.
-  void InitializeDatabase(crypto::ScopedPK11Slot system_slot) {
-    // Currently, NSSCertDatabase requires a public slot to be set, so we use
-    // the system slot there. We also want GetSystemSlot() to return the system
-    // slot. As ScopedPK11Slot is actually a unique_ptr which will be moved into
-    // the NSSCertDatabase, we need to create a copy, referencing the same slot
-    // (using PK11_ReferenceSlot).
-    crypto::ScopedPK11Slot system_slot_copy =
-        crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot.get()));
-    auto database = std::make_unique<net::NSSCertDatabaseChromeOS>(
-        std::move(system_slot) /* public_slot */,
-        crypto::ScopedPK11Slot() /* private_slot */);
-    database->SetSystemSlot(std::move(system_slot_copy));
-
-    system_token_cert_database_ = std::move(database);
-
-    VLOG(1) << "SystemTokenCertDBInitializer: Passing system token NSS "
-               "database to NetworkCertLoader.";
-    NetworkCertLoader::Get()->SetSystemNSSDB(system_token_cert_database_.get());
-  }
-
-  // Global NSSCertDatabase which sees the system token.
-  std::unique_ptr<net::NSSCertDatabase> system_token_cert_database_;
-
-  base::WeakPtrFactory<SystemTokenCertDBInitializer> weak_ptr_factory_{this};
-};
-
 }  // namespace internal
 
 // ChromeBrowserMainPartsChromeos ----------------------------------------------
@@ -654,8 +513,7 @@
 
   // Initialize NSS database for system token.
   system_token_certdb_initializer_ =
-      std::make_unique<internal::SystemTokenCertDBInitializer>();
-  system_token_certdb_initializer_->Initialize();
+      std::make_unique<SystemTokenCertDBInitializer>();
 
   CrasAudioHandler::Initialize(
       content::GetSystemConnector(),
@@ -1263,6 +1121,10 @@
   network_change_manager_client_.reset();
   session_termination_manager_.reset();
 
+  // The cert database initializer must be shut down before DBus services are
+  // destroyed.
+  system_token_certdb_initializer_->ShutDown();
+
   // Destroy DBus services immediately after threads are stopped.
   dbus_services_.reset();
 
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index 75fe1f0..cf25a77 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -60,6 +60,7 @@
 class SchedulerConfigurationManager;
 class SessionTerminationManager;
 class ShutdownPolicyForwarder;
+class SystemTokenCertDBInitializer;
 class WakeOnWifiManager;
 class WilcoDtcSupportdManager;
 
@@ -69,7 +70,6 @@
 
 namespace internal {
 class DBusServices;
-class SystemTokenCertDBInitializer;
 }  // namespace internal
 
 namespace power {
@@ -124,7 +124,7 @@
 
   std::unique_ptr<internal::DBusServices> dbus_services_;
 
-  std::unique_ptr<internal::SystemTokenCertDBInitializer>
+  std::unique_ptr<SystemTokenCertDBInitializer>
       system_token_certdb_initializer_;
 
   std::unique_ptr<ShutdownPolicyForwarder> shutdown_policy_forwarder_;
diff --git a/chrome/browser/chromeos/dbus/dbus_helper.cc b/chrome/browser/chromeos/dbus/dbus_helper.cc
index 60eee42..674fbba0 100644
--- a/chrome/browser/chromeos/dbus/dbus_helper.cc
+++ b/chrome/browser/chromeos/dbus/dbus_helper.cc
@@ -17,6 +17,7 @@
 #include "chromeos/dbus/cros_healthd/cros_healthd_client.h"
 #include "chromeos/dbus/cups_proxy/cups_proxy_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/dlcservice/dlcservice_client.h"
 #include "chromeos/dbus/initialize_dbus_client.h"
 #include "chromeos/dbus/kerberos/kerberos_client.h"
 #include "chromeos/dbus/machine_learning/machine_learning_client.h"
@@ -63,6 +64,7 @@
   InitializeDBusClient<CrosHealthdClient>(bus);
   InitializeDBusClient<CryptohomeClient>(bus);
   InitializeDBusClient<CupsProxyClient>(bus);
+  InitializeDBusClient<DlcserviceClient>(bus);
   InitializeDBusClient<KerberosClient>(bus);
   InitializeDBusClient<MachineLearningClient>(bus);
   InitializeDBusClient<MediaAnalyticsClient>(bus);
@@ -98,6 +100,7 @@
   MediaAnalyticsClient::Shutdown();
   MachineLearningClient::Shutdown();
   KerberosClient::Shutdown();
+  DlcserviceClient::Shutdown();
   CupsProxyClient::Shutdown();
   CryptohomeClient::Shutdown();
   CrosHealthdClient::Shutdown();
diff --git a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
index 873cde7..5157446 100644
--- a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
@@ -46,12 +46,13 @@
 #define MAYBE_TestDeviceRequisition TestDeviceRequisition
 #endif
 
+// Disabled due to flakiness: https://crbug.com/997685.
+#define MAYBE_TestDemoModeAcceptEula DISABLED_TestDemoModeAcceptEula
+#define MAYBE_TestDemoModeOfflineNetwork DISABLED_TestDemoModeOfflineNetwork
 // Disabled on debug build due to flakiness: https://crbug.com/997685.
 #if !defined(NDEBUG)
 #define MAYBE_TestAcceptEula DISABLED_TestAcceptEula
 #define MAYBE_TestDemoModeAcceptArcTos DISABLED_TestDemoModeAcceptArcTos
-#define MAYBE_TestDemoModeAcceptEula DISABLED_TestDemoModeAcceptEula
-#define MAYBE_TestDemoModeOfflineNetwork DISABLED_TestDemoModeOfflineNetwork
 #define MAYBE_TestDemoModePreferences DISABLED_TestDemoModePreferences
 #define MAYBE_TestEnableDemoMode DISABLED_TestEnableDemoMode
 #define MAYBE_TestLeaveWelcomeScreen DISABLED_TestLeaveWelcomeScreen
@@ -61,8 +62,6 @@
 #else
 #define MAYBE_TestAcceptEula TestAcceptEula
 #define MAYBE_TestDemoModeAcceptArcTos TestDemoModeAcceptArcTos
-#define MAYBE_TestDemoModeAcceptEula TestDemoModeAcceptEula
-#define MAYBE_TestDemoModeOfflineNetwork TestDemoModeOfflineNetwork
 #define MAYBE_TestDemoModePreferences TestDemoModePreferences
 #define MAYBE_TestEnableDemoMode TestEnableDemoMode
 #define MAYBE_TestLeaveWelcomeScreen TestLeaveWelcomeScreen
@@ -350,7 +349,7 @@
 
 // Check that HID detection screen is shown if it is not specified by
 // configuration.
-IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, TestShowHID) {
+IN_PROC_BROWSER_TEST_F(OobeConfigurationTestNoHID, TestLeaveWelcomeScreen) {
   LoadConfiguration();
   OobeScreenWaiter(HIDDetectionView::kScreenId).Wait();
 }
diff --git a/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
index 664545c7..1d49104 100644
--- a/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enrollment/hands_off_enrollment_browsertest.cc
@@ -152,10 +152,7 @@
   WizardController::default_controller()->AdvanceToScreen(
       WelcomeView::kScreenId);
 
-  OobeScreenWaiter screen_waiter(NetworkScreenView::kScreenId);
-  // WebUI window is not visible until the screen animation finishes.
-  screen_waiter.set_no_check_native_window_visible();
-  screen_waiter.Wait();
+  OobeScreenWaiter(NetworkScreenView::kScreenId).Wait();
 
   OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait();
 
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
index 45c1dcbf..d460bfdc 100644
--- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
+++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -3,8 +3,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <memory>
-
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "base/bind.h"
@@ -14,8 +12,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "build/branding_buildflags.h"
-#include "chrome/browser/chrome_browser_main.h"
-#include "chrome/browser/chrome_browser_main_extra_parts.h"
 #include "chrome/browser/chromeos/arc/arc_service_launcher.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api.h"
@@ -57,8 +53,6 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
 #include "ui/display/display_switches.h"
 
 using net::test_server::BasicHttpResponse;
@@ -354,58 +348,6 @@
       ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver);
 };
 
-// Observes an |aura::Window| to see if the window was visible at some point in
-// time.
-class NativeWindowVisibilityObserver : public aura::WindowObserver {
- public:
-  NativeWindowVisibilityObserver() = default;
-  // aura::Window will remove observers on destruction.
-  ~NativeWindowVisibilityObserver() override = default;
-
-  void Observe(aura::Window* window) {
-    window_ = window;
-    window_->AddObserver(this);
-  }
-
-  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
-    if (visible)
-      was_visible_ = visible;
-  }
-
-  bool was_visible() { return was_visible_; }
-
- private:
-  // The window was visible at some point in time.
-  bool was_visible_ = false;
-
-  aura::Window* window_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeWindowVisibilityObserver);
-};
-
-// Sets the |NativeWindowVisibilityObserver| to observe the
-// |LoginDisplayHost|'s |NativeWindow|. This needs to be done in
-// |PostProfileInit()| as the |default_host| will not be initialized before
-// this.
-class NativeWindowVisibilityBrowserMainExtraParts
-    : public ChromeBrowserMainExtraParts {
- public:
-  NativeWindowVisibilityBrowserMainExtraParts(
-      NativeWindowVisibilityObserver* observer)
-      : observer_(observer) {}
-  ~NativeWindowVisibilityBrowserMainExtraParts() override = default;
-
-  // ChromeBrowserMainExtraParts:
-  void PostProfileInit() override {
-    observer_->Observe(LoginDisplayHost::default_host()->GetNativeWindow());
-  }
-
- private:
-  NativeWindowVisibilityObserver* observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeWindowVisibilityBrowserMainExtraParts);
-};
-
 class OobeEndToEndTestSetupMixin : public InProcessBrowserTestMixin {
  public:
   struct Parameters {
@@ -736,8 +678,7 @@
       : PublicSessionOobeTest(false /*requires_terms_of_service*/) {}
 
   explicit PublicSessionOobeTest(bool requires_terms_of_service)
-      : requires_terms_of_service_(requires_terms_of_service),
-        observer_(std::make_unique<NativeWindowVisibilityObserver>()) {
+      : requires_terms_of_service_(requires_terms_of_service) {
     // Prevents Chrome from starting to quit right after login display is
     // finalized.
     login_manager_.set_should_launch_browser(true);
@@ -781,26 +722,11 @@
     MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
   }
 
-  void CreatedBrowserMainParts(content::BrowserMainParts* parts) override {
-    MixinBasedInProcessBrowserTest::CreatedBrowserMainParts(parts);
-    static_cast<ChromeBrowserMainParts*>(parts)->AddParts(
-        new NativeWindowVisibilityBrowserMainExtraParts(observer_.get()));
-  }
-
-  void TearDownOnMainThread() override {
-    observer_.reset();
-    MixinBasedInProcessBrowserTest::TearDownOnMainThread();
-  }
-
-  bool DialogWasVisible() { return observer_->was_visible(); }
-
   LoginManagerMixin login_manager_{&mixin_host_, {}};
 
  private:
   const bool requires_terms_of_service_;
 
-  std::unique_ptr<NativeWindowVisibilityObserver> observer_;
-
   OobeEndToEndTestSetupMixin setup_{&mixin_host_, nullptr, GetParam()};
   DeviceStateMixin device_state_{
       &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
@@ -808,8 +734,6 @@
 
 IN_PROC_BROWSER_TEST_P(PublicSessionOobeTest, NoTermsOfService) {
   login_manager_.WaitForActiveSession();
-  // Check that the dialog was never shown.
-  EXPECT_FALSE(DialogWasVisible());
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 8fd2323..936945a 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -1482,9 +1482,6 @@
 // Verifies that password attributes are extracted and stored during a
 // successful log in - but only if the appropriate policy is enabled.
 IN_PROC_BROWSER_TEST_P(SAMLPasswordAttributesTest, LoginSucceeded) {
-  // LoginDisplayHostMojo does not show Oobe dialog by default.
-  LoginDisplayHost::default_host()->ShowGaiaDialog(true, EmptyAccountId());
-
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   fake_saml_idp()->SetSamlResponseFile("saml_with_password_attributes.xml");
   StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
@@ -1516,9 +1513,6 @@
 
 // Verify that no password attributes are stored when login fails.
 IN_PROC_BROWSER_TEST_P(SAMLPasswordAttributesTest, LoginFailed) {
-  // LoginDisplayHostMojo does not show Oobe dialog by default.
-  LoginDisplayHost::default_host()->ShowGaiaDialog(true, EmptyAccountId());
-
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   fake_saml_idp()->SetSamlResponseFile("saml_with_password_attributes.xml");
   StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
index c45c4a3..6f7c21a 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.cc
@@ -6,11 +6,7 @@
 
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/window.h"
-#include "ui/views/controls/webview/webview.h"
-#include "ui/views/view.h"
 
 namespace chromeos {
 
@@ -22,20 +18,13 @@
 void OobeScreenWaiter::Wait() {
   DCHECK_EQ(State::IDLE, state_);
 
-  if ((!check_native_window_visible_ || IsNativeWindowVisible()) &&
-      IsTargetScreenReached()) {
+  if (GetOobeUI()->current_screen() == target_screen_) {
     state_ = State::DONE;
     return;
   }
   DCHECK(!run_loop_);
 
   oobe_ui_observer_.Add(GetOobeUI());
-  if (check_native_window_visible_) {
-    aura::Window* native_window =
-        LoginDisplayHost::default_host()->GetNativeWindow();
-    DCHECK(native_window);
-    native_window_observer_.Add(native_window);
-  }
 
   state_ = State::WAITING_FOR_SCREEN;
 
@@ -46,8 +35,6 @@
   DCHECK_EQ(State::DONE, state_);
 
   oobe_ui_observer_.RemoveAll();
-  if (check_native_window_visible_)
-    native_window_observer_.RemoveAll();
 
   if (assert_last_screen_)
     EXPECT_EQ(target_screen_, GetOobeUI()->current_screen());
@@ -73,33 +60,10 @@
     return;
   }
 
-  if (check_native_window_visible_ && !IsNativeWindowVisible()) {
-    return;
-  }
-
-  if (IsTargetScreenReached())
+  if (new_screen == target_screen_)
     EndWait();
 }
 
-void OobeScreenWaiter::OnWindowVisibilityChanged(aura::Window* window,
-                                                 bool visible) {
-  DCHECK_NE(state_, State::IDLE);
-  DCHECK(check_native_window_visible_);
-
-  if (IsNativeWindowVisible() && IsTargetScreenReached())
-    EndWait();
-}
-
-bool OobeScreenWaiter::IsTargetScreenReached() {
-  return GetOobeUI()->current_screen() == target_screen_;
-}
-
-bool OobeScreenWaiter::IsNativeWindowVisible() {
-  aura::Window* native_window =
-      LoginDisplayHost::default_host()->GetNativeWindow();
-  return native_window && native_window->IsVisible();
-}
-
 void OobeScreenWaiter::OnDestroyingOobeUI() {
   oobe_ui_observer_.RemoveAll();
 
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
index c737b1e..3dedcd2 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
@@ -10,7 +10,6 @@
 #include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
-#include "ui/aura/window_observer.h"
 
 namespace base {
 class RunLoop;
@@ -22,17 +21,13 @@
 
 // A waiter that blocks until the target oobe screen is reached.
 class OobeScreenWaiter : public OobeUI::Observer,
-                         public test::TestConditionWaiter,
-                         public aura::WindowObserver {
+                         public test::TestConditionWaiter {
  public:
   explicit OobeScreenWaiter(OobeScreenId target_screen);
   ~OobeScreenWaiter() override;
 
   void set_no_assert_last_screen() { assert_last_screen_ = false; }
   void set_assert_next_screen() { assert_next_screen_ = true; }
-  void set_no_check_native_window_visible() {
-    check_native_window_visible_ = false;
-  }
 
   // OobeUI::Observer implementation:
   void OnCurrentScreenChanged(OobeScreenId current_screen,
@@ -42,21 +37,12 @@
   // TestConditionWaiter;
   void Wait() override;
 
-  // aura::WindowObserver:
-  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
-
  private:
   enum class State { IDLE, WAITING_FOR_SCREEN, DONE };
 
   OobeUI* GetOobeUI();
   void EndWait();
 
-  // Returns true if the target screen is reached.
-  bool IsTargetScreenReached();
-
-  // Returns true if the native window is visible.
-  bool IsNativeWindowVisible();
-
   const OobeScreenId target_screen_;
 
   State state_ = State::IDLE;
@@ -66,20 +52,12 @@
   // This applies to the time period Wait() is running only.
   bool assert_last_screen_ = true;
 
-  // If set, the waiter will assert OOBE UI does not transition to any other
-  // screen before transitioning to the target screen.
+  // If set, the watier will assert OOBE UI does not transition to any other
+  // screen before transisioning to the target screen.
   bool assert_next_screen_ = false;
 
-  // If set, the waiter will only finish waiting if the target screen has been
-  // reached and the native window is visible. The assert_last_screen and
-  // assert_next_screen checks will only be done if the native window is
-  // visible. True by default.
-  bool check_native_window_visible_ = true;
-
   ScopedObserver<OobeUI, OobeScreenWaiter> oobe_ui_observer_{this};
 
-  ScopedObserver<aura::Window, OobeScreenWaiter> native_window_observer_{this};
-
   std::unique_ptr<base::RunLoop> run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(OobeScreenWaiter);
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index e75c71a..b38f22a 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -78,7 +78,6 @@
   LoginScreenClient::Get()->SetDelegate(nullptr);
   if (dialog_) {
     dialog_->GetOobeUI()->signin_screen_handler()->SetDelegate(nullptr);
-    StopObservingOobeUI();
     dialog_->Close();
   }
 }
@@ -86,7 +85,6 @@
 void LoginDisplayHostMojo::OnDialogDestroyed(
     const OobeUIDialogDelegate* dialog) {
   if (dialog == dialog_) {
-    StopObservingOobeUI();
     dialog_ = nullptr;
     wizard_controller_.reset();
   }
@@ -103,25 +101,25 @@
   DCHECK(GetOobeUI());
   GetOobeUI()->signin_screen_handler()->ShowPasswordChangedDialog(
       show_password_error, email);
-  ShowDialog();
+  dialog_->Show();
 }
 
 void LoginDisplayHostMojo::ShowWhitelistCheckFailedError() {
   DCHECK(GetOobeUI());
   GetOobeUI()->signin_screen_handler()->ShowWhitelistCheckFailedError();
-  ShowDialog();
+  dialog_->Show();
 }
 
 void LoginDisplayHostMojo::ShowErrorScreen(LoginDisplay::SigninError error_id) {
   DCHECK(GetOobeUI());
   GetOobeUI()->signin_screen_handler()->ShowErrorScreen(error_id);
-  ShowDialog();
+  dialog_->Show();
 }
 
 void LoginDisplayHostMojo::ShowSigninUI(const std::string& email) {
   DCHECK(GetOobeUI());
   GetOobeUI()->signin_screen_handler()->ShowSigninUI(email);
-  ShowDialog();
+  dialog_->Show();
 }
 
 void LoginDisplayHostMojo::HandleDisplayCaptivePortal() {
@@ -176,15 +174,12 @@
 }
 
 void LoginDisplayHostMojo::StartWizard(OobeScreenId first_screen) {
-  OobeUI* oobe_ui = GetOobeUI();
-  DCHECK(oobe_ui);
-  // Dialog is not shown immediately, and will be shown only when a screen
-  // change occurs. This prevents the dialog from showing when there are no
-  // screens to show.
-  ObserveOobeUI();
+  DCHECK(GetOobeUI());
 
   wizard_controller_ = std::make_unique<WizardController>();
   wizard_controller_->Init(first_screen);
+
+  dialog_->Show();
 }
 
 WizardController* LoginDisplayHostMojo::GetWizardController() {
@@ -246,11 +241,11 @@
 }
 
 void LoginDisplayHostMojo::OnStartAppLaunch() {
-  ShowFullScreen();
+  dialog_->ShowFullScreen();
 }
 
 void LoginDisplayHostMojo::OnStartArcKiosk() {
-  ShowFullScreen();
+  dialog_->ShowFullScreen();
 }
 
 void LoginDisplayHostMojo::OnBrowserCreated() {
@@ -269,7 +264,7 @@
 
   ShowGaiaDialogCommon(prefilled_account);
 
-  ShowDialog();
+  dialog_->Show();
 }
 
 void LoginDisplayHostMojo::HideOobeDialog() {
@@ -285,7 +280,7 @@
   }
 
   LoadWallpaper(focused_pod_account_id_);
-  HideDialog();
+  dialog_->Hide();
 }
 
 void LoginDisplayHostMojo::UpdateOobeDialogSize(int width, int height) {
@@ -456,17 +451,6 @@
     const UserContext& user_context,
     bool has_incomplete_migration) {}
 
-void LoginDisplayHostMojo::OnCurrentScreenChanged(OobeScreenId current_screen,
-                                                  OobeScreenId new_screen) {
-  DCHECK(dialog_);
-  if (!dialog_->IsVisible())
-    ShowDialog();
-}
-
-void LoginDisplayHostMojo::OnDestroyingOobeUI() {
-  StopObservingOobeUI();
-}
-
 void LoginDisplayHostMojo::LoadOobeDialog() {
   if (dialog_)
     return;
@@ -500,45 +484,4 @@
   existing_user_controller_->Login(user_context, chromeos::SigninSpecifics());
 }
 
-void LoginDisplayHostMojo::ShowDialog() {
-  ObserveOobeUI();
-  dialog_->Show();
-}
-
-void LoginDisplayHostMojo::ShowFullScreen() {
-  ObserveOobeUI();
-  dialog_->ShowFullScreen();
-}
-
-void LoginDisplayHostMojo::HideDialog() {
-  // Stop observing so that dialog will not be shown when a screen change
-  // occurs. Screen changes can occur even when the dialog is not shown (e.g.
-  // with hidden error screens).
-  StopObservingOobeUI();
-  dialog_->Hide();
-}
-
-void LoginDisplayHostMojo::ObserveOobeUI() {
-  if (added_as_oobe_observer_)
-    return;
-
-  OobeUI* oobe_ui = GetOobeUI();
-  if (!oobe_ui)
-    return;
-
-  oobe_ui->AddObserver(this);
-  added_as_oobe_observer_ = true;
-}
-
-void LoginDisplayHostMojo::StopObservingOobeUI() {
-  if (!added_as_oobe_observer_)
-    return;
-
-  added_as_oobe_observer_ = false;
-
-  OobeUI* oobe_ui = GetOobeUI();
-  if (oobe_ui)
-    oobe_ui->RemoveObserver(this);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
index 7cc02dc..ba9f5127 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -18,7 +18,6 @@
 #include "chrome/browser/chromeos/login/ui/login_display_host_common.h"
 #include "chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h"
 #include "chrome/browser/ui/ash/login_screen_client.h"
-#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
 #include "chromeos/login/auth/challenge_response_key.h"
 
@@ -35,8 +34,7 @@
 // screen.
 class LoginDisplayHostMojo : public LoginDisplayHostCommon,
                              public LoginScreenClient::Delegate,
-                             public AuthStatusConsumer,
-                             public OobeUI::Observer {
+                             public AuthStatusConsumer {
  public:
   LoginDisplayHostMojo();
   ~LoginDisplayHostMojo() override;
@@ -128,11 +126,6 @@
   void OnOldEncryptionDetected(const UserContext& user_context,
                                bool has_incomplete_migration) override;
 
-  // OobeUI::Observer:
-  void OnCurrentScreenChanged(OobeScreenId current_screen,
-                              OobeScreenId new_screen) override;
-  void OnDestroyingOobeUI() override;
-
  private:
   void LoadOobeDialog();
 
@@ -144,17 +137,6 @@
       base::OnceCallback<void(bool)> on_auth_complete_callback,
       std::vector<ChallengeResponseKey> challenge_response_keys);
 
-  // Helper methods to show and hide the dialog.
-  void ShowDialog();
-  void ShowFullScreen();
-  void HideDialog();
-
-  // Adds this as a |OobeUI::Observer| if it has not already been added as one.
-  void ObserveOobeUI();
-
-  // Removes this as a |OobeUI::Observer| if it has been added as an observer.
-  void StopObservingOobeUI();
-
   // State associated with a pending authentication attempt.
   struct AuthState {
     AuthState(AccountId account_id, base::OnceCallback<void(bool)> callback);
@@ -199,9 +181,6 @@
 
   SecurityTokenPinDialogHostAshImpl security_token_pin_dialog_host_ash_impl_;
 
-  // Set if this has been added as a |OobeUI::Observer|.
-  bool added_as_oobe_observer_ = false;
-
   base::WeakPtrFactory<LoginDisplayHostMojo> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(LoginDisplayHostMojo);
diff --git a/chrome/browser/chromeos/system_token_cert_db_initializer.cc b/chrome/browser/chromeos/system_token_cert_db_initializer.cc
new file mode 100644
index 0000000..6ea2e78
--- /dev/null
+++ b/chrome/browser/chromeos/system_token_cert_db_initializer.cc
@@ -0,0 +1,152 @@
+// 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/chromeos/system_token_cert_db_initializer.h"
+
+#include <pk11pub.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/task/post_task.h"
+#include "build/branding_buildflags.h"
+#include "build/buildflag.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/network/network_cert_loader.h"
+#include "chromeos/tpm/tpm_token_loader.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "crypto/nss_util_internal.h"
+#include "net/cert/nss_cert_database.h"
+#include "net/cert/nss_cert_database_chromeos.h"
+
+namespace chromeos {
+
+namespace {
+
+// Called on UI Thread when the system slot has been retrieved.
+void GotSystemSlotOnUIThread(
+    base::OnceCallback<void(crypto::ScopedPK11Slot)> callback_ui_thread,
+    crypto::ScopedPK11Slot system_slot) {
+  std::move(callback_ui_thread).Run(std::move(system_slot));
+}
+
+// Called on IO Thread when the system slot has been retrieved.
+void GotSystemSlotOnIOThread(
+    base::OnceCallback<void(crypto::ScopedPK11Slot)> callback_ui_thread,
+    crypto::ScopedPK11Slot system_slot) {
+  base::PostTask(
+      FROM_HERE, {content::BrowserThread::UI},
+      base::BindOnce(&GotSystemSlotOnUIThread, std::move(callback_ui_thread),
+                     std::move(system_slot)));
+}
+
+// Called on IO Thread, initiates retrieval of system slot. |callback_ui_thread|
+// will be executed on the UI thread when the system slot has been retrieved.
+void GetSystemSlotOnIOThread(
+    base::RepeatingCallback<void(crypto::ScopedPK11Slot)> callback_ui_thread) {
+  auto callback =
+      base::BindRepeating(&GotSystemSlotOnIOThread, callback_ui_thread);
+  crypto::ScopedPK11Slot system_nss_slot =
+      crypto::GetSystemNSSKeySlot(callback);
+  if (system_nss_slot) {
+    callback.Run(std::move(system_nss_slot));
+  }
+}
+
+// Decides if on start we shall signal to the platform that it can attempt
+// owning the TPM.
+// For official Chrome builds, send this signal if EULA has been accepted
+// already (i.e. the user has started OOBE) to make sure we are not stuck with
+// uninitialized TPM after an interrupted OOBE process.
+// For Chromium builds, don't send it here. Instead, rely on this signal being
+// sent after each successful login.
+bool ShallAttemptTpmOwnership() {
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  return StartupUtils::IsEulaAccepted();
+#else
+  return false;
+#endif
+}
+
+}  // namespace
+
+SystemTokenCertDBInitializer::SystemTokenCertDBInitializer() {
+  // Only start loading the system token once cryptohome is available and only
+  // if the TPM is ready (available && owned && not being owned).
+  CryptohomeClient::Get()->WaitForServiceToBeAvailable(
+      base::BindOnce(&SystemTokenCertDBInitializer::OnCryptohomeAvailable,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+SystemTokenCertDBInitializer::~SystemTokenCertDBInitializer() = default;
+
+void SystemTokenCertDBInitializer::ShutDown() {}
+
+void SystemTokenCertDBInitializer::OnCryptohomeAvailable(bool available) {
+  if (!available) {
+    LOG(ERROR) << "SystemTokenCertDBInitializer: Failed to wait for "
+                  "cryptohome to become available.";
+    return;
+  }
+
+  VLOG(1) << "SystemTokenCertDBInitializer: Cryptohome available.";
+  CryptohomeClient::Get()->TpmIsReady(
+      base::BindOnce(&SystemTokenCertDBInitializer::OnGotTpmIsReady,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SystemTokenCertDBInitializer::OnGotTpmIsReady(
+    base::Optional<bool> tpm_is_ready) {
+  if (!tpm_is_ready.has_value() || !tpm_is_ready.value()) {
+    VLOG(1) << "SystemTokenCertDBInitializer: TPM is not ready - not loading "
+               "system token.";
+    if (ShallAttemptTpmOwnership()) {
+      // Signal to cryptohome that it can attempt TPM ownership, if it
+      // haven't done that yet. The previous signal from EULA dialogue could
+      // have been lost if initialization was interrupted.
+      // We don't care about the result, and don't block waiting for it.
+      LOG(WARNING) << "Request attempting TPM ownership.";
+      CryptohomeClient::Get()->TpmCanAttemptOwnership(
+          EmptyVoidDBusMethodCallback());
+    }
+
+    return;
+  }
+  VLOG(1)
+      << "SystemTokenCertDBInitializer: TPM is ready, loading system token.";
+  TPMTokenLoader::Get()->EnsureStarted();
+  base::RepeatingCallback<void(crypto::ScopedPK11Slot)> callback =
+      base::BindRepeating(&SystemTokenCertDBInitializer::InitializeDatabase,
+                          weak_ptr_factory_.GetWeakPtr());
+  base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                 base::BindOnce(&GetSystemSlotOnIOThread, callback));
+}
+
+void SystemTokenCertDBInitializer::InitializeDatabase(
+    crypto::ScopedPK11Slot system_slot) {
+  // Currently, NSSCertDatabase requires a public slot to be set, so we use
+  // the system slot there. We also want GetSystemSlot() to return the system
+  // slot. As ScopedPK11Slot is actually a unique_ptr which will be moved into
+  // the NSSCertDatabase, we need to create a copy, referencing the same slot
+  // (using PK11_ReferenceSlot).
+  crypto::ScopedPK11Slot system_slot_copy =
+      crypto::ScopedPK11Slot(PK11_ReferenceSlot(system_slot.get()));
+  auto database = std::make_unique<net::NSSCertDatabaseChromeOS>(
+      /*public_slot=*/std::move(system_slot),
+      /*private_slot=*/crypto::ScopedPK11Slot());
+  database->SetSystemSlot(std::move(system_slot_copy));
+
+  system_token_cert_database_ = std::move(database);
+
+  VLOG(1) << "SystemTokenCertDBInitializer: Passing system token NSS "
+             "database to NetworkCertLoader.";
+  NetworkCertLoader::Get()->SetSystemNSSDB(system_token_cert_database_.get());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/system_token_cert_db_initializer.h b/chrome/browser/chromeos/system_token_cert_db_initializer.h
new file mode 100644
index 0000000..e25ee581
--- /dev/null
+++ b/chrome/browser/chromeos/system_token_cert_db_initializer.h
@@ -0,0 +1,60 @@
+// 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_BROWSER_CHROMEOS_SYSTEM_TOKEN_CERT_DB_INITIALIZER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_TOKEN_CERT_DB_INITIALIZER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace net {
+class NSSCertDatabase;
+}
+
+namespace chromeos {
+
+// Initializes a global NSSCertDatabase for the system token and starts
+// NetworkCertLoader with that database.
+//
+// Lifetime: The global NetworkCertLoader instance must exist until ShutDown()
+// has been called. The global NetworkCertLoader instance must exist until
+// ShutDown() has been called, but must be outlived by this object.
+//
+// All of the methods must be called on the UI thread.
+class SystemTokenCertDBInitializer final {
+ public:
+  SystemTokenCertDBInitializer();
+  ~SystemTokenCertDBInitializer();
+
+  // Stops making new requests to D-Bus services.
+  void ShutDown();
+
+ private:
+  // Called once the cryptohome service is available.
+  void OnCryptohomeAvailable(bool available);
+
+  // This is a callback for the cryptohome TpmIsReady query. Note that this is
+  // not a listener which would be called once TPM becomes ready if it was not
+  // ready on startup (e.g. after device enrollment), see crbug.com/725500.
+  void OnGotTpmIsReady(base::Optional<bool> tpm_is_ready);
+
+  // Initializes the global system token NSSCertDatabase with |system_slot|.
+  // Also starts NetworkCertLoader with the system token database.
+  void InitializeDatabase(crypto::ScopedPK11Slot system_slot);
+
+  // Global NSSCertDatabase which sees the system token.
+  std::unique_ptr<net::NSSCertDatabase> system_token_cert_database_;
+
+  base::WeakPtrFactory<SystemTokenCertDBInitializer> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(SystemTokenCertDBInitializer);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_TOKEN_CERT_DB_INITIALIZER_H_
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index ad76170..5e1c118 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -99,6 +99,7 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_response.h"
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "ui/compositor/compositor_switches.h"
 #include "ui/gl/gl_switches.h"
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 1acc82d..8fcc622 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -77,6 +77,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "ui/base/page_transition_types.h"
@@ -393,7 +394,7 @@
 
  private:
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head) {
+                         const network::mojom::URLResponseHead& response_head) {
     response_headers_ = response_head.headers;
   }
 
diff --git a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
index 1b50f59..9187ce2c 100644
--- a/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
+++ b/chrome/browser/dom_distiller/distillable_page_utils_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/browser.h"
@@ -30,6 +31,7 @@
 using ::testing::AllOf;
 using ::testing::Field;
 using ::testing::Not;
+using ::testing::Optional;
 
 // This is essentially an "enum" with human-readable strings (e.g. "adaboost",
 // "none") as values.
@@ -138,6 +140,8 @@
         .WillOnce(testing::InvokeWithoutArgs(
             this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
     NavigateAndWait(kAllPaths[i], base::TimeDelta());
+    EXPECT_THAT(GetLatestResult(web_contents_),
+                Optional(AllOf(IsDistillable(), IsLast())));
   }
 }
 
@@ -145,6 +149,7 @@
                        LocalUrlsDoNotCallObserver) {
   EXPECT_CALL(holder_, OnResult(_)).Times(0);
   NavigateAndWait("about:blank", kWaitNoExpectedCall);
+  EXPECT_EQ(GetLatestResult(web_contents_), base::nullopt);
 }
 
 using DistillablePageUtilsBrowserTestNone =
@@ -153,6 +158,7 @@
 IN_PROC_BROWSER_TEST_F(DistillablePageUtilsBrowserTestNone, NeverCallObserver) {
   EXPECT_CALL(holder_, OnResult(_)).Times(0);
   NavigateAndWait(kSimpleArticlePath, kWaitNoExpectedCall);
+  EXPECT_EQ(GetLatestResult(web_contents_), base::nullopt);
 }
 
 using DistillablePageUtilsBrowserTestOGArticle =
@@ -164,6 +170,8 @@
       .WillOnce(testing::InvokeWithoutArgs(
           this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
   NavigateAndWait(kArticlePath, base::TimeDelta());
+  EXPECT_THAT(GetLatestResult(web_contents_),
+              Optional(AllOf(IsDistillable(), IsLast())));
 }
 
 IN_PROC_BROWSER_TEST_F(DistillablePageUtilsBrowserTestOGArticle,
@@ -172,6 +180,8 @@
       .WillOnce(testing::InvokeWithoutArgs(
           this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
   NavigateAndWait(kNonArticlePath, base::TimeDelta());
+  EXPECT_THAT(GetLatestResult(web_contents_),
+              Optional(AllOf(Not(IsDistillable()), IsLast())));
 }
 
 using DistillablePageUtilsBrowserTestAdaboost =
@@ -190,6 +200,10 @@
         .WillOnce(testing::InvokeWithoutArgs(
             this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
     NavigateAndWait(paths[i], base::TimeDelta());
+
+    EXPECT_THAT(
+        GetLatestResult(web_contents_),
+        Optional(AllOf(IsDistillable(), IsLast(), Not(IsMobileFriendly()))));
   }
 }
 
@@ -204,6 +218,9 @@
       .WillOnce(testing::InvokeWithoutArgs(
           this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
   NavigateAndWait(kNonArticlePath, base::TimeDelta());
+  EXPECT_THAT(
+      GetLatestResult(web_contents_),
+      Optional(AllOf(Not(IsDistillable()), IsLast(), Not(IsMobileFriendly()))));
 }
 
 using DistillablePageUtilsBrowserTestAllArticles =
@@ -222,6 +239,9 @@
         .WillOnce(testing::InvokeWithoutArgs(
             this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
     NavigateAndWait(paths[i], base::TimeDelta());
+    EXPECT_THAT(
+        GetLatestResult(web_contents_),
+        Optional(AllOf(IsDistillable(), IsLast(), Not(IsMobileFriendly()))));
   }
 }
 
@@ -236,6 +256,9 @@
       .WillOnce(testing::InvokeWithoutArgs(
           this, &DistillablePageUtilsBrowserTestOption::QuitSoon));
   NavigateAndWait(kNonArticlePath, base::TimeDelta());
+  EXPECT_THAT(
+      GetLatestResult(web_contents_),
+      Optional(AllOf(Not(IsDistillable()), IsLast(), Not(IsMobileFriendly()))));
 }
 
 }  // namespace dom_distiller
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 37b362a..51493d96 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -88,7 +88,6 @@
 #include "chrome/browser/android/download/download_manager_service.h"
 #include "chrome/browser/android/download/download_open_source.h"
 #include "chrome/browser/android/download/download_utils.h"
-#include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #else
 #include "chrome/browser/ui/browser.h"
@@ -875,8 +874,7 @@
 #if defined(OS_ANDROID)
   content::WebContents* web_contents =
       content::DownloadItemUtils::GetWebContents(download);
-  if (!chrome::android::IsNoTouchModeEnabled() &&
-      base::FeatureList::IsEnabled(features::kDownloadsLocationChange)) {
+  if (base::FeatureList::IsEnabled(features::kDownloadsLocationChange)) {
     if (reason == DownloadConfirmationReason::SAVE_AS) {
       // If this is a 'Save As' download, just run without confirmation.
       callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 83dffa7..f176c13c 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -62,7 +62,6 @@
 #endif
 
 #if defined(OS_ANDROID)
-#include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/download/download_prompt_status.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "components/infobars/core/infobar.h"
@@ -1596,11 +1595,6 @@
 
 TEST_F(ChromeDownloadManagerDelegateTest,
        RequestConfirmation_Android_WithLocationChangeEnabled) {
-#if defined(OS_ANDROID)
-  // We do not prompt for location in this case.
-  if (chrome::android::IsNoTouchModeEnabled())
-    return;
-#endif
   DeleteContents();
   SetContents(CreateTestWebContents());
 
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index fdebd68..a5ebd3f 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -10,8 +10,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace extensions {
 namespace image_writer {
@@ -136,7 +136,7 @@
 
 void WriteFromUrlOperation::OnResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   total_response_bytes_ = response_head.content_length;
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index 617f609..b35f365 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -9,10 +9,10 @@
 
 #include "chrome/browser/extensions/api/image_writer_private/operation.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace network {
-struct ResourceResponseHead;
 class SimpleURLLoader;
 }  // namespace network
 
@@ -53,7 +53,7 @@
  private:
   void DestroySimpleURLLoader();
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head);
+                         const network::mojom::URLResponseHead& response_head);
   void OnDataDownloaded(uint64_t current);
   void OnSimpleLoaderComplete(base::FilePath file_path);
   void VerifyDownloadCompare(base::OnceClosure continuation,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 67d91d3..cfb3b381 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1525,8 +1525,8 @@
   },
   {
     "name": "enable-quic",
-    "owners": [ "rch" ],
-    "expiry_milestone": 78
+    "owners": [ "//net/quic/OWNERS" ],
+    "expiry_milestone": 88
   },
   {
     "name": "enable-reader-mode",
@@ -1849,6 +1849,11 @@
     "expiry_milestone": 79
   },
   {
+    "name": "enable-vulkan",
+    "owners": [ "penghuang" ],
+    "expiry_milestone": 82
+  },
+  {
     "name": "enable-web-authentication-ble-support",
     "owners": [ "webauthn-team@google.com" ],
     "expiry_milestone": 82
@@ -1978,7 +1983,7 @@
     "owners": [ "wensh@microsoft.com" ],
     "expiry_milestone": 80
   },
-  {
+ {
     "name": "enable-zero-copy",
     "owners": [ "ccameron", "chrome-gpu@google.com" ],
     // This flag is commonly used when asking users to help gather debug info.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 78ffac7d..8954498 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2244,6 +2244,9 @@
 const char kZeroCopyDescription[] =
     "Raster threads write directly to GPU memory associated with tiles.";
 
+const char kEnableVulkanName[] = "Vulkan";
+const char kEnableVulkanDescription[] = "Use vulkan as the graphocs backend.";
+
 // Android ---------------------------------------------------------------------
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e7e3d8d..f7f0336c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1324,6 +1324,9 @@
 extern const char kZeroCopyName[];
 extern const char kZeroCopyDescription[];
 
+extern const char kEnableVulkanName[];
+extern const char kEnableVulkanDescription[];
+
 // Android --------------------------------------------------------------------
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/image_fetcher/BUILD.gn b/chrome/browser/image_fetcher/BUILD.gn
new file mode 100644
index 0000000..9bac0cc
--- /dev/null
+++ b/chrome/browser/image_fetcher/BUILD.gn
@@ -0,0 +1,31 @@
+# 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/android/rules.gni")
+
+android_library("java") {
+  deps = [
+    "//base:base_java",
+    "//chrome/android/public/profiles:java",
+    "//chrome/lib/util/public/android:java",
+    "//content/public/android:content_java",
+    "//third_party/gif_player:gif_player_java",
+  ]
+  java_files = [
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java",
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java",
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java",
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java",
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java",
+  ]
+
+  srcjar_deps = [ "//components/image_fetcher/core:java_enums_srcjar" ]
+}
+
+generate_jni("jni_headers") {
+  sources = [
+    "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
+  ]
+}
diff --git a/chrome/lib/image_fetcher/DEPS b/chrome/browser/image_fetcher/DEPS
similarity index 70%
rename from chrome/lib/image_fetcher/DEPS
rename to chrome/browser/image_fetcher/DEPS
index 4e42d6b6..2febd10 100644
--- a/chrome/lib/image_fetcher/DEPS
+++ b/chrome/browser/image_fetcher/DEPS
@@ -3,4 +3,5 @@
   "+chrome/android/public/profiles",
 
   "+chrome/lib/util/public",
+  "+content/public/android/java/src/org/chromium/content_public",
 ]
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java
diff --git a/chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java b/chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
similarity index 100%
rename from chrome/lib/image_fetcher/public/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
rename to chrome/browser/image_fetcher/android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java
diff --git a/chrome/browser/media/router/discovery/dial/device_description_fetcher.cc b/chrome/browser/media/router/discovery/dial/device_description_fetcher.cc
index f119fbc..4ef92c5 100644
--- a/chrome/browser/media/router/discovery/dial/device_description_fetcher.cc
+++ b/chrome/browser/media/router/discovery/dial/device_description_fetcher.cc
@@ -48,7 +48,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(fetcher_);
 
-  const network::ResourceResponseHead* response_info =
+  const network::mojom::URLResponseHead* response_info =
       fetcher_->GetResponseHead();
   DCHECK(response_info);
 
diff --git a/chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc b/chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc
index 0061dbbf..d060a9e1 100644
--- a/chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc
@@ -19,6 +19,7 @@
 #include "net/url_request/redirect_info.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 // The maximum number of retries allowed for GET requests.
 constexpr int kMaxRetries = 2;
@@ -79,7 +80,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-const network::ResourceResponseHead* DialURLFetcher::GetResponseHead() const {
+const network::mojom::URLResponseHead* DialURLFetcher::GetResponseHead() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return loader_ ? loader_->ResponseInfo() : nullptr;
 }
@@ -148,7 +149,7 @@
 
 void DialURLFetcher::ReportRedirectError(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   // Cancel the request.
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/media/router/discovery/dial/dial_url_fetcher.h b/chrome/browser/media/router/discovery/dial/dial_url_fetcher.h
index 2019a5e4..79796e0 100644
--- a/chrome/browser/media/router/discovery/dial/dial_url_fetcher.h
+++ b/chrome/browser/media/router/discovery/dial/dial_url_fetcher.h
@@ -11,8 +11,9 @@
 
 #include "base/callback.h"
 #include "base/optional.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -21,7 +22,6 @@
 
 namespace network {
 class SimpleURLLoader;
-struct ResourceResponseHead;
 }  // namespace network
 
 namespace media_router {
@@ -57,7 +57,7 @@
   // owned by underlying |loader_| object and is reset per HTTP request. Returns
   // nullptr if this function is called before |loader_| has informed the caller
   // of completion.
-  const network::ResourceResponseHead* GetResponseHead() const;
+  const network::mojom::URLResponseHead* GetResponseHead() const;
 
  private:
   friend class TestDialURLFetcher;
@@ -81,7 +81,7 @@
 
   // Invokes the error callback due to redirect, and aborts the request.
   void ReportRedirectError(const net::RedirectInfo& redirect_info,
-                           const network::ResourceResponseHead& response_head,
+                           const network::mojom::URLResponseHead& response_head,
                            std::vector<std::string>* to_be_removed_headers);
 
   // Runs |error_cb_| with |message| and clears it.
diff --git a/chrome/browser/media/router/providers/dial/dial_activity_manager.cc b/chrome/browser/media/router/providers/dial/dial_activity_manager.cc
index efa9063..04d1ad9d 100644
--- a/chrome/browser/media/router/providers/dial/dial_activity_manager.cc
+++ b/chrome/browser/media/router/providers/dial/dial_activity_manager.cc
@@ -25,7 +25,7 @@
 // Returns the Application Instance URL from the POST response headers given by
 // |response_info|.
 GURL GetApplicationInstanceURL(
-    const network::ResourceResponseHead& response_info) {
+    const network::mojom::URLResponseHead& response_info) {
   if (!response_info.headers)
     return GURL();
 
@@ -264,7 +264,7 @@
     return;
 
   auto& record = record_it->second;
-  const network::ResourceResponseHead* response_info =
+  const network::mojom::URLResponseHead* response_info =
       record->pending_launch_request->fetcher->GetResponseHead();
 
   DCHECK(response_info);
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc
index 6ba282f..440b5e70 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -774,8 +774,7 @@
           EmitAudioServiceMemoryMetrics(
               pmd, ukm::UkmRecorder::GetNewSourceID(), GetUkmRecorder(),
               GetProcessUptime(now, pmd.pid()), emit_metrics_for_all_processes);
-        } else if (base::Contains(pmd.service_names(),
-                                  content::mojom::kNetworkServiceName)) {
+        } else if (pmd.service_name() == content::mojom::kNetworkServiceName) {
           EmitNetworkServiceMemoryMetrics(
               pmd, ukm::UkmRecorder::GetNewSourceID(), GetUkmRecorder(),
               GetProcessUptime(now, pmd.pid()), emit_metrics_for_all_processes);
diff --git a/chrome/browser/net/chrome_report_sender.cc b/chrome/browser/net/chrome_report_sender.cc
index 2abfa83..95dee58 100644
--- a/chrome/browser/net/chrome_report_sender.cc
+++ b/chrome/browser/net/chrome_report_sender.cc
@@ -8,6 +8,7 @@
 #include "net/url_request/report_sender.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace {
 
@@ -46,7 +47,7 @@
   ~SimpleURLLoaderOwner() = default;
 
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head) {
+                         const network::mojom::URLResponseHead& response_head) {
     OnDone(&response_head, net::OK);
   }
 
@@ -54,7 +55,7 @@
     OnDone(loader_->ResponseInfo(), loader_->NetError());
   }
 
-  void OnDone(const network::ResourceResponseHead* response_head,
+  void OnDone(const network::mojom::URLResponseHead* response_head,
               int net_error) {
     if (net_error == net::OK) {
       if (success_callback_)
diff --git a/chrome/browser/password_manager/password_store_utils.cc b/chrome/browser/password_manager/password_store_utils.cc
new file mode 100644
index 0000000..a6e98a6
--- /dev/null
+++ b/chrome/browser/password_manager/password_store_utils.cc
@@ -0,0 +1,69 @@
+// 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/password_manager/password_store_utils.h"
+
+#include "chrome/browser/password_manager/account_storage/account_password_store_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_store.h"
+
+void EditSavedPasswords(
+    Profile* profile,
+    const base::span<const std::unique_ptr<autofill::PasswordForm>> old_forms,
+    const base::string16& old_username,
+    const std::string& signon_realm,
+    const base::string16& new_username,
+    const base::string16* new_password) {
+  DCHECK(!old_forms.empty());
+
+  const bool username_changed = old_username != new_username;
+
+  // In case the username changed, make sure that there exists no other
+  // credential with the same signon_realm and username.
+  if (username_changed &&
+      std::any_of(old_forms.begin(), old_forms.end(),
+                  [&](const auto& old_form) {
+                    return old_form->signon_realm == signon_realm &&
+                           old_form->username_value == new_username;
+                  })) {
+    // TODO(crbug.com/1002021): We shouldn't fail silently.
+    DLOG(ERROR) << "A credential with the same signon_realm and username "
+                   "already exists.";
+    return;
+  }
+
+  // An updated username implies a change in the primary key, thus we need to
+  // make sure to call the right API. Update every entry in the equivalence
+  // class.
+  for (const auto& old_form : old_forms) {
+    scoped_refptr<password_manager::PasswordStore> store =
+        GetPasswordStore(profile, old_form->IsUsingAccountStore());
+
+    if (!store)
+      continue;
+    autofill::PasswordForm new_form = *old_form;
+    if (new_password)
+      new_form.password_value = *new_password;
+
+    if (username_changed) {
+      new_form.username_value = new_username;
+      store->UpdateLoginWithPrimaryKey(new_form, *old_form);
+    } else {
+      store->UpdateLogin(new_form);
+    }
+  }
+}
+
+scoped_refptr<password_manager::PasswordStore> GetPasswordStore(
+    Profile* profile,
+    bool use_account_store) {
+  if (use_account_store) {
+    return AccountPasswordStoreFactory::GetForProfile(
+        profile, ServiceAccessType::EXPLICIT_ACCESS);
+  }
+  return PasswordStoreFactory::GetForProfile(
+      profile, ServiceAccessType::EXPLICIT_ACCESS);
+}
diff --git a/chrome/browser/password_manager/password_store_utils.h b/chrome/browser/password_manager/password_store_utils.h
new file mode 100644
index 0000000..2d19355
--- /dev/null
+++ b/chrome/browser/password_manager/password_store_utils.h
@@ -0,0 +1,40 @@
+// 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.
+
+// This file contains utilities related to password store.
+
+#ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_UTILS_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_UTILS_H_
+
+#include "base/containers/span.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/strings/string16.h"
+
+namespace autofill {
+struct PasswordForm;
+}
+
+namespace password_manager {
+class PasswordStore;
+}
+
+class Profile;
+
+// Changes a credential record in password store. If new_password is null it
+// isn't changed, but if it is non-null it can't be empty.
+void EditSavedPasswords(
+    Profile* profile,
+    const base::span<const std::unique_ptr<autofill::PasswordForm>> old_forms,
+    const base::string16& old_username,
+    const std::string& signon_realm,
+    const base::string16& new_username,
+    const base::string16* new_password);
+
+// Returns the password store associated with the currently active profile.
+scoped_refptr<password_manager::PasswordStore> GetPasswordStore(
+    Profile* profile,
+    bool use_account_store);
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_UTILS_H_
diff --git a/chrome/browser/permissions/permission_request.h b/chrome/browser/permissions/permission_request.h
index f996ac1..575ade8b 100644
--- a/chrome/browser/permissions/permission_request.h
+++ b/chrome/browser/permissions/permission_request.h
@@ -85,8 +85,7 @@
   virtual IconId GetIconId() const = 0;
 
 #if defined(OS_ANDROID)
-  // Returns the title of this permission as text. This is currently only used
-  // in touchless mode in Android.
+  // Returns the title of this permission as text.
   virtual base::string16 GetTitleText() const = 0;
 
   // Returns the full prompt text for this permission. This is currently only
diff --git a/chrome/browser/predictors/loading_predictor_browsertest.cc b/chrome/browser/predictors/loading_predictor_browsertest.cc
index 933584a8..0a13aea 100644
--- a/chrome/browser/predictors/loading_predictor_browsertest.cc
+++ b/chrome/browser/predictors/loading_predictor_browsertest.cc
@@ -388,8 +388,10 @@
 class LoadingPredictorBrowserTest : public InProcessBrowserTest {
  public:
   LoadingPredictorBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kLoadingOnlyLearnHighPriorityResources);
+    scoped_feature_list_.InitWithFeatures(
+        {features::kLoadingOnlyLearnHighPriorityResources,
+         features::kLoadingPreconnectToRedirectTarget},
+        {});
   }
   ~LoadingPredictorBrowserTest() override {}
 
@@ -399,6 +401,10 @@
         &LoadingPredictorBrowserTest::HandleFaviconRequest));
     embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
         &LoadingPredictorBrowserTest::HandleCacheRedirectRequest));
+
+    ASSERT_TRUE(preconnecting_test_server_.InitializeAndListen());
+    preconnecting_test_server_.AddDefaultHandlers(GetChromeTestDataDir());
+
     InProcessBrowserTest::SetUp();
   }
 
@@ -408,9 +414,20 @@
     connection_tracker_ = std::make_unique<ConnectionTracker>();
     connection_listener_ =
         std::make_unique<ConnectionListener>(connection_tracker_.get());
+    preconnecting_server_connection_tracker_ =
+        std::make_unique<ConnectionTracker>();
+    preconnecting_server_connection_listener_ =
+        std::make_unique<ConnectionListener>(
+            preconnecting_server_connection_tracker_.get());
+
     embedded_test_server()->SetConnectionListener(connection_listener_.get());
     embedded_test_server()->StartAcceptingConnections();
 
+    preconnecting_test_server_.SetConnectionListener(
+        preconnecting_server_connection_listener());
+    EXPECT_TRUE(preconnecting_test_server_.Started());
+    preconnecting_test_server_.StartAcceptingConnections();
+
     loading_predictor_ =
         LoadingPredictorFactory::GetForProfile(browser()->profile());
     ASSERT_TRUE(loading_predictor_);
@@ -453,6 +470,7 @@
     close_all_connections_loop.Run();
 
     connection_tracker()->ResetCounts();
+    preconnecting_server_connection_tracker_->ResetCounts();
   }
 
   void ResetPredictorState() {
@@ -477,6 +495,14 @@
 
   ConnectionTracker* connection_tracker() { return connection_tracker_.get(); }
 
+  ConnectionTracker* preconnecting_server_connection_tracker() const {
+    return preconnecting_server_connection_tracker_.get();
+  }
+
+  ConnectionListener* preconnecting_server_connection_listener() const {
+    return preconnecting_server_connection_listener_.get();
+  }
+
   static std::unique_ptr<net::test_server::HttpResponse> HandleFaviconRequest(
       const net::test_server::HttpRequest& request) {
     if (request.relative_url != "/favicon.ico")
@@ -512,10 +538,17 @@
     return http_response;
   }
 
+ protected:
+  // Test server that initiates preconnect. Separate server from the one being
+  // preconnected to separate preconnected connection count.
+  net::EmbeddedTestServer preconnecting_test_server_;
+
  private:
   LoadingPredictor* loading_predictor_ = nullptr;
   std::unique_ptr<ConnectionListener> connection_listener_;
   std::unique_ptr<ConnectionTracker> connection_tracker_;
+  std::unique_ptr<ConnectionListener> preconnecting_server_connection_listener_;
+  std::unique_ptr<ConnectionTracker> preconnecting_server_connection_tracker_;
   std::unique_ptr<TestPreconnectManagerObserver> preconnect_manager_observer_;
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -707,10 +740,10 @@
       "redirect.com",
       base::StringPrintf("/server-redirect?%s", redirect_url.spec().c_str()));
   url::Origin origin = url::Origin::Create(redirect_url);
-  std::vector<PreconnectRequest> requests;
+  std::vector<PreconnectRequest> expected_requests;
   for (auto* const host : kHtmlSubresourcesHosts) {
-    requests.emplace_back(embedded_test_server()->GetURL(host, "/"), 1,
-                          net::NetworkIsolationKey(origin, origin));
+    expected_requests.emplace_back(embedded_test_server()->GetURL(host, "/"), 1,
+                                   net::NetworkIsolationKey(origin, origin));
   }
 
   ui_test_utils::NavigateToURL(browser(), original_url);
@@ -720,20 +753,34 @@
   EXPECT_EQ(prediction->is_redirected, false);
   EXPECT_EQ(prediction->host, redirect_url.host());
   EXPECT_THAT(prediction->requests,
-              testing::UnorderedElementsAreArray(requests));
+              testing::UnorderedElementsAreArray(expected_requests));
   // The predictor needs minimum two redirect hits to be confident in the
-  // redirect.
+  // redirect to generate the origins for subresources. However, after the
+  // first redirect, the predictor should learn the redirect origin for
+  // preconnect.
   prediction = GetPreconnectPrediction(original_url);
-  EXPECT_FALSE(prediction);
+  ASSERT_TRUE(prediction);
+  EXPECT_FALSE(prediction->is_redirected);
+  EXPECT_EQ(prediction->host, original_url.host());
+  std::vector<PreconnectRequest> expected_requests_1;
+  expected_requests_1.emplace_back(
+      embedded_test_server()->GetURL(redirect_url.host(), "/"), 1,
+      net::NetworkIsolationKey(origin, origin));
+  EXPECT_THAT(prediction->requests,
+              testing::UnorderedElementsAreArray(expected_requests_1));
 
-  // The predictor will start predict a redirect after the second navigation.
+  // The predictor will start predict for origins of subresources (based on
+  // redirect) after the second navigation.
   ui_test_utils::NavigateToURL(browser(), original_url);
   prediction = GetPreconnectPrediction(original_url);
+  expected_requests.emplace_back(
+      embedded_test_server()->GetURL(redirect_url.host(), "/"), 1,
+      net::NetworkIsolationKey(origin, origin));
   ASSERT_TRUE(prediction);
   EXPECT_EQ(prediction->is_redirected, true);
   EXPECT_EQ(prediction->host, redirect_url.host());
   EXPECT_THAT(prediction->requests,
-              testing::UnorderedElementsAreArray(requests));
+              testing::UnorderedElementsAreArray(expected_requests));
 }
 
 // Tests that the LoadingPredictor performs preresolving/preconnecting for a
@@ -901,9 +948,6 @@
       public testing::WithParamInterface<NetworkIsolationKeyMode> {
  public:
   LoadingPredictorNetworkIsolationKeyBrowserTest() {
-    preconnecting_test_server_.AddDefaultHandlers(GetChromeTestDataDir());
-    EXPECT_TRUE(preconnecting_test_server_.Start());
-
     switch (GetParam()) {
       case NetworkIsolationKeyMode::kNone:
         break;
@@ -915,7 +959,8 @@
              // some depend on cache behavior, and it would be
              // unfortunate if splitting the cache by the key as well broke
              // them.
-             net::features::kSplitCacheByNetworkIsolationKey},
+             net::features::kSplitCacheByNetworkIsolationKey,
+             features::kLoadingPreconnectToRedirectTarget},
             // disabled_features
             {net::features::kAppendFrameOriginToNetworkIsolationKey});
         break;
@@ -924,7 +969,8 @@
             // enabled_features
             {net::features::kPartitionConnectionsByNetworkIsolationKey,
              net::features::kSplitCacheByNetworkIsolationKey,
-             net::features::kAppendFrameOriginToNetworkIsolationKey},
+             net::features::kAppendFrameOriginToNetworkIsolationKey,
+             features::kLoadingPreconnectToRedirectTarget},
             // disabled_features
             {});
         break;
@@ -974,10 +1020,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list2_;
-
-  // Test server that initiates preconnect. Separate server from the one being
-  // preconnected to separate preconnected connection count.
-  net::EmbeddedTestServer preconnecting_test_server_;
 };
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1100,10 +1142,16 @@
     connection_tracker()->WaitForAcceptedConnections(2);
     EXPECT_EQ(0u, connection_tracker()->GetReadSocketCount());
 
-    // Verify that the preconnects were made using the |redirecting_url|'s
-    // NetworkIsolationKey. To do this, make a request using the tracked
-    // server's NetworkIsolationKey, and verify it used one of the existing
-    // sockets.
+    // Verify that the redirect from |redirecting_url| to |destination_url| was
+    // learned and preconnected to.
+    if (i == 1) {
+      preconnecting_server_connection_tracker()->WaitForAcceptedConnections(1);
+    }
+
+    // Verify that the preconnects to |embedded_test_server| were made using
+    // the |redirecting_url|'s NetworkIsolationKey. To do this, make a request
+    // using the tracked server's NetworkIsolationKey, and verify it used one
+    // of the existing sockets.
     auto request = std::make_unique<network::ResourceRequest>();
     request->url = embedded_test_server()->GetURL("/echo");
     content::SimpleURLLoaderTestHelper simple_loader_helper;
diff --git a/chrome/browser/predictors/loading_test_util.cc b/chrome/browser/predictors/loading_test_util.cc
index 7c400ad..d19ed0ee 100644
--- a/chrome/browser/predictors/loading_test_util.cc
+++ b/chrome/browser/predictors/loading_test_util.cc
@@ -72,6 +72,9 @@
 }
 
 OriginData CreateOriginData(const std::string& host, uint64_t last_visit_time) {
+  // |host| should not contain the scheme.
+  EXPECT_EQ(std::string::npos, host.find("https://"));
+  EXPECT_EQ(std::string::npos, host.find("http://"));
   OriginData data;
   data.set_host(host);
   data.set_last_visit_time(last_visit_time);
diff --git a/chrome/browser/predictors/predictors_features.cc b/chrome/browser/predictors/predictors_features.cc
index 1c31975..7da737d 100644
--- a/chrome/browser/predictors/predictors_features.cc
+++ b/chrome/browser/predictors/predictors_features.cc
@@ -11,4 +11,9 @@
 const base::Feature kLoadingOnlyLearnHighPriorityResources{
     "LoadingOnlyLearnHighPriorityResources", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Modifies loading predictor so that the predictions also contain origins of
+// the redirect target of the navigation.
+const base::Feature kLoadingPreconnectToRedirectTarget{
+    "LoadingPreconnectToRedirectTarget", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
diff --git a/chrome/browser/predictors/predictors_features.h b/chrome/browser/predictors/predictors_features.h
index 5c9fd1e..9d8738e 100644
--- a/chrome/browser/predictors/predictors_features.h
+++ b/chrome/browser/predictors/predictors_features.h
@@ -14,6 +14,8 @@
 
 extern const base::Feature kLoadingOnlyLearnHighPriorityResources;
 
+extern const base::Feature kLoadingPreconnectToRedirectTarget;
+
 }  // namespace features
 
 #endif  // CHROME_BROWSER_PREDICTORS_PREDICTORS_FEATURES_H_
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc
index 2c4a0f5..451e0e7 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/predictors/loading_data_collector.h"
 #include "chrome/browser/predictors/predictor_database.h"
 #include "chrome/browser/predictors/predictor_database_factory.h"
+#include "chrome/browser/predictors/predictors_features.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/history/core/browser/history_database.h"
 #include "components/history/core/browser/history_service.h"
@@ -116,11 +117,14 @@
   // The predictor doesn't apply a minimum-number-of-hits threshold to
   // the no-redirect case because the no-redirect is a default assumption.
   const RedirectStat& redirect = data.redirect_endpoints(0);
+  bool redirect_origin_matches_entry_origin =
+      redirect.url() == entry_origin.host() &&
+      redirect.url_port() == entry_origin.port();
 
   if (ComputeRedirectConfidence(redirect) <
           kMinRedirectConfidenceToTriggerPrefetch ||
       (redirect.number_of_hits() < kMinRedirectHitsToTriggerPrefetch &&
-       redirect.url() != entry_origin.host())) {
+       !redirect_origin_matches_entry_origin)) {
     return false;
   }
 
@@ -150,6 +154,64 @@
   return true;
 }
 
+bool ResourcePrefetchPredictor::GetRedirectEndpointsForPreconnect(
+    const url::Origin& entry_origin,
+    const RedirectDataMap& redirect_data,
+    PreconnectPrediction* prediction) const {
+  if (!base::FeatureList::IsEnabled(
+          features::kLoadingPreconnectToRedirectTarget)) {
+    return false;
+  }
+  DCHECK(!prediction || prediction->requests.empty());
+
+  RedirectData data;
+  if (!redirect_data.TryGetData(entry_origin.host(), &data))
+    return false;
+
+  // The thresholds here are lower than the thresholds used above in
+  // GetRedirectOrigin() method. Here the overhead of a negative prediction is
+  // that the browser preconnects to one incorrectly predicted origin. In
+  // GetRedirectOrigin(), the overhead of wrong prediction is much higher
+  // (multiple incorrect preconnects).
+  const float kMinRedirectConfidenceToTriggerPrefetch = 0.1f;
+
+  bool at_least_one_redirect_endpoint_added = false;
+  for (const auto& redirect : data.redirect_endpoints()) {
+    if (ComputeRedirectConfidence(redirect) <
+        kMinRedirectConfidenceToTriggerPrefetch) {
+      continue;
+    }
+
+    // Assume HTTPS and port 443 by default.
+    std::string redirect_scheme =
+        redirect.url_scheme().empty() ? "https" : redirect.url_scheme();
+    int redirect_port = redirect.has_url_port() ? redirect.url_port() : 443;
+
+    const url::Origin redirect_origin = url::Origin::CreateFromNormalizedTuple(
+        redirect_scheme, redirect.url(), redirect_port);
+
+    if (redirect_origin == entry_origin) {
+      continue;
+    }
+
+    // Add the endpoint to which the predictor has seen redirects to.
+    // Set network isolation key same as the origin of the redirect target.
+    if (prediction) {
+      prediction->requests.emplace_back(
+          redirect_origin.GetURL(), 1 /* num_scokets */,
+          net::NetworkIsolationKey(redirect_origin, redirect_origin));
+    }
+    at_least_one_redirect_endpoint_added = true;
+  }
+
+  if (prediction && prediction->host.empty() &&
+      at_least_one_redirect_endpoint_added) {
+    prediction->host = entry_origin.host();
+  }
+
+  return at_least_one_redirect_endpoint_added;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // ResourcePrefetchPredictor.
 
@@ -242,21 +304,26 @@
 
   url::Origin url_origin = url::Origin::Create(url);
   url::Origin redirect_origin;
+  bool has_any_prediction = GetRedirectEndpointsForPreconnect(
+      url_origin, *host_redirect_data_, prediction);
   if (!GetRedirectOrigin(url_origin, *host_redirect_data_, &redirect_origin)) {
-    return false;
+    // GetRedirectOrigin() may return false if it's not confident about the
+    // redirect target or the navigation target. Calling
+    // GetRedirectEndpointsForPreconnect() ensures we add all possible redirect
+    // targets to the preconnect prediction.
+    return has_any_prediction;
   }
 
   OriginData data;
-  if (!origin_data_->TryGetData(redirect_origin.host(), &data))
-    return false;
+  if (!origin_data_->TryGetData(redirect_origin.host(), &data)) {
+    return has_any_prediction;
+  }
 
   if (prediction) {
     prediction->host = redirect_origin.host();
     prediction->is_redirected = (redirect_origin != url_origin);
   }
 
-  bool has_any_prediction = false;
-
   net::NetworkIsolationKey network_isolation_key(redirect_origin,
                                                  redirect_origin);
 
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.h b/chrome/browser/predictors/resource_prefetch_predictor.h
index 86ae7294..d05c0246 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor.h
+++ b/chrome/browser/predictors/resource_prefetch_predictor.h
@@ -192,8 +192,11 @@
                            PopulatePrefetcherRequest);
   FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetRedirectOrigin);
   FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest, GetPrefetchData);
+  FRIEND_TEST_ALL_PREFIXES(
+      ResourcePrefetchPredictorPreconnectToRedirectTargetTest,
+      TestPredictPreconnectOrigins);
   FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest,
-                           TestPredictPreconnectOrigins);
+                           TestPredictPreconnectOrigins_RedirectsToNewOrigin);
   FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest,
                            TestPrecisionRecallHistograms);
   FRIEND_TEST_ALL_PREFIXES(ResourcePrefetchPredictorTest,
@@ -217,6 +220,13 @@
                                 const RedirectDataMap& redirect_data,
                                 url::Origin* redirect_origin);
 
+  // Returns true if a redirect endpoint is available. Appends the redirect
+  // domains to |prediction->requests|. Sets |prediction->host| if it's empty.
+  bool GetRedirectEndpointsForPreconnect(
+      const url::Origin& entry_origin,
+      const RedirectDataMap& redirect_data,
+      PreconnectPrediction* prediction) const;
+
   // Callback for the task to read the predictor database. Takes ownership of
   // all arguments.
   void CreateCaches(std::unique_ptr<RedirectDataMap> host_redirect_data,
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
index ca160d1..93a23d5 100644
--- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
+++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -13,11 +13,13 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/time.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_test_util.h"
+#include "chrome/browser/predictors/predictors_features.h"
 #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/history/core/browser/history_service.h"
@@ -716,10 +718,42 @@
   EXPECT_EQ(no_scheme_redirect_origin, redirect_origin);
 }
 
-TEST_F(ResourcePrefetchPredictorTest, TestPredictPreconnectOrigins) {
+class ResourcePrefetchPredictorPreconnectToRedirectTargetTest
+    : public ResourcePrefetchPredictorTest,
+      public ::testing::WithParamInterface<bool> {};
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    ResourcePrefetchPredictorPreconnectToRedirectTargetTest,
+    ::testing::Values(false, true));
+
+// google.com redirects to https://www.google.com and stores origin data for
+// https://www.google.com. Verifies that predictions for google.com returns the
+// origin data stored for https://www.google.com.
+TEST_P(ResourcePrefetchPredictorPreconnectToRedirectTargetTest,
+       TestPredictPreconnectOrigins) {
+  const bool enable_preconnect_to_redirect_target_experiment = GetParam();
+
+  base::test::ScopedFeatureList scoped_feature_list;
+
+  if (enable_preconnect_to_redirect_target_experiment) {
+    scoped_feature_list.InitWithFeatures(
+        {features::kLoadingOnlyLearnHighPriorityResources,
+         features::kLoadingPreconnectToRedirectTarget},
+        {});
+  } else {
+    scoped_feature_list.InitWithFeatures(
+        {features::kLoadingOnlyLearnHighPriorityResources},
+        {features::kLoadingPreconnectToRedirectTarget});
+  }
+
   const GURL main_frame_url("http://google.com/?query=cats");
   const url::Origin origin = url::Origin::Create(main_frame_url);
   const net::NetworkIsolationKey network_isolation_key(origin, origin);
+  const url::Origin www_google_origin =
+      url::Origin::Create(GURL("https://www.google.com"));
+  const net::NetworkIsolationKey www_google_network_isolation_key(
+      www_google_origin, www_google_origin);
   auto prediction = std::make_unique<PreconnectPrediction>();
   // No prefetch data.
   EXPECT_FALSE(predictor_->IsUrlPreconnectable(main_frame_url));
@@ -757,12 +791,117 @@
                          GURL("https://www.google.com"), 10, 0, 0);
   predictor_->host_redirect_data_->UpdateData(redirect.primary_key(), redirect);
 
-  // Prediction failed: no data associated with the redirect endpoint.
+  // Prediction should succeed: The redirect endpoint should be associated
+  // with |main_frame_url|.
   prediction = std::make_unique<PreconnectPrediction>();
+  EXPECT_EQ(enable_preconnect_to_redirect_target_experiment,
+            predictor_->IsUrlPreconnectable(main_frame_url));
+  EXPECT_EQ(
+      enable_preconnect_to_redirect_target_experiment,
+      predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
+  auto expected_prediction_1 = CreatePreconnectPrediction(
+      "google.com", 0,
+      {{GURL("https://www.google.com/"), 1, www_google_network_isolation_key}});
+  if (enable_preconnect_to_redirect_target_experiment) {
+    EXPECT_EQ(expected_prediction_1, *prediction);
+  } else {
+    EXPECT_TRUE(prediction->requests.empty());
+  }
+
+  // Add a resource associated with the redirect endpoint
+  // (https://www.google.com).
+  OriginData www_google = CreateOriginData("www.google.com", 4);
+  InitializeOriginStat(www_google.add_origins(), gen_origin(4), 10, 0, 0, 1.0,
+                       true,
+                       true);  // High confidence - preconnect.
+  predictor_->origin_data_->UpdateData(www_google.host(), www_google);
+
+  prediction = std::make_unique<PreconnectPrediction>();
+  EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url));
+  EXPECT_TRUE(
+      predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
+
+  auto expected_prediction_2 = CreatePreconnectPrediction(
+      "www.google.com", true,
+      {{GURL(gen_origin(4)), 1, www_google_network_isolation_key}});
+  if (enable_preconnect_to_redirect_target_experiment) {
+    // Getting the prediction for google.com should include the redirect
+    // target as well. The redirect target should be present in the front.
+    expected_prediction_2.requests.emplace(
+        expected_prediction_2.requests.begin(), GURL("https://www.google.com"),
+        1, www_google_network_isolation_key);
+  }
+  EXPECT_EQ(expected_prediction_2, *prediction);
+}
+
+// Redirects from google.com to google-redirected-to.com. Origin data is added
+// for www.google.com.
+TEST_F(ResourcePrefetchPredictorTest,
+       TestPredictPreconnectOrigins_RedirectsToNewOrigin) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {features::kLoadingOnlyLearnHighPriorityResources,
+       features::kLoadingPreconnectToRedirectTarget},
+      {});
+
+  const GURL main_frame_url("http://google.com/?query=cats");
+  const url::Origin origin = url::Origin::Create(main_frame_url);
+  const net::NetworkIsolationKey network_isolation_key(origin, origin);
+  auto prediction = std::make_unique<PreconnectPrediction>();
+  // No prefetch data.
   EXPECT_FALSE(predictor_->IsUrlPreconnectable(main_frame_url));
   EXPECT_FALSE(
       predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
 
+  const char* cdn_origin = "https://cdn%d.google.com";
+  auto gen_origin = [cdn_origin](int n) {
+    return base::StringPrintf(cdn_origin, n);
+  };
+
+  // Add origins associated with the main frame host.
+  OriginData google = CreateOriginData("google.com");
+  InitializeOriginStat(google.add_origins(), gen_origin(1), 10, 0, 0, 1.0, true,
+                       true);  // High confidence - preconnect.
+  InitializeOriginStat(google.add_origins(), gen_origin(2), 10, 5, 0, 2.0, true,
+                       true);  // Medium confidence - preresolve.
+  InitializeOriginStat(google.add_origins(), gen_origin(3), 1, 10, 10, 3.0,
+                       true, true);  // Low confidence - ignore.
+  predictor_->origin_data_->UpdateData(google.host(), google);
+
+  prediction = std::make_unique<PreconnectPrediction>();
+  EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url));
+  EXPECT_TRUE(
+      predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
+  EXPECT_EQ(*prediction,
+            CreatePreconnectPrediction(
+                "google.com", false,
+                {{GURL(gen_origin(1)), 1, network_isolation_key},
+                 {GURL(gen_origin(2)), 0, network_isolation_key}}));
+
+  // Add a redirect.
+  RedirectData redirect = CreateRedirectData("google.com", 3);
+  InitializeRedirectStat(redirect.add_redirect_endpoints(),
+                         GURL("https://www.google-redirected-to.com"), 10, 0,
+                         0);
+  predictor_->host_redirect_data_->UpdateData(redirect.primary_key(), redirect);
+
+  // Prediction should succeed: The redirect endpoint should be associated with
+  // |main_frame_url|.
+  prediction = std::make_unique<PreconnectPrediction>();
+  EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url));
+  EXPECT_TRUE(
+      predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
+
+  const net::NetworkIsolationKey www_google_redirected_to_network_isolation_key(
+      url::Origin::Create(GURL("https://www.google-redirected-to.com")),
+      url::Origin::Create(GURL("https://www.google-redirected-to.com")));
+
+  const auto expected_prediction = CreatePreconnectPrediction(
+      "google.com", 0,
+      {{GURL("https://www.google-redirected-to.com/"), 1,
+        www_google_redirected_to_network_isolation_key}});
+  EXPECT_EQ(expected_prediction, *prediction);
+
   // Add a resource associated with the redirect endpoint.
   OriginData www_google = CreateOriginData("www.google.com", 4);
   InitializeOriginStat(www_google.add_origins(), gen_origin(4), 10, 0, 0, 1.0,
@@ -770,18 +909,28 @@
                        true);  // High confidence - preconnect.
   predictor_->origin_data_->UpdateData(www_google.host(), www_google);
 
-  const url::Origin www_google_origin =
-      url::Origin::Create(GURL("https://www.google.com"));
-  const net::NetworkIsolationKey www_google_network_isolation_key(
-      www_google_origin, www_google_origin);
+  // Add a resource associated with the redirect endpoint.
+  OriginData www_google_redirected_to =
+      CreateOriginData("www.google-redirected-to.com", 4);
+  InitializeOriginStat(www_google_redirected_to.add_origins(), gen_origin(4),
+                       10, 0, 0, 1.0, true,
+                       true);  // High confidence - preconnect.
+  predictor_->origin_data_->UpdateData(www_google_redirected_to.host(),
+                                       www_google_redirected_to);
+
   prediction = std::make_unique<PreconnectPrediction>();
   EXPECT_TRUE(predictor_->IsUrlPreconnectable(main_frame_url));
   EXPECT_TRUE(
       predictor_->PredictPreconnectOrigins(main_frame_url, prediction.get()));
-  EXPECT_EQ(*prediction,
-            CreatePreconnectPrediction(
-                "www.google.com", true,
-                {{GURL(gen_origin(4)), 1, www_google_network_isolation_key}}));
+  const auto expected_prediction_redirected_to = CreatePreconnectPrediction(
+      "www.google-redirected-to.com", true,
+      {
+          {GURL("https://www.google-redirected-to.com"), 1,
+           www_google_redirected_to_network_isolation_key},
+          {GURL(gen_origin(4)), 1,
+           www_google_redirected_to_network_isolation_key},
+      });
+  EXPECT_EQ(expected_prediction_redirected_to, *prediction);
 }
 
 }  // namespace predictors
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc
index 35e5c95..b47ea7c 100644
--- a/chrome/browser/previews/previews_lite_page_browsertest.cc
+++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -139,8 +139,6 @@
 
   ~BasePreviewsLitePageServerBrowserTest() override {}
 
-  virtual bool UseURLLoaderImplementation() const = 0;
-
   virtual bool UseOptimizationGuideKeyedServiceImplementation() const = 0;
 
   enum PreviewsServerAction {
@@ -308,6 +306,7 @@
 
     scoped_feature_list_.InitWithFeatures(
         {previews::features::kPreviews,
+         previews::features::kHTTPSServerPreviewsUsingURLLoader,
          optimization_guide::features::kOptimizationHints,
          previews::features::kResourceLoadingHints,
          data_reduction_proxy::features::
@@ -315,10 +314,6 @@
          network::features::kReporting},
         {network::features::kNetworkErrorLogging});
 
-    if (UseURLLoaderImplementation()) {
-      url_loader_feature_list_.InitWithFeatures(
-          {previews::features::kHTTPSServerPreviewsUsingURLLoader}, {});
-    }
     if (UseOptimizationGuideKeyedServiceImplementation()) {
       opt_guide_keyed_service_feature_list_.InitWithFeatures(
           {optimization_guide::features::kOptimizationGuideKeyedService}, {});
@@ -410,30 +405,6 @@
     return GetWebContents()->GetController().GetVisibleEntry()->GetURL();
   }
 
-  void VerifyInfoStatus(base::HistogramTester* histogram_tester,
-                        previews::ServerLitePageStatus status) {
-    PreviewsUITabHelper* ui_tab_helper =
-        PreviewsUITabHelper::FromWebContents(GetWebContents());
-    previews::PreviewsUserData* previews_data =
-        ui_tab_helper->previews_user_data();
-    if (!UseURLLoaderImplementation()) {
-      EXPECT_TRUE(previews_data->server_lite_page_info());
-      EXPECT_EQ(previews_data->server_lite_page_info()->status, status);
-    }
-    // This UMA is not recorded for an unknown or control group status
-    if (status == previews::ServerLitePageStatus::kUnknown ||
-        status == previews::ServerLitePageStatus::kControl) {
-      return;
-    }
-
-    if (!UseURLLoaderImplementation()) {
-      histogram_tester->ExpectTotalCount(
-          "Previews.ServerLitePage.Penalty." +
-              previews::ServerLitePageStatusToString(status),
-          1);
-    }
-  }
-
   void VerifyPreviewLoaded() const {
     // The Virtual URL is set in a WebContentsObserver::OnFinishNavigation.
     // Since |ui_test_utils::NavigationToURL| uses the same signal to stop
@@ -461,18 +432,6 @@
     content::NavigationEntry* entry =
         GetWebContents()->GetController().GetVisibleEntry();
 
-    if (!UseURLLoaderImplementation()) {
-      // server_lite_page_info does not exist on forward/back navigations.
-      if (!(entry->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK)) {
-        EXPECT_TRUE(previews_data->server_lite_page_info());
-        EXPECT_NE(
-            previews_data->server_lite_page_info()->original_navigation_start,
-            base::TimeTicks());
-        EXPECT_NE(previews_data->server_lite_page_info()->page_id, 0U);
-        EXPECT_NE(previews_data->server_lite_page_info()->drp_session_key, "");
-      }
-    }
-
     EXPECT_EQ(content::PAGE_TYPE_NORMAL, entry->GetPageType());
     const GURL virtual_url = entry->GetVirtualURL();
 
@@ -965,28 +924,23 @@
   base::OnceClosure waiting_for_report_closure_;
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 class PreviewsLitePageServerBrowserTest
     : public BasePreviewsLitePageServerBrowserTest,
-      public testing::WithParamInterface<std::tuple<bool, bool>> {
+      public testing::WithParamInterface<bool> {
  public:
-  bool UseURLLoaderImplementation() const override {
-    return std::get<0>(GetParam());
-  }
   bool UseOptimizationGuideKeyedServiceImplementation() const override {
-    return std::get<1>(GetParam());
+    return GetParam();
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageServerBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 // Previews InfoBar (which these tests trigger) does not work on Mac.
 // See https://crbug.com/782322 for detail.
@@ -1019,8 +973,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess));
     VerifyPreviewLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kSuccess);
   }
 
   {
@@ -1168,17 +1120,6 @@
 
     VerifyPreviewNotLoaded();
     ClearDeciderState();
-
-    if (!UseURLLoaderImplementation()) {
-      // It takes a few redirects to reach the end case. Just make sure at least
-      // one sample has been recorded in the correct bucket.
-      histogram_tester.ExpectBucketCount(
-          "Previews.ServerLitePage.IneligibleReasons",
-          static_cast<int>(
-              PreviewsLitePageNavigationThrottle::IneligibleReason::
-                  kExceededMaxNavigationRestarts),
-          1);
-    }
   }
 
   {
@@ -1203,10 +1144,6 @@
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageServerBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(LitePagePreviewsOriginProbe_Success)) {
-  // This behavior is not implemented for the nav throttle.
-  if (!UseURLLoaderImplementation())
-    return;
-
   set_origin_probe_success(true);
 
   ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess));
@@ -1217,10 +1154,6 @@
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageServerBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(LitePagePreviewsOriginProbe_Fail)) {
-  // This behavior is not implemented for the nav throttle.
-  if (!UseURLLoaderImplementation())
-    return;
-
   set_origin_probe_success(false);
 
   ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess));
@@ -1299,7 +1232,6 @@
   base::HistogramTester histogram_tester;
   ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess));
   VerifyPreviewLoaded();
-  VerifyInfoStatus(&histogram_tester, previews::ServerLitePageStatus::kSuccess);
 
   PreviewsServiceFactory::GetForProfile(
       Profile::FromBrowserContext(browser()
@@ -1322,8 +1254,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), http_to_https_redirect_url());
     VerifyPreviewLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kSuccess);
   }
 
   {
@@ -1331,8 +1261,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), https_to_https_redirect_url());
     VerifyPreviewLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kSuccess);
   }
 
   {
@@ -1342,8 +1270,6 @@
     ui_test_utils::NavigateToURL(browser(),
                                  HttpsLitePageURL(kRedirectNonPreview));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kRedirect);
     ClearDeciderState();
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1356,8 +1282,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kRedirectPreview));
     VerifyPreviewLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kSuccess);
     ClearDeciderState();
 
     histogram_tester.ExpectBucketCount(
@@ -1377,8 +1301,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kBypass));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kBypass);
     ClearDeciderState();
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1396,8 +1318,6 @@
     ui_test_utils::NavigateToURL(
         browser(), HttpsLitePageURL(kBypassAndBlacklistOriginHost));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kBypass);
 
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1424,8 +1344,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kAuthFailure));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kFailure);
     ClearDeciderState();
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1437,8 +1355,6 @@
     base::HistogramTester histogram_tester;
     ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kLoadshed));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kFailure);
     ClearDeciderState();
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1611,11 +1527,7 @@
   {
     SCOPED_TRACE("Navigate back");
     GetWebContents()->GetController().GoBack();
-    if (UseURLLoaderImplementation()) {
-      VerifyPreviewNotLoaded();
-    } else {
-      VerifyPreviewLoaded();
-    }
+    VerifyPreviewNotLoaded();
   }
 
   {
@@ -1676,13 +1588,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageServerTimeoutBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(PreviewsLitePageServerTimeoutBrowserTest,
                        DISABLE_ON_WIN_MAC_CHROMESOS(LitePagePreviewsTimeout)) {
@@ -1693,8 +1604,6 @@
     ui_test_utils::NavigateToURL(browser(),
                                  HttpsLitePageURL(kSuccess, nullptr, -1));
     VerifyPreviewNotLoaded();
-    VerifyInfoStatus(&histogram_tester,
-                     previews::ServerLitePageStatus::kFailure);
     ClearDeciderState();
     histogram_tester.ExpectBucketCount(
         "Previews.ServerLitePage.ServerResponse",
@@ -1725,13 +1634,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageServerBadServerBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageServerBadServerBrowserTest,
@@ -1776,13 +1684,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageServerDataSaverBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageServerDataSaverBrowserTest,
@@ -1814,13 +1721,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageServerNoDataSaverHeaderBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageServerNoDataSaverHeaderBrowserTest,
@@ -1856,13 +1762,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageNotificationDSEnabledBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageNotificationDSEnabledBrowserTest,
@@ -1918,13 +1823,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageDSDisabledBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageDSDisabledBrowserTest,
@@ -1952,13 +1856,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageControlBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageControlBrowserTest,
@@ -1966,7 +1869,6 @@
   base::HistogramTester histogram_tester;
   ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(kSuccess));
   VerifyPreviewNotLoaded();
-  VerifyInfoStatus(&histogram_tester, previews::ServerLitePageStatus::kControl);
   ClearDeciderState();
 }
 
@@ -2010,8 +1912,6 @@
     }
   }
 
-  bool UseURLLoaderImplementation() const override { return true; }
-
   bool UseOptimizationGuideKeyedServiceImplementation() const override {
     return false;
   }
@@ -2091,13 +1991,12 @@
   }
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     PreviewsLitePageAndPageHintsBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 // Regression test for crbug.com/954554.
 IN_PROC_BROWSER_TEST_P(
@@ -2169,10 +2068,6 @@
 
   ~CoinFlipHoldbackExperimentBrowserTest() override = default;
 
-  // Doesn't work with the NavThrottle impl since the coin flip event is
-  // recorded multiple times.
-  bool UseURLLoaderImplementation() const override { return true; }
-
   void SetUp() override {
     PreviewsLitePageAndPageHintsBrowserTest::SetUp();
     ukm_feature_list_.InitAndEnableFeature(ukm::kUkmFeature);
@@ -2320,13 +2215,12 @@
   base::test::ScopedFeatureList ukm_feature_list_;
 };
 
-// First param is true if testing using the URLLoader Interceptor implementation
-// and the second param is true if testing using the
-// OptimizationGuideKeyedService implementation.
+// Param is true if testing using the OptimizationGuideKeyedService
+// implementation.
 INSTANTIATE_TEST_SUITE_P(
     /* no prefix */,
     CoinFlipHoldbackExperimentBrowserTest,
-    testing::Combine(testing::Bool(), testing::Bool()));
+    testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(CoinFlipHoldbackExperimentBrowserTest,
                        DISABLE_ON_WIN_MAC_CHROMESOS(NoPreviews_NoCoinFlip)) {
diff --git a/chrome/browser/previews/previews_lite_page_decider.cc b/chrome/browser/previews/previews_lite_page_decider.cc
index b4a62a1..1be6316 100644
--- a/chrome/browser/previews/previews_lite_page_decider.cc
+++ b/chrome/browser/previews/previews_lite_page_decider.cc
@@ -235,49 +235,6 @@
 }
 
 // static
-std::unique_ptr<content::NavigationThrottle>
-PreviewsLitePageDecider::MaybeCreateThrottleFor(
-    content::NavigationHandle* handle) {
-  DCHECK(handle);
-  DCHECK(handle->GetWebContents());
-  DCHECK(handle->GetWebContents()->GetBrowserContext());
-
-  if (!handle->IsInMainFrame())
-    return nullptr;
-
-  if (base::FeatureList::IsEnabled(
-          previews::features::kHTTPSServerPreviewsUsingURLLoader)) {
-    return nullptr;
-  }
-
-  content::BrowserContext* browser_context =
-      handle->GetWebContents()->GetBrowserContext();
-
-  PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile(
-      Profile::FromBrowserContext(browser_context));
-  if (!previews_service)
-    return nullptr;
-  DCHECK(!browser_context->IsOffTheRecord());
-
-  PreviewsLitePageDecider* decider =
-      previews_service->previews_lite_page_decider();
-  DCHECK(decider);
-
-  bool drp_enabled = decider->drp_settings_->IsDataReductionProxyEnabled();
-  bool preview_enabled = previews::params::ArePreviewsAllowed() &&
-                         previews::params::IsLitePageServerPreviewsEnabled();
-
-  // Always create a navigation throttle if the feature is enabled. The throttle
-  // itself will check the PreviewsState bit for triggering.
-  if (drp_enabled && preview_enabled) {
-    return std::make_unique<PreviewsLitePageNavigationThrottle>(handle,
-                                                                decider);
-  }
-
-  return nullptr;
-}
-
-// static
 uint64_t PreviewsLitePageDecider::GeneratePageIdForWebContents(
     content::WebContents* web_contents) {
   return PreviewsLitePageDecider::GeneratePageIdForProfile(
@@ -495,7 +452,7 @@
 
 bool PreviewsLitePageDecider::IsResponseSuccess(
     net::Error net_error,
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Any HTTP response is fine, so long as we got it.
diff --git a/chrome/browser/previews/previews_lite_page_decider.h b/chrome/browser/previews/previews_lite_page_decider.h
index 65e31c0..803cdf08 100644
--- a/chrome/browser/previews/previews_lite_page_decider.h
+++ b/chrome/browser/previews/previews_lite_page_decider.h
@@ -27,8 +27,6 @@
 
 namespace content {
 class BrowserContext;
-class NavigationHandle;
-class NavigationThrottle;
 class WebContents;
 
 }  // namespace content
@@ -52,12 +50,6 @@
   // Registers the prefs used in this class.
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  // Checks if the feature is enabled and if so, returns a
-  // |PreviewsLitePageNavigationThrottle| that handles the rest of the decision
-  // making.
-  static std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottleFor(
-      content::NavigationHandle* handle);
-
   // Helpers to generate page ID.
   static uint64_t GeneratePageIdForWebContents(
       content::WebContents* web_contents);
@@ -112,7 +104,7 @@
   // AvailabilityProber::Delegate:
   bool ShouldSendNextProbe() override;
   bool IsResponseSuccess(net::Error net_error,
-                         const network::ResourceResponseHead* head,
+                         const network::mojom::URLResponseHead* head,
                          std::unique_ptr<std::string> body) override;
 
   // The time after which it is ok to send the server more preview requests.
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
index b87ccad..610e80a 100644
--- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
+++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
@@ -6,247 +6,33 @@
 
 #include <stdint.h>
 #include <string>
-#include <unordered_set>
-#include <vector>
 
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
-#include "base/rand_util.h"
 #include "base/strings/safe_sprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
 #include "base/time/time.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/previews/previews_lite_page_decider.h"
-#include "chrome/browser/previews/previews_service.h"
-#include "chrome/browser/previews/previews_service_factory.h"
 #include "chrome/browser/previews/previews_ui_tab_helper.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "components/base32/base32.h"
-#include "components/content_settings/core/browser/cookie_settings.h"
-#include "components/content_settings/core/common/cookie_settings_base.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/previews/core/previews_experiments.h"
 #include "components/previews/core/previews_lite_page_redirect.h"
-#include "components/variations/variations_associated_data.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/page_navigator.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-#include "content/public/common/referrer.h"
 #include "crypto/sha2.h"
 #include "net/base/escape.h"
-#include "net/base/ip_address.h"
 #include "net/base/url_util.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
-#include "services/network/public/cpp/network_quality_tracker.h"
-#include "ui/base/window_open_disposition.h"
-#include "url/gurl.h"
-
-namespace {
-
-constexpr char kChromeProxyHeader[] = "chrome-proxy";
-
-const base::TimeDelta kBlacklistDuration = base::TimeDelta::FromDays(30);
-
-content::OpenURLParams MakeOpenURLParams(content::NavigationHandle* handle,
-                                         GURL url,
-                                         const std::string& headers) {
-  content::OpenURLParams url_params(
-      url, content::Referrer(handle->GetReferrer()),
-      WindowOpenDisposition::CURRENT_TAB, handle->GetPageTransition(),
-      handle->IsRendererInitiated());
-  url_params.initiator_origin = handle->GetInitiatorOrigin();
-  // crbug.com/916892: When a client redirect occurs on a site before the page
-  // has finished loading, it is not considered a new NavigationEntry and so
-  // clicking "Back" on the redirected page returns to the previous loaded page.
-  // However, all browser-initiated navigations are assumed to be new
-  // NavigationEntries (see NavigationControllerImpl::NavigateWithoutEntry). So
-  // if the canceled navigation was a client redirect, and there is a previous
-  // entry to go to, set |should_replace_current_entry|.
-  url_params.should_replace_current_entry =
-      (handle->GetPageTransition() & ui::PAGE_TRANSITION_CLIENT_REDIRECT) &&
-      handle->IsRendererInitiated() &&
-      handle->GetWebContents()->GetController().GetLastCommittedEntry();
-  url_params.extra_headers = headers;
-  url_params.redirect_chain = handle->GetRedirectChain();
-  url_params.frame_tree_node_id = handle->GetFrameTreeNodeId();
-  url_params.user_gesture = handle->HasUserGesture();
-  url_params.started_from_context_menu = handle->WasStartedFromContextMenu();
-  url_params.reload_type = handle->GetReloadType();
-  return url_params;
-}
-
-}  // namespace
-
-class PreviewsWebContentsLifetimeHelper
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<PreviewsWebContentsLifetimeHelper> {
- public:
-  explicit PreviewsWebContentsLifetimeHelper(content::WebContents* web_contents)
-      : content::WebContentsObserver(web_contents),
-        web_contents_(web_contents) {}
-
-  // Keep track of all ongoing navigations in this WebContents.
-  void DidStartNavigation(content::NavigationHandle* handle) override {
-    DCHECK(handle);
-    if (!handle->IsInMainFrame())
-      return;
-
-    navigations_.insert(handle);
-
-    // Check if the starting navigation was reported as being caused by a
-    // restart. Note: This could be a navigation to the litepages server, or to
-    // the original URL.
-    if (restarted_navigation_url_ == handle->GetURL()) {
-      if (!info_) {
-        // Create a new info_ if needed. This will use the previous page_id,
-        // which is desired.
-        PreviewsService* previews_service =
-            PreviewsServiceFactory::GetForProfile(Profile::FromBrowserContext(
-                web_contents()->GetBrowserContext()));
-        PreviewsLitePageNavigationThrottleManager* manager =
-            previews_service->previews_lite_page_decider();
-
-        info_ =
-            PreviewsLitePageNavigationThrottle::GetOrCreateServerLitePageInfo(
-                handle, manager)
-                ->Clone();
-      }
-
-      // Create a new PreviewsUserData if needed.
-      PreviewsUITabHelper* ui_tab_helper =
-          PreviewsUITabHelper::FromWebContents(web_contents());
-      previews::PreviewsUserData* previews_data =
-          ui_tab_helper->CreatePreviewsUserDataForNavigationHandle(
-              handle, info_->page_id);
-      previews_data->set_server_lite_page_info(std::move(info_));
-
-      // Reset member state.
-      restarted_navigation_url_ = GURL();
-    }
-  }
-
-  // Keep track of all ongoing navigations in this WebContents.
-  void DidFinishNavigation(content::NavigationHandle* handle) override {
-    DCHECK(handle);
-    if (!handle->IsInMainFrame())
-      return;
-
-    if (navigations_.find(handle) != navigations_.end()) {
-      navigations_.erase(handle);
-    }
-
-    // If this navigation is committing here, it has passed the Navigation
-    // Throttle checks. Record time penalty UMA about the final state of the
-    // navigation.
-    PreviewsUITabHelper* ui_tab_helper =
-        PreviewsUITabHelper::FromWebContents(web_contents());
-    previews::PreviewsUserData* previews_data =
-        ui_tab_helper->GetPreviewsUserData(handle);
-    if (!handle->HasCommitted() || !previews_data ||
-        !previews_data->server_lite_page_info()) {
-      return;
-    }
-
-    previews::PreviewsUserData::ServerLitePageInfo* info =
-        previews_data->server_lite_page_info();
-
-    // Don't record this UMA for an unknown or control group status.
-    if (info->status == previews::ServerLitePageStatus::kUnknown ||
-        info->status == previews::ServerLitePageStatus::kControl) {
-      return;
-    }
-
-    base::TimeDelta penalty =
-        handle->NavigationStart() - info->original_navigation_start;
-
-    base::LinearHistogram::FactoryTimeGet(
-        base::StringPrintf(
-            "Previews.ServerLitePage.Penalty.%s",
-            previews::ServerLitePageStatusToString(info->status).c_str()),
-        base::TimeDelta(), base::TimeDelta::FromMinutes(3), 50,
-        base::HistogramBase::kUmaTargetedHistogramFlag)
-        ->Add(penalty.InMilliseconds());
-  }
-
-  // This method should be called after some delay to cancel an ongoing previews
-  // navigation. This method checks if the ongoing navigation is for the given
-  // |url|, if so the |fallback_callback| is run.
-  void CheckForHungNavigation(const GURL& url,
-                              base::OnceClosure fallback_callback) {
-    DCHECK_GE(2u, navigations_.size());
-    if (navigations_.empty())
-      return;
-
-    content::NavigationHandle* handle = *navigations_.begin();
-    if (handle->GetURL() != url)
-      return;
-
-    UMA_HISTOGRAM_ENUMERATION(
-        "Previews.ServerLitePage.ServerResponse",
-        PreviewsLitePageNavigationThrottle::ServerResponse::kTimeout);
-
-    std::move(fallback_callback).Run();
-  }
-
-  base::WeakPtr<PreviewsWebContentsLifetimeHelper> GetWeakPtr() {
-    return weak_factory_.GetWeakPtr();
-  }
-
-  void PostNewNavigation(
-      const content::OpenURLParams& url_params,
-      std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo> info) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    DCHECK(url_params.url.is_valid());
-    DCHECK(url_params.url.SchemeIs(url::kHttpsScheme));
-    // Setting these members should always happen before |OpenURL| which can be
-    // synchronous.
-    restarted_navigation_url_ = url_params.url;
-    info_ = std::move(info);
-    if (info_)
-      info_->restart_count++;
-
-    web_contents_->OpenURL(url_params);
-  }
-
- private:
-  friend class content::WebContentsUserData<PreviewsWebContentsLifetimeHelper>;
-  // The url to monitor for. When it is seen, |info_| will be attached to that
-  // navigation.
-  GURL restarted_navigation_url_;
-
-  // The ServerLitePageInfo to attach to the next navigation that matches
-  // |restarted_navigation_url_|.
-  std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo> info_;
-
-  content::WebContents* web_contents_;
-  std::unordered_set<content::NavigationHandle*> navigations_;
-  base::WeakPtrFactory<PreviewsWebContentsLifetimeHelper> weak_factory_{this};
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-};
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(PreviewsWebContentsLifetimeHelper)
 
 bool HandlePreviewsLitePageURLRewrite(
     GURL* url,
@@ -279,19 +65,6 @@
   return false;
 }
 
-PreviewsLitePageNavigationThrottle::PreviewsLitePageNavigationThrottle(
-    content::NavigationHandle* handle,
-    PreviewsLitePageNavigationThrottleManager* manager)
-    : content::NavigationThrottle(handle), manager_(manager) {
-  DCHECK(manager_);
-  DCHECK(handle);
-  DCHECK(handle->GetWebContents());
-  DCHECK(handle->GetWebContents()->GetBrowserContext());
-}
-
-PreviewsLitePageNavigationThrottle::~PreviewsLitePageNavigationThrottle() =
-    default;
-
 // static
 void PreviewsLitePageNavigationThrottle::LogIneligibleReason(
     IneligibleReason reason) {
@@ -300,37 +73,6 @@
                             reason);
 }
 
-bool PreviewsLitePageNavigationThrottle::IsEligibleForPreview() const {
-  DCHECK(navigation_handle()->IsInMainFrame());
-
-  if (data_reduction_proxy::HasURLRedirectCycle(
-          navigation_handle()->GetRedirectChain()) ||
-      (GetServerLitePageInfo() &&
-       GetServerLitePageInfo()->restart_count >=
-           previews::params::LitePageRedirectPreviewMaxNavigationRestarts())) {
-    LogIneligibleReason(IneligibleReason::kExceededMaxNavigationRestarts);
-    return false;
-  }
-
-  PreviewsUITabHelper* tab_helper = PreviewsUITabHelper::FromWebContents(
-      navigation_handle()->GetWebContents());
-  previews::PreviewsUserData* previews_data =
-      tab_helper ? (tab_helper->GetPreviewsUserData(navigation_handle()))
-                 : nullptr;
-
-  if (!previews_data || !(previews_data->AllowedPreviewsState() &
-                          content::LITE_PAGE_REDIRECT_ON)) {
-    return false;
-  }
-
-  DCHECK_EQ(navigation_handle()->GetReloadType(), content::ReloadType::NONE);
-
-  if (previews::IsLitePageRedirectPreviewDomain(navigation_handle()->GetURL()))
-    return false;
-
-  return true;
-}
-
 // static
 GURL PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(
     const GURL& original_url) {
@@ -367,336 +109,6 @@
   return previews_url;
 }
 
-GURL PreviewsLitePageNavigationThrottle::GetPreviewsURL() const {
-  DCHECK(!previews::IsLitePageRedirectPreviewDomain(
-      navigation_handle()->GetURL()));
-  return GetPreviewsURLForURL(navigation_handle()->GetURL());
-}
-
-// static
-void PreviewsLitePageNavigationThrottle::LoadAndBypass(
-    content::WebContents* web_contents,
-    PreviewsLitePageNavigationThrottleManager* manager,
-    const content::OpenURLParams& params,
-    std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo> info,
-    bool use_post_task) {
-  DCHECK(web_contents);
-  DCHECK(manager);
-
-  manager->AddSingleBypass(params.url.spec());
-
-  PreviewsWebContentsLifetimeHelper::CreateForWebContents(web_contents);
-  PreviewsWebContentsLifetimeHelper* helper =
-      PreviewsWebContentsLifetimeHelper::FromWebContents(web_contents);
-
-  if (!use_post_task) {
-    helper->PostNewNavigation(params, std::move(info));
-    return;
-  }
-
-  base::PostTask(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&PreviewsWebContentsLifetimeHelper::PostNewNavigation,
-                     helper->GetWeakPtr(), params, std::move(info)));
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::TriggerPreview() const {
-  net::HttpRequestHeaders request_headers;
-  content::BrowserContext* browser_context =
-      navigation_handle()->GetWebContents()->GetBrowserContext();
-
-  previews::PreviewsUserData::ServerLitePageInfo* info =
-      GetOrCreateServerLitePageInfo(navigation_handle(), manager_);
-
-  // Set DRP headers.
-  DataReductionProxyChromeSettings* drp_settings =
-      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
-          browser_context);
-  DCHECK(drp_settings);
-  request_headers.MergeFrom(drp_settings->GetProxyRequestHeaders());
-
-  // Set ECT header.
-  request_headers.SetHeader(data_reduction_proxy::chrome_proxy_ect_header(),
-                            net::GetNameForEffectiveConnectionType(
-                                g_browser_process->network_quality_tracker()
-                                    ->GetEffectiveConnectionType()));
-
-  // Add in the page id to the chrome-proxy header.
-  if (request_headers.HasHeader(kChromeProxyHeader)) {
-    std::string header_value;
-    request_headers.GetHeader(kChromeProxyHeader, &header_value);
-
-    // 64 bit uint fits in 16 characters when represented in hexadecimal, but
-    // there needs to be a trailing null terminated character in the buffer.
-    char page_id_buffer[17];
-    base::strings::SafeSPrintf(page_id_buffer, "%x", info->page_id);
-    header_value += ", pid=" + std::string(page_id_buffer);
-    request_headers.SetHeader(kChromeProxyHeader, header_value);
-  }
-
-  content::WebContents* web_contents = navigation_handle()->GetWebContents();
-  PreviewsWebContentsLifetimeHelper::CreateForWebContents(web_contents);
-  PreviewsWebContentsLifetimeHelper* helper =
-      PreviewsWebContentsLifetimeHelper::FromWebContents(web_contents);
-
-  // Post a delayed task to the WebContents helper. This task will check after a
-  // timeout whether the previews navigation has finished (either in success or
-  // failure). If not, the helper will stop the ongoing previews navigation and
-  // load the original page.
-  const base::TimeDelta timeout =
-      previews::params::LitePagePreviewsNavigationTimeoutDuration();
-  std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo>
-      timed_out_info = info->Clone();
-  timed_out_info->status = previews::ServerLitePageStatus::kFailure;
-  if (timeout > base::TimeDelta()) {
-    base::PostDelayedTask(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::BindOnce(
-            &PreviewsWebContentsLifetimeHelper::CheckForHungNavigation,
-            helper->GetWeakPtr(), GetPreviewsURL(),
-            base::BindOnce(
-                &PreviewsLitePageNavigationThrottle::LoadAndBypass,
-                base::Unretained(web_contents), manager_,
-                MakeOpenURLParams(navigation_handle(),
-                                  navigation_handle()->GetURL(), std::string()),
-                std::move(timed_out_info), false)),
-        timeout);
-  }
-
-  // The helper class and its weak pointer protect against the WebContents
-  // dying in-between the PostTask and its execution, resulting in a use after
-  // free crash. Since the helper is a WebContentsUserData, it will be
-  // destroyed when the WebContents is and the task will not be executed.
-  base::PostTask(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&PreviewsWebContentsLifetimeHelper::PostNewNavigation,
-                     helper->GetWeakPtr(),
-                     MakeOpenURLParams(navigation_handle(), GetPreviewsURL(),
-                                       request_headers.ToString()),
-                     info->Clone()));
-
-  return content::NavigationThrottle::CANCEL;
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::MaybeNavigateToPreview() const {
-  const bool trigger =
-      IsEligibleForPreview() &&
-      !manager_->CheckSingleBypass(navigation_handle()->GetURL().spec());
-  UMA_HISTOGRAM_BOOLEAN("Previews.ServerLitePage.Triggered", trigger);
-  if (trigger)
-    return TriggerPreview();
-  return content::NavigationThrottle::PROCEED;
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::WillStartRequest() {
-  // Check if the user is trying to navigate to a valid previews URL in the form
-  // of a reload. In such a case, cancel the navigation and start a new one to
-  // the original URL instead. We might trigger this preview again, but if so
-  // there will be a server_lite_page_info associated with it.
-  std::string original_url;
-  if (previews::ExtractOriginalURLFromLitePageRedirectURL(
-          navigation_handle()->GetURL(), &original_url) &&
-      navigation_handle()->GetReloadType() != content::ReloadType::NONE &&
-      !GetServerLitePageInfo()) {
-    // Don't use |LoadAndBypass| because we might not want to bypass.
-    PreviewsWebContentsLifetimeHelper::CreateForWebContents(
-        navigation_handle()->GetWebContents());
-    PreviewsWebContentsLifetimeHelper* helper =
-        PreviewsWebContentsLifetimeHelper::FromWebContents(
-            navigation_handle()->GetWebContents());
-
-    base::PostTask(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::BindOnce(
-            &PreviewsWebContentsLifetimeHelper::PostNewNavigation,
-            helper->GetWeakPtr(),
-            MakeOpenURLParams(navigation_handle(), GURL(original_url),
-                              std::string()),
-            GetOrCreateServerLitePageInfo(navigation_handle(), manager_)
-                ->Clone()));
-    return content::NavigationThrottle::CANCEL;
-  }
-
-  return MaybeNavigateToPreview();
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::WillRedirectRequest() {
-  // WillRedirectRequest is called after the navigation_handle's URL has already
-  // been set to the next location. So inspect the previous URL for the presence
-  // of the previews server.
-  const std::vector<GURL>& redirect_chain =
-      navigation_handle()->GetRedirectChain();
-  // |navigation_handle()->GetURL()| is always the last element in the redirect
-  // chain. So if we've come here after a redirect, the length of
-  // |redirect_chain| is at least 2.
-  const GURL& previous_url = redirect_chain[redirect_chain.size() - 2];
-
-  // If we are redirecting on a preview, count some UMA and proceed.
-  std::string original_url;
-  if (previews::ExtractOriginalURLFromLitePageRedirectURL(previous_url,
-                                                          &original_url)) {
-    // A redirect means one of two things: (1) there is no preview available for
-    // this page and we should redirect back to the original page. (2) the
-    // previews server is forwarding along a redirect from the origin. The
-    // difference between the two is where the Location header is pointing. If
-    // it is pointing towards the original page, it is considered a bypass.
-    // Otherwise it is just a forwarded bypass.
-    if (GURL(original_url) == navigation_handle()->GetURL()) {
-      SetServerLitePageInfoStatus(previews::ServerLitePageStatus::kBypass);
-      manager_->AddSingleBypass(navigation_handle()->GetURL().spec());
-      UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                                ServerResponse::kPreviewUnavailable);
-
-      // Check if the original host should be blacklisted, as directed by the
-      // server.
-      const net::HttpResponseHeaders* response_headers =
-          navigation_handle()->GetResponseHeaders();
-
-      std::string chrome_proxy_header;
-      bool blacklist_host =
-          response_headers &&
-          response_headers->EnumerateHeader(nullptr, kChromeProxyHeader,
-                                            &chrome_proxy_header) &&
-          chrome_proxy_header.find("host-blacklisted") != std::string::npos;
-
-      if (blacklist_host)
-        manager_->BlacklistBypassedHost(GURL(original_url).host(),
-                                        kBlacklistDuration);
-
-      UMA_HISTOGRAM_BOOLEAN("Previews.ServerLitePage.HostBlacklistedOnBypass",
-                            blacklist_host);
-
-      return content::NavigationThrottle::PROCEED;
-    }
-
-    // Otherwise fall out of this if and potentially trigger again.
-    UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                              ServerResponse::kRedirect);
-    SetServerLitePageInfoStatus(previews::ServerLitePageStatus::kRedirect);
-  }
-
-  return MaybeNavigateToPreview();
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::WillFailRequest() {
-  std::string original_url;
-  if (!previews::ExtractOriginalURLFromLitePageRedirectURL(
-          navigation_handle()->GetURL(), &original_url)) {
-    return content::NavigationThrottle::PROCEED;
-  }
-
-  UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                            ServerResponse::kFailed);
-  SetServerLitePageInfoStatus(previews::ServerLitePageStatus::kFailure);
-
-  // The Preview was triggered but there was some irrecoverable issue (like
-  // there is no network connection). Load the original page and let it go
-  // through the normal process for whatever error it is.
-  LoadAndBypass(
-      navigation_handle()->GetWebContents(), manager_,
-      MakeOpenURLParams(navigation_handle(), GURL(original_url), std::string()),
-      GetOrCreateServerLitePageInfo(navigation_handle(), manager_)->Clone(),
-      true);
-  return content::NavigationThrottle::CANCEL;
-}
-
-content::NavigationThrottle::ThrottleCheckResult
-PreviewsLitePageNavigationThrottle::WillProcessResponse() {
-  std::string original_url;
-  if (!previews::ExtractOriginalURLFromLitePageRedirectURL(
-          navigation_handle()->GetURL(), &original_url)) {
-    // Return early if this request was not for a Preview.
-    return content::NavigationThrottle::PROCEED;
-  }
-
-  const net::HttpResponseHeaders* response_headers =
-      navigation_handle()->GetResponseHeaders();
-
-  // After this point, the given response is known to be for a Preview.
-  // The Previews server will only send the following response codes: 200, 307,
-  // 404, and 503. 200 and 307 should proceed as normal, 404 and 503 request the
-  // client to load the original page instead because the server is not capable
-  // of generating a lite page. All other response codes are treated as a 404.
-
-  const int response_code = response_headers->response_code();
-
-  if (response_code == net::HTTP_OK) {
-    // Attempt to get the original content length and report it to Data Saver.
-    const int64_t ofcl =
-        data_reduction_proxy::GetDataReductionProxyOFCL(response_headers);
-    if (ofcl > 0) {
-      manager_->ReportDataSavings(response_headers->GetContentLength(), ofcl,
-                                  GURL(original_url).host());
-    }
-
-    UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                              ServerResponse::kOk);
-    GetOrCreateServerLitePageInfo(navigation_handle(), manager_)->status =
-        previews::ServerLitePageStatus::kSuccess;
-
-    return content::NavigationThrottle::PROCEED;
-  }
-
-  if (response_code == net::HTTP_SERVICE_UNAVAILABLE) {
-    std::string retry_after_header;
-    base::TimeDelta retry_after = base::TimeDelta::FromSeconds(
-        base::RandInt(60, previews::params::PreviewServerLoadshedMaxSeconds()));
-    if (response_headers->EnumerateHeader(nullptr, "retry-after",
-                                          &retry_after_header)) {
-      net::HttpUtil::ParseRetryAfterHeader(retry_after_header,
-                                           base::Time::Now(), &retry_after);
-    }
-    manager_->SetServerUnavailableFor(retry_after);
-
-    UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                              ServerResponse::kServiceUnavailable);
-  } else if (response_code == net::HTTP_FORBIDDEN) {
-    UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                              ServerResponse::kAuthFailure);
-  } else {
-    UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.ServerResponse",
-                              ServerResponse::kOther);
-  }
-
-  previews::PreviewsUserData::ServerLitePageInfo* info =
-      GetOrCreateServerLitePageInfo(navigation_handle(), manager_);
-  info->status = previews::ServerLitePageStatus::kFailure;
-  LoadAndBypass(
-      navigation_handle()->GetWebContents(), manager_,
-      MakeOpenURLParams(navigation_handle(), GURL(original_url), std::string()),
-      info->Clone(), true);
-  return content::NavigationThrottle::CANCEL;
-}
-
-previews::PreviewsUserData::ServerLitePageInfo*
-PreviewsLitePageNavigationThrottle::GetServerLitePageInfo() const {
-  PreviewsUITabHelper* ui_tab_helper = PreviewsUITabHelper::FromWebContents(
-      navigation_handle()->GetWebContents());
-  if (!ui_tab_helper)
-    return nullptr;
-
-  previews::PreviewsUserData* previews_data =
-      ui_tab_helper->GetPreviewsUserData(navigation_handle());
-  if (!previews_data)
-    return nullptr;
-
-  return previews_data->server_lite_page_info();
-}
-
-void PreviewsLitePageNavigationThrottle::SetServerLitePageInfoStatus(
-    previews::ServerLitePageStatus status) {
-  previews::PreviewsUserData::ServerLitePageInfo* info =
-      GetServerLitePageInfo();
-  if (!info)
-    return;
-  info->status = status;
-}
-
 // static
 previews::PreviewsUserData::ServerLitePageInfo*
 PreviewsLitePageNavigationThrottle::GetOrCreateServerLitePageInfo(
@@ -746,7 +158,3 @@
 
   return info;
 }
-
-const char* PreviewsLitePageNavigationThrottle::GetNameForLogging() {
-  return "PreviewsLitePageNavigationThrottle";
-}
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.h b/chrome/browser/previews/previews_lite_page_navigation_throttle.h
index 6720cea..47e2bfe 100644
--- a/chrome/browser/previews/previews_lite_page_navigation_throttle.h
+++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.h
@@ -5,16 +5,16 @@
 #ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_H_
 #define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_H_
 
-#include "chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h"
 #include "components/previews/content/previews_user_data.h"
 #include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/navigation_throttle.h"
+#include "url/gurl.h"
 
 namespace content {
-struct OpenURLParams;
 class BrowserContext;
 }  // namespace content
 
+class PreviewsLitePageNavigationThrottleManager;
+
 // If the given URL is a LitePage Preview URL, this returns true but does not
 // change the |url|. This will set |update_virtual_url_with_url| on
 // NavigationEntry so that |HandlePreviewsLitePageURLRewriteReverse| is called
@@ -31,11 +31,7 @@
     GURL* url,
     content::BrowserContext* browser_context);
 
-// This class does the actual decision making about when to serve a Lite Page
-// Server Preview, and the legwork to trigger the Preview navigation. When a
-// Preview is triggered, it will cancel the incoming navigation and PostTask a
-// new one to the Previews Server.
-class PreviewsLitePageNavigationThrottle : public content::NavigationThrottle {
+class PreviewsLitePageNavigationThrottle {
  public:
   // Reasons that a navigation is blacklisted from this preview. This enum must
   // remain synchronized with the enum |PreviewsServerLitePageBlacklistReason|
@@ -110,24 +106,9 @@
     kMaxValue = kConnectionError,
   };
 
-  PreviewsLitePageNavigationThrottle(
-      content::NavigationHandle* handle,
-      PreviewsLitePageNavigationThrottleManager* manager);
-
-  ~PreviewsLitePageNavigationThrottle() override;
-
   // Returns the URL for a preview given by the url.
   static GURL GetPreviewsURLForURL(const GURL& original_url);
 
-  // Starts a new navigation with |params| page in the given |web_contents|,
-  // adding the params' url as a single bypass to |manager|.
-  static void LoadAndBypass(
-      content::WebContents* web_contents,
-      PreviewsLitePageNavigationThrottleManager* manager,
-      const content::OpenURLParams& params,
-      std::unique_ptr<previews::PreviewsUserData::ServerLitePageInfo> info,
-      bool use_post_task);
-
   // Records an entry in the ineligibility histogram.
   static void LogIneligibleReason(IneligibleReason reason);
 
@@ -140,52 +121,6 @@
       content::NavigationHandle* navigation_handle,
       PreviewsLitePageNavigationThrottleManager* manager);
 
- private:
-  // The current effective connection type;
-  net::EffectiveConnectionType GetECT() const;
-
-  // Returns true if the current URL is eligible for the preview. Does not check
-  // any blacklisting or single bypass.
-  bool IsEligibleForPreview() const;
-
-  // Returns the URL for a preview of the current URL given by the navigation
-  // handle.
-  GURL GetPreviewsURL() const;
-
-  // This method is called on every request and redirect. It checks all
-  // eligibility and blacklisting criteria for the current URL and will return
-  // CANCEL when the preview is triggered and post a new navigation, or will
-  // return PROCEED if the preview is not triggered.
-  content::NavigationThrottle::ThrottleCheckResult MaybeNavigateToPreview()
-      const;
-
-  // Can be called by any of the content::NavigationThrottle implementation
-  // methods to trigger the preview. Returns the
-  // |content::NavigationThrottle::ThrottleCheckResult| for the implemented
-  // method to return.
-  content::NavigationThrottle::ThrottleCheckResult TriggerPreview() const;
-
-  // Gets the ServerLitePageInfo struct from an existing attempted lite page
-  // navigation, if there is one. If not, returns nullptr.
-  previews::PreviewsUserData::ServerLitePageInfo* GetServerLitePageInfo() const;
-
-  // Safely sets the status of the ServerLitePageInfo struct from an existing
-  // attempted lite page navigation, if there is one. If not, does nothing.
-  void SetServerLitePageInfoStatus(previews::ServerLitePageStatus status);
-
-  // content::NavigationThrottle implementation:
-  content::NavigationThrottle::ThrottleCheckResult WillStartRequest() override;
-  content::NavigationThrottle::ThrottleCheckResult WillRedirectRequest()
-      override;
-  content::NavigationThrottle::ThrottleCheckResult WillFailRequest() override;
-  content::NavigationThrottle::ThrottleCheckResult WillProcessResponse()
-      override;
-  const char* GetNameForLogging() override;
-
-  // The manager class to report state changes to and get state from. Outlives
-  // |this|.
-  PreviewsLitePageNavigationThrottleManager* manager_;
-
   DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageNavigationThrottle);
 };
 
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
index 35efb3dea..024cf52 100644
--- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
+++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
@@ -12,6 +12,7 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/previews/previews_lite_page_navigation_throttle.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/previews/core/previews_experiments.h"
 #include "components/previews/core/previews_lite_page_redirect.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/common/previews_state.h"
@@ -116,7 +117,7 @@
 
 bool PreviewsLitePageRedirectURLLoader::IsResponseSuccess(
     net::Error net_error,
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Any HTTP response is fine, so long as we got it.
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.h b/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
index 04417fb..54887760 100644
--- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
+++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.h
@@ -58,7 +58,7 @@
   // AvailabilityProber::Delegate:
   bool ShouldSendNextProbe() override;
   bool IsResponseSuccess(net::Error net_error,
-                         const network::ResourceResponseHead* head,
+                         const network::mojom::URLResponseHead* head,
                          std::unique_ptr<std::string> body) override;
 
  private:
diff --git a/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc b/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
index a790a42..55fc976 100644
--- a/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
+++ b/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
@@ -28,6 +28,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 using net::DefineNetworkTrafficAnnotation;
 
@@ -146,7 +147,7 @@
 
 void GCDApiFlowImpl::OnDownloadedToString(
     std::unique_ptr<std::string> response_body) {
-  const network::ResourceResponseHead* response_info =
+  const network::mojom::URLResponseHead* response_info =
       url_loader_->ResponseInfo();
 
   if (url_loader_->NetError() != net::OK || !response_info) {
diff --git a/chrome/browser/printing/cloud_print/privet_url_loader.cc b/chrome/browser/printing/cloud_print/privet_url_loader.cc
index 7f82e01..81207239a 100644
--- a/chrome/browser/printing/cloud_print/privet_url_loader.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_loader.cc
@@ -27,6 +27,7 @@
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace cloud_print {
 
@@ -220,7 +221,7 @@
 
 void PrivetURLLoader::OnResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   if (!response_head.headers ||
       response_head.headers->response_code() == net::HTTP_SERVICE_UNAVAILABLE) {
     url_loader_.reset();
diff --git a/chrome/browser/printing/cloud_print/privet_url_loader.h b/chrome/browser/printing/cloud_print/privet_url_loader.h
index 537cd50..93fcb3a 100644
--- a/chrome/browser/printing/cloud_print/privet_url_loader.h
+++ b/chrome/browser/printing/cloud_print/privet_url_loader.h
@@ -17,6 +17,7 @@
 #include "base/values.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace network {
@@ -115,7 +116,7 @@
   void RequestTokenRefresh();
   void RefreshToken(const std::string& token);
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head);
+                         const network::mojom::URLResponseHead& response_head);
   void OnDownloadedToString(std::unique_ptr<std::string> response_body);
   void OnDownloadedToFile(base::FilePath path);
   bool CheckURLLoaderForError();
diff --git a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
index 76ead54..b533ba8 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
@@ -16,7 +16,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/browser_task_environment.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
index ce171dc9..5aa01ab 100644
--- a/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
+++ b/chrome/browser/profiling_host/chrome_browser_main_extra_parts_profiling.cc
@@ -11,7 +11,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "components/heap_profiling/supervisor.h"
 #include "components/services/heap_profiling/public/cpp/settings.h"
-#include "content/public/browser/system_connector.h"
 
 namespace {
 
@@ -42,7 +41,6 @@
   heap_profiling::Mode mode = heap_profiling::GetModeForStartup();
   if (mode != heap_profiling::Mode::kNone) {
     heap_profiling::Supervisor::GetInstance()->Start(
-        content::GetSystemConnector(),
         base::BindOnce(
             &heap_profiling::ProfilingProcessHost::Start,
             base::Unretained(
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index e8434c0..d1a58e6 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
@@ -888,8 +889,10 @@
   decision_details.Clear();
 
   // Disable the heuristics and check that the tab can now be safely discarded.
-  GetMutableStaticProactiveTabFreezeAndDiscardParamsForTesting()
-      ->disable_heuristics_protections = true;
+  base::AutoReset<bool> disable_heuristics_protections(
+      &GetMutableStaticProactiveTabFreezeAndDiscardParamsForTesting()
+           ->disable_heuristics_protections,
+      true);
 
   EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
   EXPECT_TRUE(decision_details.IsPositive());
@@ -901,9 +904,7 @@
   decision_details.Clear();
 }
 
-// TODO(crbug.com/1004578) Disabled due to flake
-TEST_F(TabLifecycleUnitTest,
-       DISABLED_CannotFreezeOrDiscardIfConnectedToBluetooth) {
+TEST_F(TabLifecycleUnitTest, CannotFreezeOrDiscardIfConnectedToBluetooth) {
   TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
                                       usage_clock_.get(), web_contents_,
                                       tab_strip_model_.get());
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 58b2b89..4bb39ec 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -19,6 +19,7 @@
         "bluetooth_internals:closure_compile",
         "bookmarks:closure_compile",
         "discards:closure_compile",
+        "download_internals:closure_compile",
         "downloads:closure_compile",
         "history:closure_compile",
         "local_ntp:closure_compile",
diff --git a/chrome/browser/resources/accessibility/accessibility.js b/chrome/browser/resources/accessibility/accessibility.js
index 6a52f038..277d6c8 100644
--- a/chrome/browser/resources/accessibility/accessibility.js
+++ b/chrome/browser/resources/accessibility/accessibility.js
@@ -57,10 +57,12 @@
     const tree = $(id + ':tree');
     // If the tree is visible, request a new tree with the updated mode.
     const shouldRequestTree = !!tree && tree.style.display != 'none';
-    chrome.send('toggleAccessibility', [
-      String(data.processId), String(data.routeId), mode,
-      String(shouldRequestTree)
-    ]);
+    chrome.send('toggleAccessibility', [{
+                  'processId': data.processId,
+                  'routeId': data.routeId,
+                  'modeId': mode,
+                  'shouldRequestTree': shouldRequestTree
+                }]);
   }
 
   function requestTree(data, element) {
@@ -78,13 +80,17 @@
       const delay = $('native_ui_delay').value;
       setTimeout(() => {
         chrome.send(
-            'requestNativeUITree', [String(data.sessionId), requestType]);
+            'requestNativeUITree',
+            [{'sessionId': data.sessionId, 'requestType': requestType}]);
       }, delay);
     } else {
-      chrome.send('requestWebContentsTree', [
-        String(data.processId), String(data.routeId), requestType, allow,
-        allowEmpty, deny
-      ]);
+      chrome.send(
+          'requestWebContentsTree', [{
+            'processId': data.processId,
+            'routeId': data.routeId,
+            'requestType': requestType,
+            'filters': {'allow': allow, 'allowEmpty': allowEmpty, 'deny': deny}
+          }]);
     }
   }
 
@@ -97,7 +103,7 @@
     bindCheckbox('text', data['text']);
     bindCheckbox('screenreader', data['screenreader']);
     bindCheckbox('html', data['html']);
-    bindCheckbox('label_images', data['label_images']);
+    bindCheckbox('label_images', data['labelImages']);
     bindCheckbox('internal', data['internal']);
 
     $('pages').textContent = '';
@@ -128,7 +134,8 @@
       $(name).labels[0].classList.add('disabled');
     }
     $(name).addEventListener('change', function() {
-      chrome.send('setGlobalFlag', [name, $(name).checked]);
+      chrome.send(
+          'setGlobalFlag', [{'flagName': name, 'enabled': $(name).checked}]);
       document.location.reload();
     });
   }
@@ -169,7 +176,7 @@
 
     if (data.type == 'page') {
       const siteInfo = document.createElement('div');
-      const properties = ['favicon_url', 'name', 'url'];
+      const properties = ['faviconUrl', 'name', 'url'];
       for (let j = 0; j < properties.length; j++) {
         siteInfo.appendChild(formatValue(data, properties[j]));
       }
@@ -181,7 +188,7 @@
       row.appendChild(createModeElement(AXMode.kScreenReader, data, 'web'));
       row.appendChild(createModeElement(AXMode.kHTML, data, 'web'));
       row.appendChild(
-          createModeElement(AXMode.kLabelImages, data, 'label_images'));
+          createModeElement(AXMode.kLabelImages, data, 'labelImages'));
     } else {
       const siteInfo = document.createElement('span');
       siteInfo.appendChild(formatValue(data, 'name'));
@@ -212,7 +219,7 @@
   function formatValue(data, property) {
     const value = data[property];
 
-    if (property == 'favicon_url') {
+    if (property == 'faviconUrl') {
       const faviconElement = document.createElement('img');
       if (value) {
         faviconElement.src = value;
@@ -257,7 +264,7 @@
   }
 
   function createModeElement(mode, data, globalStateName) {
-    const currentMode = data['a11y_mode'];
+    const currentMode = data['a11yMode'];
     const link = document.createElement('a', 'action-link');
     link.setAttribute('role', 'button');
 
diff --git a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2
index d48354df..e43f124 100644
--- a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2
+++ b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2
@@ -109,6 +109,9 @@
   "content_security_policy": "default-src 'none'; script-src 'self' chrome://resources; style-src 'unsafe-inline' chrome://resources;",
   "externally_connectable": {
     "ids": [
+       // Braille IME.
+      "jddehjeebkoimngcbdkaahpobgicbffp",
+
        // Allow connections with js2at (name may change) project, which allows
        // web pages and ChromeVox to exchange messages that conform to
        // a set of approved schemas. Note: js2at is currently built as an
diff --git a/chrome/browser/resources/download_internals/BUILD.gn b/chrome/browser/resources/download_internals/BUILD.gn
index e1314cf..1d0ff82 100644
--- a/chrome/browser/resources/download_internals/BUILD.gn
+++ b/chrome/browser/resources/download_internals/BUILD.gn
@@ -15,6 +15,7 @@
 js_library("download_internals") {
   deps = [
     ":download_internals_browser_proxy",
+    "//third_party/jstemplate:jstemplate",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:util",
diff --git a/chrome/browser/resources/download_internals/download_internals.html b/chrome/browser/resources/download_internals/download_internals.html
index 62b2d8c..9c60f4f 100644
--- a/chrome/browser/resources/download_internals/download_internals.html
+++ b/chrome/browser/resources/download_internals/download_internals.html
@@ -4,14 +4,12 @@
     <meta charset="utf-8">
     <title>Download Internals</title>
     <meta name="viewport" content="width=device-width">
-    <link rel="stylesheet" href="chrome://resources/css/list.css">
     <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
     <link rel="stylesheet" href="download_internals.css">
 
-    <link rel="import" href="chrome://resources/html/cr.html">
-    <link rel="import" href="chrome://resources/html/cr/ui/list_item.html">
-    <link rel="import" href="chrome://resources/html/cr/ui/list.html">
-    <link rel="import" href="chrome://resources/html/util.html">
+    <script src="chrome://resources/js/promise_resolver.js"></script>
+    <script src="chrome://resources/js/cr.js"></script>
+    <script src="chrome://resources/js/util.js"></script>
 
     <script src="download_internals_browser_proxy.js"></script>
     <script src="download_internals.js"></script>
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index f46fb75..b135a7b7 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -88,19 +88,38 @@
 
 js_library("toolbar_manager") {
   deps = [
-    "elements/viewer-pdf-toolbar:viewer-pdf-toolbar",
-    "elements/viewer-zoom-toolbar:viewer-zoom-toolbar",
+    "elements/viewer-pdf-toolbar",
+    "elements/viewer-zoom-toolbar",
   ]
 }
 
 js_library("controller") {
   deps = [
     ":viewport",
+    "elements/viewer-pdf-toolbar",
     "//ui/webui/resources/js:load_time_data",
     "//ui/webui/resources/js/cr:event_target",
   ]
 }
 
+js_library("pdf_viewer") {
+  deps = [
+    ":controller",
+    ":navigator",
+    ":toolbar_manager",
+    ":viewport",
+    "elements/viewer-bookmark",
+    "elements/viewer-error-screen",
+    "elements/viewer-page-indicator",
+    "elements/viewer-password-screen",
+    "elements/viewer-pdf-toolbar",
+    "elements/viewer-zoom-toolbar",
+    "//ui/webui/resources/js:event_tracker",
+    "//ui/webui/resources/js:load_time_data",
+  ]
+  externs_list = [ "$externs_path/resources_private.js" ]
+}
+
 js_type_check("pdf_resources") {
   deps = [
     ":browser_api",
@@ -111,6 +130,7 @@
     ":open_pdf_params_parser",
     ":pdf_fitting_type",
     ":pdf_scripting_api",
+    ":pdf_viewer",
     ":toolbar_manager",
     ":viewport",
     ":viewport_scroller",
diff --git a/chrome/browser/resources/pdf/controller.js b/chrome/browser/resources/pdf/controller.js
index 815fc7c..f405a02 100644
--- a/chrome/browser/resources/pdf/controller.js
+++ b/chrome/browser/resources/pdf/controller.js
@@ -39,7 +39,7 @@
  */
 let PrintPreviewParams;
 
-// Note: Redefining these types here, to work around the fact that ink externs
+// Note: Redefining this type here, to work around the fact that ink externs
 // are only available on Chrome OS, so the targets that contain them cannot be
 // built on other platforms.
 // TODO (rbpotter): Break InkController into its own file that is only included
@@ -47,15 +47,6 @@
 
 /**
  * @typedef {{
- *   tool: string,
- *   size: number,
- *   color: string,
- * }}
- */
-let AnnotationTool;
-
-/**
- * @typedef {{
  *   setAnnotationTool: function(AnnotationTool):void,
  *   viewportChanged: function():void,
  *   saveDocument: function():!Promise,
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js
index afb87dfe..5811cb0 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js
@@ -1,6 +1,20 @@
 // 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.
+
+// Note: Redefining this type here, to work around the fact that ink externs
+// are only available on Chrome OS, so the targets that contain them cannot be
+// built on other platforms.
+
+/**
+ * @typedef {{
+ *   tool: string,
+ *   size: number,
+ *   color: (string|null),
+ * }}
+ */
+let AnnotationTool;
+
 (function() {
 Polymer({
   is: 'viewer-pdf-toolbar',
@@ -24,7 +38,7 @@
       reflectToAttribute: true,
     },
 
-    /** @type {?Object} */
+    /** @type {?AnnotationTool} */
     annotationTool: {
       type: Object,
       value: null,
diff --git a/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js b/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
index fe24ab6..fe28ef8 100644
--- a/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
+++ b/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
@@ -2,6 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+/**
+ * @typedef {{
+ *   fittingType: !FittingType,
+ *   userInitiated: boolean,
+ * }}
+ */
+let FitToChangedEvent;
+
 (function() {
 
 const FIT_TO_PAGE_BUTTON_STATE = 0;
diff --git a/chrome/browser/resources/pdf/pdf_scripting_api.js b/chrome/browser/resources/pdf/pdf_scripting_api.js
index 0ab77f4..5793bac 100644
--- a/chrome/browser/resources/pdf/pdf_scripting_api.js
+++ b/chrome/browser/resources/pdf/pdf_scripting_api.js
@@ -6,7 +6,7 @@
  * Turn a dictionary received from postMessage into a key event.
  *
  * @param {Object} dict A dictionary representing the key event.
- * @return {Event} A key event.
+ * @return {!Event} A key event.
  */
 function DeserializeKeyEvent(dict) {
   const e = document.createEvent('Event');
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index f7fe37f..0fd1d1f7 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -5,8 +5,53 @@
 'use strict';
 
 /**
- * @return {number} Width of a scrollbar in pixels
+ * @typedef {{
+ *   source: Object,
+ *   origin: string,
+ *   data: !MessageData,
+ * }}
  */
+let MessageObject;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   height: number,
+ *   width: number,
+ *   pageDimensions: Array
+ * }}
+ */
+let DocumentDimensionsMessageData;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   url: string,
+ *   disposition: !PdfNavigator.WindowOpenDisposition,
+ * }}
+ */
+let NavigateMessageData;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   title: string,
+ *   bookmarks: !Array<!Bookmark>,
+ *   canSerializeDocument: boolean,
+ * }}
+ */
+let MetadataMessageData;
+
+/**
+ * @typedef {{
+ *   hasUnsavedChanges: (boolean|undefined),
+ *   fileName: string,
+ *   dataToSave: !ArrayBuffer
+ * }}
+ */
+let RequiredSaveResult;
+
+/** @return {number} Width of a scrollbar in pixels */
 function getScrollbarWidth() {
   const div = document.createElement('div');
   div.style.visibility = 'hidden';
@@ -22,7 +67,6 @@
 
 /**
  * Return the filename component of a URL, percent decoded if possible.
- *
  * @param {string} url The URL to get the filename from.
  * @return {string} The filename component.
  */
@@ -44,8 +88,7 @@
 /**
  * Whether keydown events should currently be ignored. Events are ignored when
  * an editable element has focus, to allow for proper editing controls.
- *
- * @param {HTMLElement} activeElement The currently selected DOM node.
+ * @param {Element} activeElement The currently selected DOM node.
  * @return {boolean} True if keydown events should be ignored.
  */
 function shouldIgnoreKeyEvents(activeElement) {
@@ -92,24 +135,47 @@
 /**
  * Creates a new PDFViewer. There should only be one of these objects per
  * document.
- *
  * @param {!BrowserApi} browserApi An object providing an API to the browser.
  * @constructor
  */
 function PDFViewer(browserApi) {
+  /** @private {!BrowserApi} */
   this.browserApi_ = browserApi;
+
+  /** @private {string} */
   this.originalUrl_ = this.browserApi_.getStreamInfo().originalUrl;
+
+  /** @private {string} */
   this.javascript_ = this.browserApi_.getStreamInfo().javascript || 'block';
+
+  /** @private {!LoadState} */
   this.loadState_ = LoadState.LOADING;
+
+  /** @private {?Object} */
   this.parentWindow_ = null;
+
+  /** @private {?string} */
   this.parentOrigin_ = null;
+
+  /** @private {boolean} */
   this.isFormFieldFocused_ = false;
+
+  /** @private {number} */
   this.beepCount_ = 0;
+
+  /** @private {!Array} */
   this.delayedScriptingMessages_ = [];
+
+  /** @private {!PromiseResolver} */
   this.loaded_ = new PromiseResolver();
 
+  /** @private {boolean} */
   this.isPrintPreview_ = location.origin === 'chrome://print';
+
+  /** @private {boolean} */
   this.isPrintPreviewLoadingFinished_ = false;
+
+  /** @private {boolean} */
   this.isUserInitiatedEvent_ = true;
 
   /** @private {boolean} */
@@ -127,6 +193,7 @@
   PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED);
 
   // Parse open pdf parameters.
+  /** @private {!OpenPdfParamsParser} */
   this.paramsParser_ = new OpenPdfParamsParser(
       destination => this.pluginController_.getNamedDestination(destination));
   const toolbarEnabled =
@@ -136,15 +203,24 @@
   // The sizer element is placed behind the plugin element to cause scrollbars
   // to be displayed in the window. It is sized according to the document size
   // of the pdf and zoom level.
-  this.sizer_ = $('sizer');
+  this.sizer_ = /** @type {!HTMLDivElement} */ ($('sizer'));
 
-  if (this.isPrintPreview_) {
-    this.pageIndicator_ = $('page-indicator');
-  }
-  this.passwordScreen_ = $('password-screen');
-  this.passwordScreen_.addEventListener(
-      'password-submitted', e => this.onPasswordSubmitted_(e));
-  this.errorScreen_ = $('error-screen');
+  /** @private {?ViewerPageIndicatorElement} */
+  this.pageIndicator_ = this.isPrintPreview_ ?
+      /** @type {!ViewerPageIndicatorElement} */ ($('page-indicator')) :
+      null;
+
+  /** @private {?ViewerPasswordScreenElement} */
+  this.passwordScreen_ =
+      /** @type {!ViewerPasswordScreenElement} */ ($('password-screen'));
+  this.passwordScreen_.addEventListener('password-submitted', e => {
+    this.onPasswordSubmitted_(
+        /** @type {!CustomEvent<{password: string}>} */ (e));
+  });
+
+  /** @private {?ViewerErrorScreenElement} */
+  this.errorScreen_ =
+      /** @type {!ViewerErrorScreenElement} */ ($('error-screen'));
   // Can only reload if we are in a normal tab.
   if (chrome.tabs && this.browserApi_.getStreamInfo().tabId != -1) {
     this.errorScreen_.reloadFn = () => {
@@ -160,6 +236,8 @@
       this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ?
       this.browserApi_.getDefaultZoom() :
       1.0;
+
+  /** @private {!Viewport} */
   this.viewport_ = new Viewport(
       window, this.sizer_, getScrollbarWidth(), defaultZoom, topToolbarHeight);
   this.viewport_.setViewportChangedCallback(() => this.viewportChanged_());
@@ -175,7 +253,10 @@
   // element is sized to fill the entire window and is set to be fixed
   // positioning, acting as a viewport. The plugin renders into this viewport
   // according to the scroll position of the window.
-  this.plugin_ = document.createElement('embed');
+  /** @private {!HTMLEmbedElement} */
+  this.plugin_ =
+      /** @type {!HTMLEmbedElement} */ (document.createElement('embed'));
+
   // NOTE: The plugin's 'id' field must be set to 'plugin' since
   // chrome/renderer/printing/print_render_frame_helper.cc actually
   // references it.
@@ -185,8 +266,9 @@
   // Handle scripting messages from outside the extension that wish to interact
   // with it. We also send a message indicating that extension has loaded and
   // is ready to receive messages.
-  window.addEventListener(
-      'message', message => this.handleScriptingMessage(message), false);
+  window.addEventListener('message', message => {
+    this.handleScriptingMessage(/** @type {!MessageObject} */ (message));
+  }, false);
 
   this.plugin_.setAttribute('src', this.originalUrl_);
   this.plugin_.setAttribute(
@@ -211,12 +293,15 @@
 
   $('content').appendChild(this.plugin_);
 
+  /** @private {!PluginController} */
   this.pluginController_ = new PluginController(
       this.plugin_, this.viewport_, () => this.isUserInitiatedEvent_,
       () => this.loaded);
   this.tracker_.add(
       this.pluginController_.getEventTarget(), 'plugin-message',
       e => this.handlePluginMessage_(e));
+
+  /** @private {!InkController} */
   this.inkController_ = new InkController(this.viewport_);
   this.tracker_.add(
       this.inkController_.getEventTarget(), 'stroke-added',
@@ -224,18 +309,25 @@
   this.tracker_.add(
       this.inkController_.getEventTarget(), 'set-annotation-undo-state',
       e => this.setAnnotationUndoState_(e));
+
+  /** @private {!ContentController} */
   this.currentController_ = this.pluginController_;
 
   // Setup the button event listeners.
-  this.zoomToolbar_ = $('zoom-toolbar');
+  /** @private {!ViewerZoomToolbarElement} */
+  this.zoomToolbar_ =
+      /** @type {!ViewerZoomToolbarElement} */ ($('zoom-toolbar'));
   this.zoomToolbar_.setIsPrintPreview(this.isPrintPreview_);
   this.zoomToolbar_.addEventListener(
-      'fit-to-changed', e => this.fitToChanged_(e));
+      'fit-to-changed',
+      e => this.fitToChanged_(
+          /** @type {!CustomEvent<FitToChangedEvent>}} */ (e)));
   this.zoomToolbar_.addEventListener('zoom-in', () => this.viewport_.zoomIn());
   this.zoomToolbar_.addEventListener(
       'zoom-out', () => this.viewport_.zoomOut());
 
-  this.gestureDetector_ = new GestureDetector($('content'));
+  /** @private {!GestureDetector} */
+  this.gestureDetector_ = new GestureDetector(assert($('content')));
   this.gestureDetector_.addEventListener(
       'pinchstart', e => this.onPinchStart_(e));
   this.sentPinchEvent_ = false;
@@ -243,19 +335,23 @@
       'pinchupdate', e => this.onPinchUpdate_(e));
   this.gestureDetector_.addEventListener('pinchend', e => this.onPinchEnd_(e));
 
+  /** @private {?ViewerPdfToolbarElement} */
+  this.toolbar_ = null;
   if (toolbarEnabled) {
-    this.toolbar_ = $('toolbar');
+    this.toolbar_ = /** @type {!ViewerPdfToolbarElement} */ ($('toolbar'));
     this.toolbar_.hidden = false;
-    this.toolbar_.addEventListener('save', () => this.save());
-    this.toolbar_.addEventListener('print', () => this.print());
+    this.toolbar_.addEventListener('save', () => this.save_());
+    this.toolbar_.addEventListener('print', () => this.print_());
     this.toolbar_.addEventListener(
         'undo', () => this.currentController_.undo());
     this.toolbar_.addEventListener(
         'redo', () => this.currentController_.redo());
     this.toolbar_.addEventListener(
-        'rotate-right', () => this.rotateClockwise());
-    this.toolbar_.addEventListener(
-        'annotation-mode-toggled', e => this.annotationModeToggled_(e));
+        'rotate-right', () => this.rotateClockwise_());
+    this.toolbar_.addEventListener('annotation-mode-toggled', e => {
+      this.annotationModeToggled_(
+          /** @type {!CustomEvent<{value: boolean}>} */ (e));
+    });
     this.toolbar_.addEventListener(
         'annotation-tool-changed',
         e => this.inkController_.setAnnotationTool(e.detail.value));
@@ -290,10 +386,12 @@
     }
   });
 
+  /** @private {!ToolbarManager} */
   this.toolbarManager_ =
       new ToolbarManager(window, this.toolbar_, this.zoomToolbar_);
 
   // Set up the ZoomManager.
+  /** @private {!ZoomManager} */
   this.zoomManager_ = ZoomManager.create(
       this.browserApi_.getZoomBehavior(), () => this.viewport_.getZoom(),
       zoom => this.browserApi_.setZoom(zoom),
@@ -303,16 +401,20 @@
       zoom => this.zoomManager_.onBrowserZoomChange(zoom));
 
   // Setup the keyboard event listener.
-  document.addEventListener('keydown', e => this.handleKeyEvent_(e));
+  document.addEventListener(
+      'keydown', e => this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (e)));
   document.addEventListener('mousemove', e => this.handleMouseEvent_(e));
   document.addEventListener('mouseout', e => this.handleMouseEvent_(e));
   document.addEventListener(
       'contextmenu', e => this.handleContextMenuEvent_(e));
 
   const tabId = this.browserApi_.getStreamInfo().tabId;
+  /** @private {!PdfNavigator} */
   this.navigator_ = new PdfNavigator(
       this.originalUrl_, this.viewport_, this.paramsParser_,
       new NavigatorDelegate(tabId));
+
+  /** @private {!ViewportScroller} */
   this.viewportScroller_ =
       new ViewportScroller(this.viewport_, this.plugin_, window);
 
@@ -322,7 +424,7 @@
 
   // Listen for save commands from the browser.
   if (chrome.mimeHandlerPrivate && chrome.mimeHandlerPrivate.onSave) {
-    chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave(url));
+    chrome.mimeHandlerPrivate.onSave.addListener(url => this.onSave_(url));
   }
 }
 
@@ -330,8 +432,7 @@
   /**
    * Handle key events. These may come from the user directly or via the
    * scripting API.
-   *
-   * @param {KeyboardEvent} e the event to handle.
+   * @param {!KeyboardEvent} e the event to handle.
    * @private
    */
   handleKeyEvent_: function(e) {
@@ -343,7 +444,7 @@
       return;
     }
 
-    this.toolbarManager_.hideToolbarsAfterTimeout(e);
+    this.toolbarManager_.hideToolbarsAfterTimeout();
 
     const pageUpHandler = () => {
       // Go to the previous page if we are fit-to-page or fit-to-height.
@@ -352,8 +453,8 @@
         // Since we do the movement of the page.
         e.preventDefault();
       } else if (fromScriptingAPI) {
-        position.y -= this.viewport.size.height;
-        this.viewport.position = position;
+        position.y -= this.viewport_.size.height;
+        this.viewport_.position = position;
       }
     };
     const pageDownHandler = () => {
@@ -363,8 +464,8 @@
         // Since we do the movement of the page.
         e.preventDefault();
       } else if (fromScriptingAPI) {
-        position.y += this.viewport.size.height;
-        this.viewport.position = position;
+        position.y += this.viewport_.size.height;
+        this.viewport_.position = position;
       }
     };
 
@@ -402,14 +503,14 @@
             e.preventDefault();
           } else if (fromScriptingAPI) {
             position.x -= Viewport.SCROLL_INCREMENT;
-            this.viewport.position = position;
+            this.viewport_.position = position;
           }
         }
         return;
       case 38:  // Up arrow key.
         if (fromScriptingAPI) {
           position.y -= Viewport.SCROLL_INCREMENT;
-          this.viewport.position = position;
+          this.viewport_.position = position;
         }
         return;
       case 39:  // Right arrow key.
@@ -423,14 +524,14 @@
             e.preventDefault();
           } else if (fromScriptingAPI) {
             position.x += Viewport.SCROLL_INCREMENT;
-            this.viewport.position = position;
+            this.viewport_.position = position;
           }
         }
         return;
       case 40:  // Down arrow key.
         if (fromScriptingAPI) {
           position.y += Viewport.SCROLL_INCREMENT;
-          this.viewport.position = position;
+          this.viewport_.position = position;
         }
         return;
       case 65:  // 'a' key.
@@ -448,7 +549,7 @@
         return;
       case 219:  // Left bracket key.
         if (e.ctrlKey) {
-          this.rotateCounterclockwise();
+          this.rotateCounterclockwise_();
         }
         return;
       case 220:  // Backslash key.
@@ -458,7 +559,7 @@
         return;
       case 221:  // Right bracket key.
         if (e.ctrlKey) {
-          this.rotateClockwise();
+          this.rotateClockwise_();
         }
         return;
     }
@@ -483,12 +584,18 @@
     }
   },
 
+  /**
+   * @param {!Event} e The context menu event
+   * @private
+   */
   handleContextMenuEvent_: function(e) {
     // Stop Chrome from popping up the context menu on long press. We need to
     // make sure the start event did not have 2 touches because we don't want
     // to block two finger tap opening the context menu. We check for
     // firesTouchEvents in order to not block the context menu on right click.
-    if (e.sourceCapabilities.firesTouchEvents &&
+    const capabilities =
+        /** @type {{ sourceCapabilities: Object }} */ (e).sourceCapabilities;
+    if (capabilities.firesTouchEvents &&
         !this.gestureDetector_.wasTwoFingerTouch()) {
       e.preventDefault();
     }
@@ -496,7 +603,6 @@
 
   /**
    * Handles the annotation mode being toggled on or off.
-   *
    * @param {!CustomEvent<{value: boolean}>} e
    * @private
    */
@@ -506,9 +612,11 @@
       // Enter annotation mode.
       assert(this.currentController_ == this.pluginController_);
       // TODO(dstockwell): set plugin read-only, begin transition
-      this.updateProgress(0);
+      this.updateProgress_(0);
       // TODO(dstockwell): handle save failure
-      const result = await this.pluginController_.save(true);
+      const saveResult = await this.pluginController_.save(true);
+      // Data always exists when save is called with requireResult = true.
+      const result = /** @type {!RequiredSaveResult} */ (saveResult);
       if (result.hasUnsavedChanges) {
         assert(!loadTimeData.getBoolean('pdfFormSaveEnabled'));
         try {
@@ -516,25 +624,26 @@
         } catch (e) {
           // The user aborted entering annotation mode. Revert to the plugin.
           this.toolbar_.annotationMode = false;
-          this.updateProgress(100);
+          this.updateProgress_(100);
           return;
         }
       }
       PDFMetrics.record(PDFMetrics.UserAction.ENTER_ANNOTATION_MODE);
       this.hasEnteredAnnotationMode_ = true;
       // TODO(dstockwell): feed real progress data from the Ink component
-      this.updateProgress(50);
+      this.updateProgress_(50);
       await this.inkController_.load(result.fileName, result.dataToSave);
-      this.inkController_.setAnnotationTool(this.toolbar_.annotationTool);
+      this.inkController_.setAnnotationTool(
+          assert(this.toolbar_.annotationTool));
       this.currentController_ = this.inkController_;
       this.pluginController_.unload();
-      this.updateProgress(100);
+      this.updateProgress_(100);
     } else {
       // Exit annotation mode.
       PDFMetrics.record(PDFMetrics.UserAction.EXIT_ANNOTATION_MODE);
       assert(this.currentController_ == this.inkController_);
       // TODO(dstockwell): set ink read-only, begin transition
-      this.updateProgress(0);
+      this.updateProgress_(0);
       // This runs separately to allow other consumers of `loaded` to queue
       // up after this task.
       this.loaded.then(() => {
@@ -542,7 +651,9 @@
         this.inkController_.unload();
       });
       // TODO(dstockwell): handle save failure
-      const result = await this.inkController_.save(true);
+      const saveResult = await this.inkController_.save(true);
+      // Data always exists when save is called with requireResult = true.
+      const result = /** @type {!RequiredSaveResult} */ (saveResult);
       await this.pluginController_.load(result.fileName, result.dataToSave);
       // Ensure the plugin gets the initial viewport.
       this.pluginController_.afterZoom();
@@ -551,7 +662,6 @@
 
   /**
    * Exits annotation mode if active.
-   *
    * @return {Promise<void>}
    */
   exitAnnotationMode_: async function() {
@@ -564,11 +674,7 @@
 
   /**
    * Request to change the viewport fitting type.
-   *
-   * @param {!CustomEvent<{
-   *     fittingType: FittingType,
-   *     userInitiated: boolean
-   * }>} e
+   * @param {!CustomEvent<FitToChangedEvent>} e
    * @private
    */
   fitToChanged_: function(e) {
@@ -590,7 +696,6 @@
   /**
    * Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has
    * finished loading.
-   *
    * @private
    */
   sendDocumentLoadedMessage_: function() {
@@ -608,7 +713,6 @@
    * Handle open pdf parameters. This function updates the viewport as per
    * the parameters mentioned in the url while opening pdf. The order is
    * important as later actions can override the effects of previous actions.
-   *
    * @param {Object} params The open params passed in the URL.
    * @private
    */
@@ -645,10 +749,9 @@
   /**
    * Moves the viewport to a point in a page. Called back after a
    * 'transformPagePointReply' is returned from the plugin.
-   *
    * @param {string} origin Identifier for the caller for logging purposes.
    * @param {number} page The index of the page to go to. zero-based.
-   * @param {Object} message Message received from the plugin containing the
+   * @param {Point} message Message received from the plugin containing the
    *     x and y to navigate to in screen coordinates.
    * @private
    */
@@ -660,13 +763,23 @@
   },
 
   /**
-   * @return {Promise} Resolved when the load state reaches LOADED, rejects on
+   * @return {!Promise} Resolved when the load state reaches LOADED, rejects on
    *     FAILED.
    */
   get loaded() {
     return this.loaded_.promise;
   },
 
+  /** @return {!Viewport} The viewport. Used for testing. */
+  get viewport() {
+    return this.viewport_;
+  },
+
+  /** @return {!Array<Bookmark>} The bookmarks. Used for testing. */
+  get bookmarks() {
+    return this.bookmarks_;
+  },
+
   /**
    * Updates the load state and triggers completion of the `loaded`
    * promise if necessary.
@@ -693,10 +806,10 @@
   /**
    * Update the loading progress of the document in response to a progress
    * message being received from the content controller.
-   *
    * @param {number} progress the progress as a percentage.
+   * @private
    */
-  updateProgress: function(progress) {
+  updateProgress_: function(progress) {
     if (this.toolbar_) {
       this.toolbar_.loadProgress = progress;
     }
@@ -741,13 +854,14 @@
   /**
    * Load a dictionary of translated strings into the UI. Used as a callback for
    * chrome.resourcesPrivate.
-   *
    * @param {Object} strings Dictionary of translated strings
    * @private
    */
   handleStrings_: function(strings) {
-    document.documentElement.dir = strings.textdirection;
-    document.documentElement.lang = strings.language;
+    const stringsDictionary =
+        /** @type {{ textdirection: string, language: string }} */ (strings);
+    document.documentElement.dir = stringsDictionary.textdirection;
+    document.documentElement.lang = stringsDictionary.language;
 
     loadTimeData.data = strings;
     const isNewPrintPreview = this.isPrintPreview_ &&
@@ -774,8 +888,7 @@
   /**
    * An event handler for handling password-submitted events. These are fired
    * when an event is entered into the password screen.
-   *
-   * @param {Object} event a password-submitted event.
+   * @param {!CustomEvent<{password: string}>} event a password-submitted event.
    * @private
    */
   onPasswordSubmitted_: function(event) {
@@ -784,7 +897,6 @@
 
   /**
    * A callback that sets |isUserInitiatedEvent_| to |userInitiated|.
-   *
    * @param {boolean} userInitiated The value to set |isUserInitiatedEvent_| to.
    * @private
    */
@@ -795,7 +907,6 @@
 
   /**
    * A callback that's called when an update to a pinch zoom is detected.
-   *
    * @param {!Object} e the pinch event.
    * @private
    */
@@ -812,7 +923,6 @@
 
   /**
    * A callback that's called when the end of a pinch zoom is detected.
-   *
    * @param {!Object} e the pinch event.
    * @private
    */
@@ -826,7 +936,6 @@
 
   /**
    * A callback that's called when the start of a pinch zoom is detected.
-   *
    * @param {!Object} e the pinch event.
    * @private
    */
@@ -840,7 +949,6 @@
 
   /**
    * A callback that's called after the viewport changes.
-   *
    * @private
    */
   viewportChanged_: function() {
@@ -909,8 +1017,7 @@
    * Handle a scripting message from outside the extension (typically sent by
    * PDFScriptingAPI in a page containing the extension) to interact with the
    * plugin.
-   *
-   * @param {MessageObject} message the message to handle.
+   * @param {!MessageObject} message The message to handle.
    */
   handleScriptingMessage: function(message) {
     if (this.parentWindow_ != message.source) {
@@ -948,23 +1055,25 @@
 
   /**
    * Handle scripting messages specific to print preview.
-   *
-   * @param {!Event} messageEvent the message to handle.
+   * @param {!MessageObject} message the message to handle.
    * @return {boolean} true if the message was handled, false otherwise.
    * @private
    */
-  handlePrintPreviewScriptingMessage_: function(messageEvent) {
+  handlePrintPreviewScriptingMessage_: function(message) {
     if (!this.isPrintPreview_) {
       return false;
     }
 
-    const messageData = /** @type {!MessageData} */ (messageEvent.data);
+    let messageData = message.data;
     switch (messageData.type.toString()) {
       case 'loadPreviewPage':
+        messageData =
+            /** @type {{ url:  string, index: number }} */ (messageData);
         this.pluginController_.loadPreviewPage(
             messageData.url, messageData.index);
         return true;
       case 'resetPrintPreviewMode':
+        messageData = /** @type {!PrintPreviewParams} */ (messageData);
         this.setLoadState_(LoadState.LOADING);
         if (!this.inPrintPreviewMode_) {
           this.inPrintPreviewMode_ = true;
@@ -989,26 +1098,27 @@
 
         this.pageIndicator_.pageLabels = messageData.pageNumbers;
 
-        this.pluginController_.resetPrintPreviewMode(
-            /** @type {!PrintPreviewParams} */ (messageData));
+        this.pluginController_.resetPrintPreviewMode(messageData);
         return true;
       case 'sendKeyEvent':
-        this.handleKeyEvent_(DeserializeKeyEvent(messageData.keyEvent));
+        this.handleKeyEvent_(/** @type {!KeyboardEvent} */ (DeserializeKeyEvent(
+            /** @type {{ keyEvent: Object }} */ (message.data).keyEvent)));
         return true;
       case 'hideToolbars':
         this.toolbarManager_.resetKeyboardNavigationAndHideToolbars();
         return true;
       case 'darkModeChanged':
-        this.dark_ = messageData.darkMode;
+        this.dark_ = /** @type {{darkMode: boolean}} */ (message.data).darkMode;
         if (this.isPrintPreview_) {
           this.sendBackgroundColorForPrintPreview_();
         }
         return true;
       case 'scrollPosition':
         const position = this.viewport_.position;
+        messageData = /** @type {{ x: number, y: number }} */ (message.data);
         position.y += messageData.y;
         position.x += messageData.x;
-        this.viewport.position = position;
+        this.viewport_.position = position;
         return true;
     }
 
@@ -1018,7 +1128,6 @@
   /**
    * Send a scripting message outside the extension (typically to
    * PDFScriptingAPI in a page containing the extension).
-   *
    * @param {Object} message the message to send.
    * @private
    */
@@ -1041,25 +1150,6 @@
   },
 
   /**
-   * @type {Viewport} the viewport of the PDF viewer.
-   */
-  get viewport() {
-    return this.viewport_;
-  },
-
-  /**
-   * Each bookmark is an Object containing a:
-   * - title
-   * - page (optional)
-   * - array of children (themselves bookmarks)
-   *
-   * @type {Array} the top-level bookmarks of the PDF.
-   */
-  get bookmarks() {
-    return this.bookmarks_;
-  },
-
-  /**
    * @param {!CustomEvent<MessageData>} e
    * @private
    */
@@ -1067,38 +1157,46 @@
     const data = e.detail;
     switch (data.type.toString()) {
       case 'beep':
-        this.handleBeep();
+        this.handleBeep_();
         return;
       case 'documentDimensions':
-        this.setDocumentDimensions(data);
+        this.setDocumentDimensions_(
+            /** @type {!DocumentDimensionsMessageData} */ (data));
         return;
       case 'getPassword':
-        this.handlePasswordRequest();
+        this.handlePasswordRequest_();
         return;
       case 'getSelectedTextReply':
-        this.handleSelectedTextReply(data.selectedText);
+        this.handleSelectedTextReply_(
+            /** @type {{ selectedText: string }} */ (data).selectedText);
         return;
       case 'loadProgress':
-        this.updateProgress(data.progress);
+        this.updateProgress_(
+            /** @type {{ progress: number }} */ (data).progress);
         return;
       case 'navigate':
-        this.handleNavigate(data.url, data.disposition);
+        const navigateData = /** @type {!NavigateMessageData} */ (data);
+        this.handleNavigate_(navigateData.url, navigateData.disposition);
         return;
       case 'printPreviewLoaded':
-        this.handlePrintPreviewLoaded();
+        this.handlePrintPreviewLoaded_();
         return;
       case 'metadata':
-        this.setDocumentMetadata(
-            data.title, data.bookmarks, data.canSerializeDocument);
+        const metadata = /** @type {!MetadataMessageData} */ (data);
+        this.setDocumentMetadata_(
+            metadata.title, metadata.bookmarks, metadata.canSerializeDocument);
         return;
       case 'setIsSelecting':
-        this.setIsSelecting(data.isSelecting);
+        this.setIsSelecting_(
+            /** @type {{ isSelecting: boolean }} */ (data).isSelecting);
         return;
       case 'getNamedDestinationReply':
-        this.paramsParser_.onNamedDestinationReceived(data.pageNumber);
+        this.paramsParser_.onNamedDestinationReceived(
+            /** @type {{ pageNumber: number }} */ (data).pageNumber);
         return;
       case 'formFocusChange':
-        this.setIsFormFieldFocused(data.focused);
+        this.isFormFieldFocused_ =
+            /** @type {{ focused: boolean }} */ (data).focused;
         return;
     }
     assertNotReached('Unknown message type received: ' + data.type);
@@ -1106,11 +1204,10 @@
 
   /**
    * Sets document dimensions from the current controller.
-   *
-   * @param {{height: number, width: number, pageDimensions: Array}}
-   *     documentDimensions
+   * @param {!DocumentDimensionsMessageData} documentDimensions
+   * @private
    */
-  setDocumentDimensions: function(documentDimensions) {
+  setDocumentDimensions_: function(documentDimensions) {
     this.documentDimensions_ = documentDimensions;
     this.isUserInitiatedEvent_ = false;
     this.viewport_.setDocumentDimensions(this.documentDimensions_);
@@ -1128,16 +1225,18 @@
 
   /**
    * Handles a beep request from the current controller.
+   * @private
    */
-  handleBeep: function() {
+  handleBeep_: function() {
     // Beeps are annoying, so just track count for now.
     this.beepCount_ += 1;
   },
 
   /**
    * Handles a password request from the current controller.
+   * @private
    */
-  handlePasswordRequest: function() {
+  handlePasswordRequest_: function() {
     // If the password screen isn't up, put it up. Otherwise we're
     // responding to an incorrect password so deny it.
     if (!this.passwordScreen_.active) {
@@ -1152,8 +1251,9 @@
   /**
    * Handles a selected text reply from the current controller.
    * @param {string} selectedText
+   * @private
    */
-  handleSelectedTextReply: function(selectedText) {
+  handleSelectedTextReply_: function(selectedText) {
     this.sendScriptingMessage_({
       type: 'getSelectedTextReply',
       selectedText: selectedText,
@@ -1162,11 +1262,11 @@
 
   /**
    * Handles a navigation request from the current controller.
-   *
    * @param {string} url
-   * @param {string} disposition
+   * @param {!PdfNavigator.WindowOpenDisposition} disposition
+   * @private
    */
-  handleNavigate: function(url, disposition) {
+  handleNavigate_: function(url, disposition) {
     // If in print preview, always open a new tab.
     if (this.isPrintPreview_) {
       this.navigator_.navigate(
@@ -1179,8 +1279,9 @@
   /**
    * Handles a notification that print preview has loaded from the
    * current controller.
+   * @private
    */
-  handlePrintPreviewLoaded: function() {
+  handlePrintPreviewLoaded_: function() {
     this.isPrintPreviewLoadingFinished_ = true;
     this.sendDocumentLoadedMessage_();
   },
@@ -1188,10 +1289,11 @@
   /**
    * Sets document metadata from the current controller.
    * @param {string} title
-   * @param {Array} bookmarks
+   * @param {!Array<!Bookmark>} bookmarks
    * @param {boolean} canSerializeDocument
+   * @private
    */
-  setDocumentMetadata: function(title, bookmarks, canSerializeDocument) {
+  setDocumentMetadata_: function(title, bookmarks, canSerializeDocument) {
     if (title) {
       document.title = title;
     } else {
@@ -1200,7 +1302,7 @@
     this.bookmarks_ = bookmarks;
     if (this.toolbar_) {
       this.toolbar_.docTitle = document.title;
-      this.toolbar_.bookmarks = this.bookmarks;
+      this.toolbar_.bookmarks = this.bookmarks_;
     }
     this.canSerializeDocument_ = canSerializeDocument;
     this.updateAnnotationAvailable_();
@@ -1209,38 +1311,31 @@
   /**
    * Sets the is selecting flag from the current controller.
    * @param {boolean} isSelecting
+   * @private
    */
-  setIsSelecting: function(isSelecting) {
+  setIsSelecting_: function(isSelecting) {
     this.viewportScroller_.setEnableScrolling(isSelecting);
   },
 
   /**
-   * Sets the form field focused flag from the current controller.
-   * @param {boolean} focused
-   */
-  setIsFormFieldFocused: function(focused) {
-    this.isFormFieldFocused_ = focused;
-  },
-
-  /**
    * An event handler for when the browser tells the PDF Viewer to perform a
    * save.
-   *
    * @param {string} streamUrl unique identifier for a PDF Viewer instance.
    * @private
    */
-  onSave: async function(streamUrl) {
+  onSave_: async function(streamUrl) {
     if (streamUrl != this.browserApi_.getStreamInfo().streamUrl) {
       return;
     }
 
-    this.save();
+    this.save_();
   },
 
   /**
    * Saves the current PDF document to disk.
+   * @private
    */
-  save: async function() {
+  save_: async function() {
     PDFMetrics.record(PDFMetrics.UserAction.SAVE);
     if (this.hasEnteredAnnotationMode_) {
       PDFMetrics.record(PDFMetrics.UserAction.SAVE_WITH_ANNOTATION);
@@ -1285,7 +1380,8 @@
     this.exitAnnotationMode_();
   },
 
-  print: async function() {
+  /** @private */
+  print_: async function() {
     PDFMetrics.record(PDFMetrics.UserAction.PRINT);
     await this.exitAnnotationMode_();
     this.currentController_.print();
@@ -1294,6 +1390,7 @@
   /**
    * Updates the toolbar's annotation available flag depending on current
    * conditions.
+   * @private
    */
   updateAnnotationAvailable_() {
     if (!this.toolbar_) {
@@ -1312,14 +1409,16 @@
     this.toolbar_.annotationAvailable = annotationAvailable;
   },
 
-  rotateClockwise() {
+  /** @private */
+  rotateClockwise_() {
     PDFMetrics.record(PDFMetrics.UserAction.ROTATE);
     this.viewport_.rotateClockwise(1);
     this.currentController_.rotateClockwise();
     this.updateAnnotationAvailable_();
   },
 
-  rotateCounterclockwise() {
+  /** @private */
+  rotateCounterclockwise_() {
     PDFMetrics.record(PDFMetrics.UserAction.ROTATE);
     this.viewport_.rotateClockwise(3);
     this.currentController_.rotateCounterclockwise();
diff --git a/chrome/browser/resources/pdf/toolbar_manager.js b/chrome/browser/resources/pdf/toolbar_manager.js
index a8caa38..8a2b06c 100644
--- a/chrome/browser/resources/pdf/toolbar_manager.js
+++ b/chrome/browser/resources/pdf/toolbar_manager.js
@@ -49,14 +49,14 @@
 class ToolbarManager {
   /**
    * @param {!Window} window The window containing the UI.
-   * @param {!ViewerPdfToolbarElement} toolbar
+   * @param {?ViewerPdfToolbarElement} toolbar
    * @param {!ViewerZoomToolbarElement} zoomToolbar
    */
   constructor(window, toolbar, zoomToolbar) {
     /** @private {!Window} */
     this.window_ = window;
 
-    /** @private {!ViewerPdfToolbarElement} */
+    /** @private {?ViewerPdfToolbarElement} */
     this.toolbar_ = toolbar;
 
     /** @private {!ViewerZoomToolbarElement} */
@@ -98,7 +98,7 @@
 
   /** @param {!MouseEvent} e */
   handleMouseMove(e) {
-    this.isMouseNearTopToolbar_ = this.toolbar_ && isMouseNearTopToolbar(e);
+    this.isMouseNearTopToolbar_ = !!this.toolbar_ && isMouseNearTopToolbar(e);
     this.isMouseNearSideToolbar_ =
         isMouseNearSideToolbar(e, this.window_, this.reverseSideToolbar_);
 
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html
index 1f22b1f..8eacafb 100644
--- a/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -85,7 +85,7 @@
       <template is="dom-if" if="[[androidEnabled_]]">
         <template is="dom-if" route-path="/storage/externalStoragePreferences">
           <settings-subpage
-              associated-control="[[$$('#externalStoragePreferencesRow')]]"
+              associated-control="[[$$('#storageRow')]]"
               page-title="$i18n{storageExternal}">
             <settings-storage-external prefs="{{prefs}}">
             </settings-storage-external>
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js
index a98f501..60facec 100644
--- a/chrome/browser/resources/settings/search_settings.js
+++ b/chrome/browser/resources/settings/search_settings.js
@@ -149,11 +149,15 @@
     let associatedControl = null;
     // Find corresponding SETTINGS-SECTION parent and make it visible.
     let parent = node;
-    while (parent && parent.nodeName !== 'SETTINGS-SECTION') {
+    while (parent.nodeName !== 'SETTINGS-SECTION') {
       parent = parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE ?
           parent.host :
           parent.parentNode;
-      if (parent && parent.nodeName == 'SETTINGS-SUBPAGE') {
+      if (!parent) {
+        // |node| wasn't inside a SETTINGS-SECTION.
+        return null;
+      }
+      if (parent.nodeName == 'SETTINGS-SUBPAGE') {
         // TODO(dpapad): Cast to SettingsSubpageElement here.
         associatedControl = assert(
             parent.associatedControl,
@@ -161,9 +165,7 @@
                 parent.pageTitle + ', but was not found.');
       }
     }
-    if (parent) {
-      parent.hiddenBySearch = false;
-    }
+    parent.hiddenBySearch = false;
 
     // Need to add the search bubble after the parent SETTINGS-SECTION has
     // become visible, otherwise |offsetWidth| returns zero.
diff --git a/chrome/browser/resources/tab_strip/tab.html b/chrome/browser/resources/tab_strip/tab.html
index 1e71543..d2d1421 100644
--- a/chrome/browser/resources/tab_strip/tab.html
+++ b/chrome/browser/resources/tab_strip/tab.html
@@ -1,20 +1,26 @@
 <style>
   :host {
-    border-radius: var(--tabstrip-card-border-radius);
-    box-shadow: var(--tabstrip-elevation-box-shadow);
     cursor: pointer;
-    display: flex;
-    flex-direction: column;
     height: 230px;
-    overflow: hidden;
+    position: relative;
     width: 280px;
   }
 
-  :host([active]) {
+  :host([active]) #dragImage {
     box-shadow: 0 0 0 2px var(--tabstrip-focus-color);
     outline: none;
   }
 
+  #dragImage {
+    border-radius: var(--tabstrip-card-border-radius);
+    box-shadow: var(--tabstrip-elevation-box-shadow);
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    overflow: hidden;
+    width: 100%;
+  }
+
   #title {
     align-items: center;
     background: var(--tabstrip-card-background-color);
@@ -75,6 +81,7 @@
   #thumbnailImg {
     height: 100%;
     object-fit: contain;
+    pointer-events: none;
     width: 100%;
   }
 
@@ -94,16 +101,39 @@
   :host([pinned]) #thumbnail {
     display: none;
   }
+
+  :host([dragging]) #dragPlaceholder {
+    background: rgba(var(--google-grey-200-rgb));
+    border-radius: var(--tabstrip-card-border-radius);
+    height: 100%;
+    width: 100%;
+  }
+
+  :host([dragging][active]) #dragPlaceholder {
+    box-shadow: 0 0 0 2px var(--tabstrip-focus-color);
+  }
+
+  /* When being dragged, the contents of the drag image needs to be off-screen
+   * with nothing else on top or below obscuring it. */
+  :host([dragging]) #dragImage {
+    box-shadow: none;
+    position: absolute;
+    top: -999px;
+  }
 </style>
 
-<header id="title">
-  <span id="favicon"></span>
-  <h2 id="titleText"></h2>
-  <button id="close">
-    <span id="closeIcon"></span>
-  </button>
-</header>
+<div id="dragPlaceholder"></div>
 
-<div id="thumbnail">
-  <img id="thumbnailImg">
+<div id="dragImage">
+  <header id="title">
+    <span id="favicon"></span>
+    <h2 id="titleText"></h2>
+    <button id="close">
+      <span id="closeIcon"></span>
+    </button>
+  </header>
+
+  <div id="thumbnail">
+    <img id="thumbnailImg">
+  </div>
 </div>
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.js
index 0b16488f..c14cfb3 100644
--- a/chrome/browser/resources/tab_strip/tab.js
+++ b/chrome/browser/resources/tab_strip/tab.js
@@ -22,6 +22,11 @@
         /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#close'));
 
     /** @private {!HTMLElement} */
+    this.dragImage_ =
+        /** @type {!HTMLElement} */ (
+            this.shadowRoot.querySelector('#dragImage'));
+
+    /** @private {!HTMLElement} */
     this.faviconEl_ =
         /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#favicon'));
 
@@ -48,6 +53,10 @@
     this.closeButtonEl_.addEventListener('click', this.onClose_.bind(this));
   }
 
+  connectedCallback() {
+    this.setAttribute('draggable', 'true');
+  }
+
   /** @return {!Tab} */
   get tab() {
     return this.tab_;
@@ -82,6 +91,13 @@
   }
 
   /**
+   * @return {!HTMLElement}
+   */
+  getDragImage() {
+    return this.dragImage_;
+  }
+
+  /**
    * @param {string} imgData
    */
   updateThumbnail(imgData) {
@@ -111,6 +127,13 @@
   }
 
   /**
+   * @param {boolean} dragging
+   */
+  setDragging(dragging) {
+    this.toggleAttribute('dragging', dragging);
+  }
+
+  /**
    * @return {!Promise}
    */
   slideIn() {
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.js
index 914c12d..9a6046b 100644
--- a/chrome/browser/resources/tab_strip/tab_list.js
+++ b/chrome/browser/resources/tab_strip/tab_list.js
@@ -9,15 +9,25 @@
 import {TabElement} from './tab.js';
 import {TabsApiProxy} from './tabs_api_proxy.js';
 
+/** @const {number} */
 const GHOST_PINNED_TAB_COUNT = 3;
 
 /**
  * The amount of padding to leave between the edge of the screen and the active
  * tab when auto-scrolling. This should leave some room to show the previous or
  * next tab to afford to users that there more tabs if the user scrolls.
+ * @const {number}
  */
 const SCROLL_PADDING = 32;
 
+/**
+ * @param {!Element} element
+ * @return {boolean}
+ */
+function isTabElement(element) {
+  return element.tagName === 'TABSTRIP-TAB';
+}
+
 class TabListElement extends CustomElement {
   static get template() {
     return `{__html_template__}`;
@@ -35,6 +45,12 @@
      */
     this.animationPromises = Promise.resolve();
 
+    /**
+     * The TabElement that is currently being dragged.
+     * @private {!TabElement|undefined}
+     */
+    this.draggedItem_;
+
     /** @private {!Element} */
     this.pinnedTabsContainerElement_ =
         /** @type {!Element} */ (
@@ -59,6 +75,13 @@
 
     addWebUIListener(
         'tab-thumbnail-updated', this.tabThumbnailUpdated_.bind(this));
+
+    this.addEventListener(
+        'dragstart', (e) => this.onDragStart_(/** @type {!DragEvent} */ (e)));
+    this.addEventListener(
+        'dragend', (e) => this.onDragEnd_(/** @type {!DragEvent} */ (e)));
+    this.addEventListener(
+        'dragover', (e) => this.onDragOver_(/** @type {!DragEvent} */ (e)));
   }
 
   /**
@@ -131,6 +154,15 @@
   }
 
   /**
+   * @return {number}
+   * @private
+   */
+  getPinnedTabsCount_() {
+    return this.pinnedTabsContainerElement_.childElementCount -
+        GHOST_PINNED_TAB_COUNT;
+  }
+
+  /**
    * @param {!TabElement} tabElement
    * @param {number} index
    * @private
@@ -145,9 +177,7 @@
     } else {
       // Pinned tabs are in their own container, so the index of non-pinned
       // tabs need to be offset by the number of pinned tabs
-      const offsetIndex = index -
-          (this.pinnedTabsContainerElement_.childElementCount -
-           GHOST_PINNED_TAB_COUNT);
+      const offsetIndex = index - this.getPinnedTabsCount_();
       this.tabsContainerElement_.insertBefore(
           tabElement, this.tabsContainerElement_.childNodes[offsetIndex]);
     }
@@ -156,6 +186,64 @@
   }
 
   /**
+   * @param {!DragEvent} event
+   * @private
+   */
+  onDragEnd_(event) {
+    if (!this.draggedItem_) {
+      return;
+    }
+
+    this.draggedItem_.setDragging(false);
+    this.draggedItem_ = undefined;
+  }
+
+  /**
+   * @param {!DragEvent} event
+   * @private
+   */
+  onDragOver_(event) {
+    event.preventDefault();
+    const dragOverItem = event.path.find((pathItem) => {
+      return pathItem !== this.draggedItem_ && isTabElement(pathItem);
+    });
+
+    if (!dragOverItem ||
+        dragOverItem.tab.pinned !== this.draggedItem_.tab.pinned) {
+      // TODO(johntlee): Support dragging between different pinned states.
+      return;
+    }
+
+    let dragOverIndex =
+        Array.from(dragOverItem.parentNode.children).indexOf(dragOverItem);
+    event.dataTransfer.dropEffect = 'move';
+    if (!dragOverItem.tab.pinned) {
+      dragOverIndex += this.getPinnedTabsCount_();
+    }
+
+    this.tabsApi_.moveTab(this.draggedItem_.tab.id, dragOverIndex);
+  }
+
+  /**
+   * @param {!DragEvent} event
+   * @private
+   */
+  onDragStart_(event) {
+    const draggedItem = event.path[0];
+    if (!isTabElement(draggedItem)) {
+      return;
+    }
+
+    this.draggedItem_ = /** @type {!TabElement} */ (draggedItem);
+    this.draggedItem_.setDragging(true);
+    event.dataTransfer.effectAllowed = 'move';
+    event.dataTransfer.setDragImage(
+        this.draggedItem_.getDragImage(),
+        event.pageX - this.draggedItem_.offsetLeft,
+        event.pageY - this.draggedItem_.offsetTop);
+  }
+
+  /**
    * @param {!TabActivatedInfo} activeInfo
    * @private
    */
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
index c414ba0..152a479 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
@@ -272,7 +272,8 @@
   // Wait for the request to complete and check the response.
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(net::OK, loader()->NetError());
-  const network::ResourceResponseHead* response_head = loader()->ResponseInfo();
+  const network::mojom::URLResponseHead* response_head =
+      loader()->ResponseInfo();
   ASSERT_TRUE(response_head && response_head->headers);
   EXPECT_FALSE(response_head->headers->HasHeader("X-Response-3"));
   EXPECT_TRUE(response_head->headers->HasHeader("X-Response-4"));
diff --git a/chrome/browser/ssl/common_name_mismatch_handler.cc b/chrome/browser/ssl/common_name_mismatch_handler.cc
index 36b405b..19ab038 100644
--- a/chrome/browser/ssl/common_name_mismatch_handler.cc
+++ b/chrome/browser/ssl/common_name_mismatch_handler.cc
@@ -19,6 +19,7 @@
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 CommonNameMismatchHandler::CommonNameMismatchHandler(
     const GURL& request_url,
@@ -125,7 +126,7 @@
 
 void CommonNameMismatchHandler::OnSimpleLoaderHandler(
     const GURL& final_url,
-    const network::ResourceResponseHead* head) {
+    const network::mojom::URLResponseHead* head) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsCheckingSuggestedUrl());
   DCHECK(!check_url_callback_.is_null());
@@ -149,14 +150,14 @@
 
 void CommonNameMismatchHandler::OnSimpleLoaderRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   OnSimpleLoaderHandler(redirect_info.new_url, &response_head);
 }
 
 void CommonNameMismatchHandler::OnSimpleLoaderResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   OnSimpleLoaderHandler(final_url, &response_head);
 }
 
diff --git a/chrome/browser/ssl/common_name_mismatch_handler.h b/chrome/browser/ssl/common_name_mismatch_handler.h
index dfda29127..0a864ad 100644
--- a/chrome/browser/ssl/common_name_mismatch_handler.h
+++ b/chrome/browser/ssl/common_name_mismatch_handler.h
@@ -15,6 +15,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -22,7 +23,6 @@
 }  // namespace net
 
 namespace network {
-struct ResourceResponseHead;
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
 }  // namespace network
@@ -80,14 +80,14 @@
 
  private:
   void OnSimpleLoaderHandler(const GURL& final_url,
-                             const network::ResourceResponseHead* head);
+                             const network::mojom::URLResponseHead* head);
   void OnSimpleLoaderRedirect(
       const net::RedirectInfo& redirect_info,
-      const network::ResourceResponseHead& response_head,
+      const network::mojom::URLResponseHead& response_head,
       std::vector<std::string>* to_be_removed_headers);
   void OnSimpleLoaderResponseStarted(
       const GURL& final_url,
-      const network::ResourceResponseHead& response_head);
+      const network::mojom::URLResponseHead& response_head);
   void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
 
   // Returns true if the check is currently running.
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
index 03f00ee..be1b69ef0 100644
--- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -50,10 +50,30 @@
     SupervisedUserSettingsService* settings_service =
         SupervisedUserSettingsServiceFactory::GetForKey(
             profile->GetProfileKey());
-    auto dict = std::make_unique<base::DictionaryValue>();
-    dict->SetKey(host, base::Value(false));
+
+    const base::DictionaryValue* local_settings =
+        settings_service->LocalSettingsForTest();
+    std::unique_ptr<base::DictionaryValue> dict_to_insert;
+
+    if (local_settings->HasKey(
+            supervised_users::kContentPackManualBehaviorHosts)) {
+      const base::DictionaryValue* dict_value;
+
+      local_settings->GetDictionary(
+          supervised_users::kContentPackManualBehaviorHosts, &dict_value);
+
+      std::unique_ptr<base::Value> clone =
+          std::make_unique<base::Value>(dict_value->Clone());
+
+      dict_to_insert = base::DictionaryValue::From(std::move(clone));
+    } else {
+      dict_to_insert = std::make_unique<base::DictionaryValue>();
+    }
+
+    dict_to_insert->SetKey(host, base::Value(false));
     settings_service->SetLocalSetting(
-        supervised_users::kContentPackManualBehaviorHosts, std::move(dict));
+        supervised_users::kContentPackManualBehaviorHosts,
+        std::move(dict_to_insert));
   }
 
   bool IsInterstitialBeingShown(Browser* browser);
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc
index 329bc747..4a11cdc 100644
--- a/chrome/browser/supervised_user/supervised_user_settings_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -433,6 +433,11 @@
   InformSubscribers();
 }
 
+const base::DictionaryValue*
+SupervisedUserSettingsService::LocalSettingsForTest() const {
+  return local_settings_.get();
+}
+
 base::DictionaryValue* SupervisedUserSettingsService::GetOrCreateDictionary(
     const std::string& key) const {
   base::Value* value = nullptr;
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.h b/chrome/browser/supervised_user/supervised_user_settings_service.h
index 860a63d..d3d7eed4 100644
--- a/chrome/browser/supervised_user/supervised_user_settings_service.h
+++ b/chrome/browser/supervised_user/supervised_user_settings_service.h
@@ -148,6 +148,8 @@
   void OnPrefValueChanged(const std::string& key) override;
   void OnInitializationCompleted(bool success) override;
 
+  const base::DictionaryValue* LocalSettingsForTest() const;
+
  private:
   base::DictionaryValue* GetOrCreateDictionary(const std::string& key) const;
   base::DictionaryValue* GetAtomicSettings() const;
diff --git a/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc b/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc
index 9f14487..da994fd 100644
--- a/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc
+++ b/chrome/browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "chrome/browser/android/android_theme_resources.h"
-#include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -94,8 +93,6 @@
     return 0;
 
   int buttons = BUTTON_OK;
-  if (chrome::android::IsNoTouchModeEnabled())
-    buttons |= BUTTON_CANCEL;
 
   return buttons;
 }
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index f788bbd..b80d200 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -479,7 +479,10 @@
     }
   }
 
-  void RemoveIcon(const std::string& app_id) { icon_map_.erase(app_id); }
+  void RemoveIcon(const std::string& app_id) {
+    icon_map_.erase(app_id);
+    icon_loader_->ClearImage(app_id);
+  }
 
  private:
   int IconSize(bool for_chip) const {
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc
index 9c39997..f3ced37 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc
@@ -29,6 +29,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
@@ -221,7 +222,7 @@
 
 void ChromeOmniboxNavigationObserver::OnURLRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   bool valid_redirect = IsValidNavigation(alternate_nav_match_.destination_url,
                                           redirect_info.new_url);
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.h b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.h
index 5e8e2733..fdb810d 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.h
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.h
@@ -18,13 +18,13 @@
 #include "content/public/browser/reload_type.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "net/url_request/url_fetcher_delegate.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 class Profile;
 class ShortcutsBackend;
 class TemplateURLService;
 
 namespace network {
-struct ResourceResponseHead;
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
 }
@@ -115,7 +115,7 @@
 
   // See SimpleURLLoader::OnRedirectCallback for info on the signature.
   void OnURLRedirect(const net::RedirectInfo& redirect_info,
-                     const network::ResourceResponseHead& response_head,
+                     const network::mojom::URLResponseHead& response_head,
                      std::vector<std::string>* to_be_removed_headers);
 
   // Called from either OnURLLoadComplete or OnURLRedirect.
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
index 6ec295f..1fd9f20 100644
--- a/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/settings/password_manager_presenter.cc
@@ -15,6 +15,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -22,6 +23,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/password_manager/account_storage/account_password_store_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/password_manager/password_store_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -236,7 +238,40 @@
   if (it == password_map_.end())
     return;
 
-  ChangeSavedPasswords(it->second, new_username, new_password);
+  const FormVector& old_forms = it->second;
+
+  // If a password was provided, make sure it is not empty.
+  if (new_password && new_password->empty()) {
+    DLOG(ERROR) << "The password is empty.";
+    return;
+  }
+
+  const std::string& signon_realm = old_forms[0]->signon_realm;
+  const base::string16& old_username = old_forms[0]->username_value;
+
+  // TODO(crbug.com/377410): Clean up this check for duplicates because a
+  // very similar one is in password_store_utils in EditSavedPasswords already.
+
+  // In case the username
+  // changed, make sure that there exists no other credential with the same
+  // signon_realm and username.
+  const bool username_changed = old_username != new_username;
+  if (username_changed) {
+    for (const auto& sort_key_passwords_pair : password_map_) {
+      for (const auto& password : sort_key_passwords_pair.second) {
+        if (password->signon_realm == signon_realm &&
+            password->username_value == new_username) {
+          DLOG(ERROR) << "A credential with the same signon_realm and username "
+                         "already exists.";
+          return;
+        }
+      }
+    }
+  }
+
+  EditSavedPasswords(password_view_->GetProfile(), old_forms, old_username,
+                     signon_realm, new_username,
+                     base::OptionalOrNullptr(new_password));
 }
 
 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) {
@@ -327,54 +362,6 @@
   store->RemoveLogin(form);
 }
 
-void PasswordManagerPresenter::ChangeSavedPasswords(
-    const FormVector& old_forms,
-    const base::string16& new_username,
-    const base::Optional<base::string16>& new_password) {
-  // If a password was provided, make sure it is not empty.
-  if (new_password && new_password->empty()) {
-    DLOG(ERROR) << "The password is empty.";
-    return;
-  }
-
-  DCHECK(!old_forms.empty());
-  const std::string& signon_realm = old_forms[0]->signon_realm;
-  const base::string16& old_username = old_forms[0]->username_value;
-
-  const bool username_changed = old_username != new_username;
-  // In case the username changed, make sure that there exists no other
-  // credential with the same signon_realm and username.
-  if (username_changed) {
-    for (const auto& sort_key_passwords_pair : password_map_) {
-      for (const auto& password : sort_key_passwords_pair.second) {
-        if (password->signon_realm == signon_realm &&
-            password->username_value == new_username) {
-          DLOG(ERROR) << "A credential with the same signon_realm and username "
-                         "already exists.";
-          return;
-        }
-      }
-    }
-  }
-
-  // An updated username implies a change in the primary key, thus we need to
-  // make sure to call the right API. Update every entry in the equivalence
-  // class.
-  for (const auto& old_form : old_forms) {
-    PasswordStore* store = GetPasswordStore(old_form->IsUsingAccountStore());
-    if (!store)
-      continue;
-
-    autofill::PasswordForm new_form = *old_form;
-    new_form.username_value = new_username;
-    if (new_password)
-      new_form.password_value = *new_password;
-
-    username_changed ? store->UpdateLoginWithPrimaryKey(new_form, *old_form)
-                     : store->UpdateLogin(new_form);
-  }
-}
-
 bool PasswordManagerPresenter::TryRemovePasswordEntries(
     PasswordFormMap* form_map,
     size_t index) {
diff --git a/chrome/browser/ui/passwords/settings/password_manager_presenter.h b/chrome/browser/ui/passwords/settings/password_manager_presenter.h
index fdd047f..28c7189 100644
--- a/chrome/browser/ui/passwords/settings/password_manager_presenter.h
+++ b/chrome/browser/ui/passwords/settings/password_manager_presenter.h
@@ -110,12 +110,6 @@
       std::map<std::string,
                std::vector<std::unique_ptr<autofill::PasswordForm>>>;
 
-  // Implementation used in both |ChangeSavedPassword()| methods.
-  void ChangeSavedPasswords(
-      const std::vector<std::unique_ptr<autofill::PasswordForm>>& old_forms,
-      const base::string16& new_username,
-      const base::Optional<base::string16>& new_password);
-
   // Attempts to remove the entries corresponding to |index| from |form_map|.
   // This will also add a corresponding undo operation to |undo_manager_|.
   // Returns whether removing the entry succeeded.
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index f4b4fb1..b8f539a 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -172,6 +172,7 @@
   BuildSyncInfo();
   BuildAutofillButtons();
   BuildAccountFeatureButtons();
+  BuildProfileHeading();
   BuildSelectableProfiles();
   BuildProfileFeatureButtons();
 }
@@ -487,6 +488,12 @@
   }
 }
 
+void ProfileMenuView::BuildProfileHeading() {
+  // TODO(crbug.com/995720): Update this string after approval from UX.
+  SetProfileHeading(
+      l10n_util::GetStringUTF16(IDS_PROFILES_MANAGE_USERS_BUTTON));
+}
+
 void ProfileMenuView::BuildSelectableProfiles() {
   auto profile_entries = g_browser_process->profile_manager()
                              ->GetProfileAttributesStorage()
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h
index bb313b6..81e4b61b 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -104,6 +104,7 @@
   void BuildAutofillButtons();
   void BuildSyncInfo();
   void BuildAccountFeatureButtons();
+  void BuildProfileHeading();
   void BuildSelectableProfiles();
   void BuildProfileFeatureButtons();
 
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index 8d982cc..2a7e9d5 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -331,6 +331,19 @@
   RegisterClickAction(button, std::move(action));
 }
 
+void ProfileMenuViewBase::SetProfileHeading(const base::string16& heading) {
+  profile_heading_container_->RemoveAllChildViews(/*delete_children=*/true);
+  profile_heading_container_->SetLayoutManager(
+      std::make_unique<views::FillLayout>());
+
+  views::Label* label =
+      profile_heading_container_->AddChildView(std::make_unique<views::Label>(
+          heading, views::style::CONTEXT_LABEL, STYLE_HINT));
+  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  label->SetHandlesTooltips(false);
+  label->SetBorder(views::CreateEmptyBorder(gfx::Insets(0, kMenuEdgeMargin)));
+}
+
 void ProfileMenuViewBase::AddSelectableProfile(const gfx::Image& image,
                                                const base::string16& name,
                                                base::RepeatingClosure action) {
@@ -487,6 +500,8 @@
   components->AddChildView(
       CreateBorderedBoxView(std::move(bordered_box_container)));
 
+  profile_heading_container_ =
+      components->AddChildView(std::make_unique<views::View>());
   selectable_profiles_container_ =
       components->AddChildView(std::make_unique<views::View>());
   profile_features_container_ =
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
index 06b07daf..bfabe0e 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -107,6 +107,7 @@
   void AddAccountFeatureButton(const gfx::ImageSkia& icon,
                                const base::string16& text,
                                base::RepeatingClosure action);
+  void SetProfileHeading(const base::string16& heading);
   void AddSelectableProfile(const gfx::Image& image,
                             const base::string16& name,
                             base::RepeatingClosure action);
@@ -223,6 +224,7 @@
   views::View* sync_info_container_ = nullptr;
   views::View* shortcut_features_container_ = nullptr;
   views::View* account_features_container_ = nullptr;
+  views::View* profile_heading_container_ = nullptr;
   views::View* selectable_profiles_container_ = nullptr;
   views::View* profile_features_container_ = nullptr;
 
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
index 7ee1f7d6..fed20ba5 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
@@ -23,9 +23,8 @@
 namespace {
 
 enum class DeviceIconType {
-  DESKTOP = 0,
-  PHONE = 1,
-  TOTAL_COUNT = 2  // Add new types above this line.
+  kDesktop = 0,
+  kPhone = 1,
 };
 
 SkColor GetColorfromTheme() {
@@ -38,14 +37,12 @@
 gfx::ImageSkia CreateDeviceIcon(DeviceIconType icon_type) {
   const gfx::VectorIcon* vector_icon;
   switch (icon_type) {
-    case DeviceIconType::DESKTOP:
+    case DeviceIconType::kDesktop:
       vector_icon = &kHardwareComputerIcon;
       break;
-    case DeviceIconType::PHONE:
+    case DeviceIconType::kPhone:
       vector_icon = &kHardwareSmartphoneIcon;
       break;
-    default:
-      vector_icon = &kSendTabToSelfIcon;
   }
 
   constexpr int kPrimaryIconSize = 20;
@@ -55,12 +52,9 @@
 
 std::unique_ptr<views::ImageView> CreateIconView(
     const sync_pb::SyncEnums::DeviceType device_type) {
-  gfx::ImageSkia image;
-  if (device_type == sync_pb::SyncEnums::TYPE_PHONE) {
-    image = CreateDeviceIcon(DeviceIconType::PHONE);
-  } else {
-    image = CreateDeviceIcon(DeviceIconType::DESKTOP);
-  }
+  gfx::ImageSkia image = CreateDeviceIcon(
+      device_type == sync_pb::SyncEnums::TYPE_PHONE ? DeviceIconType::kPhone
+                                                    : DeviceIconType::kDesktop);
   auto icon_view = std::make_unique<views::ImageView>();
   icon_view->SetImage(image);
   constexpr auto kPrimaryIconBorder = gfx::Insets(6);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 8eb94024..7afad9f5 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -802,8 +802,13 @@
 
 ToolbarActionView* ToolbarView::GetToolbarActionViewForId(
     const std::string& id) {
-  if (extensions_container_)
+  if (display_mode_ != DisplayMode::NORMAL)
+    return nullptr;
+  if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
+    DCHECK(extensions_container_);
     return extensions_container_->GetViewForId(id);
+  }
+  DCHECK(GetBrowserActionsContainer());
   return GetBrowserActionsContainer()->GetViewForId(id);
 }
 
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc
index 29dffc2..12a05bf 100644
--- a/chrome/browser/ui/webui/discards/discards_ui.cc
+++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -39,7 +39,6 @@
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "url/gurl.h"
 #include "url/origin.h"
diff --git a/chrome/browser/ui/webui/management_ui_handler.cc b/chrome/browser/ui/webui/management_ui_handler.cc
index a54f45d4..2477b31 100644
--- a/chrome/browser/ui/webui/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management_ui_handler.cc
@@ -410,8 +410,7 @@
   RemoveObservers();
 }
 
-void ManagementUIHandler::AddExtensionReportingInfo(
-    base::Value* report_sources) {
+void ManagementUIHandler::AddReportingInfo(base::Value* report_sources) {
   const extensions::Extension* cloud_reporting_extension =
       GetEnabledExtension(kCloudReportingExtensionId);
 
@@ -439,6 +438,15 @@
 
   const bool cloud_reporting_extension_installed =
       cloud_reporting_extension != nullptr;
+  const auto* cloud_reporting_policy_value =
+      GetPolicyService()
+          ->GetPolicies(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
+                                                std::string()))
+          .GetValue(policy::key::kCloudReportingEnabled);
+  const bool cloud_reporting_policy_enabled =
+      cloud_reporting_policy_value && cloud_reporting_policy_value->is_bool() &&
+      cloud_reporting_policy_value->GetBool();
+
   const struct {
     const char* policy_key;
     const char* message;
@@ -446,22 +454,25 @@
     const bool enabled_by_default;
   } report_definitions[] = {
       {kPolicyKeyReportMachineIdData, kManagementExtensionReportMachineName,
-       ReportingType::kDevice, cloud_reporting_extension_installed},
+       ReportingType::kDevice,
+       cloud_reporting_extension_installed || cloud_reporting_policy_enabled},
       {kPolicyKeyReportMachineIdData,
        kManagementExtensionReportMachineNameAddress, ReportingType::kDevice,
        false},
       {kPolicyKeyReportVersionData, kManagementExtensionReportVersion,
-       ReportingType::kDevice, cloud_reporting_extension_installed},
+       ReportingType::kDevice,
+       cloud_reporting_extension_installed || cloud_reporting_policy_enabled},
       {kPolicyKeyReportSystemTelemetryData, kManagementExtensionReportPerfCrash,
        ReportingType::kDevice, false},
       {kPolicyKeyReportUserIdData, kManagementExtensionReportUsername,
-       ReportingType::kUser, cloud_reporting_extension_installed},
+       ReportingType::kUser,
+       cloud_reporting_extension_installed || cloud_reporting_policy_enabled},
       {kPolicyKeyReportSafeBrowsingData,
        kManagementExtensionReportSafeBrowsingWarnings, ReportingType::kSecurity,
        cloud_reporting_extension_installed},
       {kPolicyKeyReportExtensionsData,
        kManagementExtensionReportExtensionsPlugin, ReportingType::kExtensions,
-       cloud_reporting_extension_installed},
+       cloud_reporting_extension_installed || cloud_reporting_policy_enabled},
       {kPolicyKeyReportUserBrowsingData,
        kManagementExtensionReportUserBrowsingData, ReportingType::kUserActivity,
        false},
@@ -825,14 +836,14 @@
     const base::ListValue* args) {
   base::Value report_sources(base::Value::Type::LIST);
   AllowJavascript();
-  AddExtensionReportingInfo(&report_sources);
+  AddReportingInfo(&report_sources);
   ResolveJavascriptCallback(args->GetList()[0] /* callback_id */,
                             report_sources);
 }
 
 void ManagementUIHandler::NotifyBrowserReportingInfoUpdated() {
   base::Value report_sources(base::Value::Type::LIST);
-  AddExtensionReportingInfo(&report_sources);
+  AddReportingInfo(&report_sources);
   FireWebUIListener("browser-reporting-info-updated", report_sources);
 }
 
diff --git a/chrome/browser/ui/webui/management_ui_handler.h b/chrome/browser/ui/webui/management_ui_handler.h
index f06e8d6..78fc6f5 100644
--- a/chrome/browser/ui/webui/management_ui_handler.h
+++ b/chrome/browser/ui/webui/management_ui_handler.h
@@ -113,7 +113,7 @@
   static void InitializeInternal(content::WebUI* web_ui,
                                  content::WebUIDataSource* source,
                                  Profile* profile);
-  void AddExtensionReportingInfo(base::Value* report_sources);
+  void AddReportingInfo(base::Value* report_sources);
 
   base::DictionaryValue GetContextualManagedData(Profile* profile);
   base::Value GetThreatProtectionInfo(Profile* profile) const;
diff --git a/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
index 9c7e64e6..c9621a6f 100644
--- a/chrome/browser/ui/webui/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -61,7 +61,7 @@
 
   base::Value GetExtensionReportingInfo() {
     base::Value report_sources(base::Value::Type::LIST);
-    AddExtensionReportingInfo(&report_sources);
+    AddReportingInfo(&report_sources);
     return report_sources;
   }
 
@@ -565,6 +565,31 @@
   EXPECT_EQ(reporting_info.GetList().size(), expected_messages.size());
 }
 
+TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) {
+  handler_.EnableCloudReportingExtension(false);
+
+  policy::PolicyMap chrome_policies;
+  const policy::PolicyNamespace chrome_policies_namespace =
+      policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string());
+  EXPECT_CALL(policy_service_, GetPolicies(_))
+      .WillRepeatedly(ReturnRef(chrome_policies));
+  SetPolicyValue(policy::key::kCloudReportingEnabled, chrome_policies, true);
+
+  std::set<std::string> expected_messages = {
+      kManagementExtensionReportMachineName, kManagementExtensionReportUsername,
+      kManagementExtensionReportVersion,
+      kManagementExtensionReportExtensionsPlugin};
+
+  auto reporting_info = handler_.GetExtensionReportingInfo();
+  const auto& reporting_info_list = reporting_info.GetList();
+
+  for (const base::Value& info : reporting_info_list) {
+    const std::string* messageId = info.FindStringKey("messageId");
+    EXPECT_TRUE(expected_messages.find(*messageId) != expected_messages.end());
+  }
+  EXPECT_EQ(reporting_info.GetList().size(), expected_messages.size());
+}
+
 TEST_F(ManagementUIHandlerTests, ExtensionReportingInfoPoliciesMerge) {
   policy::PolicyMap on_prem_reporting_extension_beta_policies;
   policy::PolicyMap on_prem_reporting_extension_stable_policies;
@@ -603,6 +628,11 @@
   EXPECT_CALL(policy_service_,
               GetPolicies(on_prem_reporting_extension_beta_policy_namespace))
       .WillOnce(ReturnRef(on_prem_reporting_extension_beta_policies));
+  policy::PolicyMap empty_policy_map;
+  EXPECT_CALL(policy_service_,
+              GetPolicies(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
+                                                  std::string())))
+      .WillOnce(ReturnRef(empty_policy_map));
 
   handler_.EnableCloudReportingExtension(true);
 
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc
index 200602b1..35f8902 100644
--- a/chrome/browser/ui/webui/memory_internals_ui.cc
+++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -33,14 +33,12 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "content/public/common/process_type.h"
 #include "mojo/public/cpp/system/platform_handle.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "ui/shell_dialogs/select_file_policy.h"
 
@@ -269,7 +267,6 @@
     supervisor->StartManualProfiling(pid);
   } else {
     supervisor->Start(
-        content::GetSystemConnector(),
         base::BindOnce(&heap_profiling::Supervisor::StartManualProfiling,
                        base::Unretained(supervisor), pid));
   }
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index 3c79b2d..33b6ceeed 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -58,6 +58,7 @@
   "+rlz/buildflags/buildflags.h",
   "+sandbox/linux/services/credentials.h",
   "+services/network/public/cpp",
+  "+services/network/public/mojom",
   "+third_party/blink/public/mojom",
   "+third_party/boringssl/src/include",
   "+third_party/metrics_proto",  # For heap profiler test.
diff --git a/chrome/common/google_url_loader_throttle.cc b/chrome/common/google_url_loader_throttle.cc
index 3ce38cb..0a565575 100644
--- a/chrome/common/google_url_loader_throttle.cc
+++ b/chrome/common/google_url_loader_throttle.cc
@@ -7,6 +7,7 @@
 #include "chrome/common/net/safe_search_util.h"
 #include "components/variations/net/variations_http_headers.h"
 #include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "extensions/common/extension_urls.h"
@@ -63,7 +64,8 @@
     bool* /* defer */,
     std::vector<std::string>* to_be_removed_headers,
     net::HttpRequestHeaders* modified_headers) {
-  variations::RemoveVariationsHeaderIfNeeded(*redirect_info, response_head,
+  network::mojom::URLResponseHeadPtr response_head_ptr = response_head;
+  variations::RemoveVariationsHeaderIfNeeded(*redirect_info, *response_head_ptr,
                                              to_be_removed_headers);
 
   // URLLoaderThrottles can only change the redirect URL when the network
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh
index 306b59c..15f9b02 100755
--- a/chrome/installer/linux/debian/build.sh
+++ b/chrome/installer/linux/debian/build.sh
@@ -153,15 +153,15 @@
   case $CHANNEL in
     stable )
       CHANNEL=stable
-      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Stable%20updates"
+      RELEASENOTES="https://chromereleases.googleblog.com/search/label/Stable%20updates"
       ;;
-    unstable|dev|alpha )
-      CHANNEL=unstable
-      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Dev%20updates"
-      ;;
-    testing|beta )
+    beta|testing )
       CHANNEL=beta
-      RELEASENOTES="http://googlechromereleases.blogspot.com/search/label/Beta%20updates"
+      RELEASENOTES="https://chromereleases.googleblog.com/search/label/Beta%20updates"
+      ;;
+    dev|unstable|alpha )
+      CHANNEL=unstable
+      RELEASENOTES="https://chromereleases.googleblog.com/search/label/Dev%20updates"
       ;;
     * )
       echo
diff --git a/chrome/lib/image_fetcher/OWNERS b/chrome/lib/image_fetcher/OWNERS
deleted file mode 100644
index 833f4d66..0000000
--- a/chrome/lib/image_fetcher/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/image_fetcher/OWNERS
diff --git a/chrome/lib/image_fetcher/public/android/BUILD.gn b/chrome/lib/image_fetcher/public/android/BUILD.gn
deleted file mode 100644
index bf0d11d..0000000
--- a/chrome/lib/image_fetcher/public/android/BUILD.gn
+++ /dev/null
@@ -1,31 +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.
-
-import("//build/config/android/rules.gni")
-
-android_library("java") {
-  deps = [
-    "//base:base_java",
-    "//chrome/android/public/profiles:java",
-    "//chrome/lib/util/public/android:java",
-    "//content/public/android:content_java",
-    "//third_party/gif_player:gif_player_java",
-  ]
-  java_files = [
-    "java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java",
-    "java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
-    "java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java",
-    "java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java",
-    "java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java",
-    "java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java",
-  ]
-
-  srcjar_deps = [ "//components/image_fetcher/core:java_enums_srcjar" ]
-}
-
-generate_jni("jni_headers") {
-  sources = [
-    "java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
-  ]
-}
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index c868507..3b74dd9b 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -110,7 +110,6 @@
 
 #if defined(OS_ANDROID)
 bool IsAutoFetchFeatureEnabled() {
-  // Disabled for touchless builds.
   return base::FeatureList::IsEnabled(features::kAutoFetchOnNetErrorPage) &&
          offline_pages::IsOfflinePagesEnabled();
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6b6f1691..05ffe31 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2848,6 +2848,7 @@
     "../browser/android/oom_intervention/near_oom_monitor_unittest.cc",
     "../browser/android/oom_intervention/oom_intervention_decider_unittest.cc",
     "../browser/android/password_ui_view_android_unittest.cc",
+    "../browser/android/password_update_delegate_unittest.cc",
     "../browser/android/preferences/pref_service_bridge_unittest.cc",
     "../browser/android/preferences/prefs_unittest.cc",
     "../browser/android/shortcut_info_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
index c718d72..3e9717d 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -49,8 +49,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.MenuUtils;
@@ -100,14 +98,6 @@
     @Rule
     private EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule();
 
-    public static ChromeActivityTestRule forMainActivity() {
-        if (FeatureUtilities.isNoTouchModeEnabled()) {
-            return new ChromeActivityTestRule(TouchlessDelegate.getNoTouchActivityClass());
-        } else {
-            return new ChromeActivityTestRule(ChromeTabbedActivity.class);
-        }
-    }
-
     public ChromeActivityTestRule(Class<T> activityClass) {
         this(activityClass, false);
     }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
index 1351be2..a156e15 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -22,7 +22,6 @@
 import org.chromium.base.test.util.RestrictionSkipCheck;
 import org.chromium.base.test.util.SkipCheck;
 import org.chromium.chrome.browser.ChromeVersionInfo;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.test.util.ChromeRestriction;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner;
@@ -208,9 +207,6 @@
                         restriction, ChromeRestriction.RESTRICTION_TYPE_VR_SETTINGS_SERVICE)) {
                 return !isVrSettingsServiceEnabled();
             }
-            if (TextUtils.equals(restriction, ChromeRestriction.RESTRICTION_TYPE_REQUIRES_TOUCH)) {
-                return FeatureUtilities.isNoTouchModeEnabled();
-            }
             return false;
         }
     }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeRestriction.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeRestriction.java
index c2031a7..62d8321 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeRestriction.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeRestriction.java
@@ -32,6 +32,4 @@
     public static final String RESTRICTION_TYPE_SVR = "Smartphone_VR";
     /** Specifies the test is only valid if the VR settings service is enabled */
     public static final String RESTRICTION_TYPE_VR_SETTINGS_SERVICE = "VR_Settings_Service";
-    /** Specifies the test is not valid on touchless devices. */
-    public static final String RESTRICTION_TYPE_REQUIRES_TOUCH = "Not_Touchless";
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
index ed3a9d11..4519b41 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
@@ -18,8 +18,6 @@
 import org.chromium.chrome.browser.suggestions.tile.TileSource;
 import org.chromium.chrome.browser.suggestions.tile.TileTitleSource;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.touchless.TouchlessDelegate;
-import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.test.util.AccountHolder;
 import org.chromium.components.signin.test.util.FakeAccountManagerDelegate;
@@ -48,9 +46,6 @@
             @Override
             public boolean isSatisfied() {
                 if (!tab.isIncognito()) {
-                    if (FeatureUtilities.isNoTouchModeEnabled()) {
-                        return TouchlessDelegate.isTouchlessNewTabPage(tab.getNativePage());
-                    }
                     // TODO(tedchoc): Make MostVisitedPage also have a isLoaded() concept.
                     if (tab.getNativePage() instanceof NewTabPage) {
                         return ((NewTabPage) tab.getNativePage()).isLoadedForTests();
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
index d04b0be..9ff7ab83 100644
--- a/chrome/test/data/autofill/captured_sites/testcases.json
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
@@ -156,9 +156,9 @@
     { "site_name": "verizonwireless", "expectation":"FAIL", "bug_number":996478 },
     { "site_name": "wiley", "expectation":"PASS", "disabled":true, "bug_number":1003044 },
     { "site_name": "zenni_optical", "expectation":"PASS" },
-    { "site_name": "accesscorrections", "expectation":"PASS", "disabled":true, "bug_number":993044 },
-    { "site_name": "jetspizza", "expectation":"PASS", "disabled":true, "bug_number":993044 },
-    { "site_name": "star_city_games", "expectation":"PASS", "disabled":true, "bug_number":993044 },
+    { "site_name": "accesscorrections", "expectation":"PASS" },
+    { "site_name": "jetspizza", "expectation":"PASS" },
+    { "site_name": "star_city_games", "expectation":"PASS" },
     { "site_name": "1aauto", "expectation":"PASS" },
     { "site_name": "abercrombie", "expectation":"PASS", "disabled":true, "bug_number":984664 },
     { "site_name": "barnes_and_noble", "expectation":"PASS", "disabled":true, "bug_number":984664 },
diff --git a/chrome/test/data/webui/settings/search_settings_test.js b/chrome/test/data/webui/settings/search_settings_test.js
index 971b59b..5fab6c8 100644
--- a/chrome/test/data/webui/settings/search_settings_test.js
+++ b/chrome/test/data/webui/settings/search_settings_test.js
@@ -268,5 +268,21 @@
       assertEquals(1, searchHits.length);
       assertEquals('Match', searchHits[0].textContent);
     });
+
+    test('associated control causes search highlight bubble', async () => {
+      document.body.innerHTML = `
+          <settings-section>
+            <button></button>
+            <settings-subpage>
+              hello
+            </settings-subpage>
+          </settings-section>`;
+      const subpage = document.querySelector('settings-subpage');
+      subpage.associatedControl = document.querySelector('button');
+
+      await searchManager.search('hello', document.body);
+
+      assertEquals(1, document.querySelectorAll('.search-bubble').length);
+    });
   });
 });
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.js b/chrome/test/data/webui/tab_strip/tab_list_test.js
index f5a6f2c..3bd318d 100644
--- a/chrome/test/data/webui/tab_strip/tab_list_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_list_test.js
@@ -6,6 +6,43 @@
 import {TabsApiProxy} from 'chrome://tab-strip/tabs_api_proxy.js';
 import {TestTabsApiProxy} from './test_tabs_api_proxy.js';
 
+class MockDataTransfer extends DataTransfer {
+  constructor() {
+    super();
+
+    this.dragImageData = {
+      image: undefined,
+      offsetX: undefined,
+      offsetY: undefined,
+    };
+
+    this.dropEffect_ = 'none';
+    this.effectAllowed_ = 'none';
+  }
+
+  get dropEffect() {
+    return this.dropEffect_;
+  }
+
+  set dropEffect(effect) {
+    this.dropEffect_ = effect;
+  }
+
+  get effectAllowed() {
+    return this.effectAllowed_;
+  }
+
+  set effectAllowed(effect) {
+    this.effectAllowed_ = effect;
+  }
+
+  setDragImage(image, offsetX, offsetY) {
+    this.dragImageData.image = image;
+    this.dragImageData.offsetX = offsetX;
+    this.dragImageData.offsetY = offsetY;
+  }
+}
+
 suite('TabList', () => {
   let callbackRouter;
   let optionsCalled;
@@ -294,4 +331,54 @@
     await tabList.animationPromises;
     assertEquals(fakeScroller.scrollLeft, activeTab.offsetLeft - scrollPadding);
   });
+
+  test('dragstart sets a drag image offset by the event coordinates', () => {
+    const draggedTab = getUnpinnedTabs()[0];
+    const mockDataTransfer = new MockDataTransfer();
+    const dragStartEvent = new DragEvent('dragstart', {
+      bubbles: true,
+      composed: true,
+      clientX: 100,
+      clientY: 150,
+      dataTransfer: mockDataTransfer,
+    });
+    draggedTab.dispatchEvent(dragStartEvent);
+    assertEquals(dragStartEvent.dataTransfer.effectAllowed, 'move');
+    assertEquals(
+        mockDataTransfer.dragImageData.image, draggedTab.getDragImage());
+    assertEquals(
+        mockDataTransfer.dragImageData.offsetX, 100 - draggedTab.offsetLeft);
+    assertEquals(
+        mockDataTransfer.dragImageData.offsetY, 150 - draggedTab.offsetTop);
+  });
+
+  test('dragover moves tabs', async () => {
+    const draggedIndex = 0;
+    const dragOverIndex = 1;
+    const draggedTab = getUnpinnedTabs()[draggedIndex];
+    const dragOverTab = getUnpinnedTabs()[dragOverIndex];
+    const mockDataTransfer = new MockDataTransfer();
+
+    // Dispatch a dragstart event to start the drag process
+    const dragStartEvent = new DragEvent('dragstart', {
+      bubbles: true,
+      composed: true,
+      clientX: 100,
+      clientY: 150,
+      dataTransfer: mockDataTransfer,
+    });
+    draggedTab.dispatchEvent(dragStartEvent);
+
+    // Move the draggedTab over the 2nd tab
+    const dragOverEvent = new DragEvent('dragover', {
+      bubbles: true,
+      composed: true,
+      dataTransfer: mockDataTransfer,
+    });
+    dragOverTab.dispatchEvent(dragOverEvent);
+    assertEquals(dragOverEvent.dataTransfer.dropEffect, 'move');
+    const [tabId, newIndex] = await testTabsApiProxy.whenCalled('moveTab');
+    assertEquals(tabId, currentWindow.tabs[draggedIndex].id);
+    assertEquals(newIndex, dragOverIndex);
+  });
 });
diff --git a/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js b/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js
index a681846a..b495bfe 100644
--- a/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js
+++ b/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+GEN('#include "services/network/public/cpp/features.h"');
+
 var TabStripBrowserTest = class extends testing.Test {
   get isAsync() {
     return true;
@@ -21,6 +23,11 @@
   get runAccessibilityChecks() {
     return false;
   }
+
+  /** @override */
+  get featureList() {
+    return {enabled: ['network::features::kOutOfBlinkCors']};
+  }
 };
 
 var TabStripTabListTest = class extends TabStripBrowserTest {
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js
index 9cb9ba2..c873d63 100644
--- a/chrome/test/data/webui/tab_strip/tab_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -103,4 +103,17 @@
         faviconElement.style.backgroundImage,
         getFaviconForPageURL(expectedPageUrl, false));
   });
+
+  test('setting dragging state toggles an attribute', () => {
+    tabElement.setDragging(true);
+    assertTrue(tabElement.hasAttribute('dragging'));
+    tabElement.setDragging(false);
+    assertFalse(tabElement.hasAttribute('dragging'));
+  });
+
+  test('getting the drag image grabs the contents', () => {
+    assertEquals(
+        tabElement.getDragImage(),
+        tabElement.shadowRoot.querySelector('#dragImage'));
+  });
 });
diff --git a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
index 843c95d..7edcbba 100644
--- a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
+++ b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
@@ -26,6 +26,7 @@
       'activateTab',
       'closeTab',
       'getCurrentWindow',
+      'moveTab',
     ]);
 
     this.callbackRouter = {
@@ -54,6 +55,11 @@
     return Promise.resolve(this.currentWindow_);
   }
 
+  moveTab(tabId, newIndex) {
+    this.methodCalled('moveTab', [tabId, newIndex]);
+    return Promise.resolve();
+  }
+
   setCurrentWindow(currentWindow) {
     this.currentWindow_ = currentWindow;
   }
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index e1cb436..8947457 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -60,7 +60,6 @@
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
@@ -719,7 +718,7 @@
       heap_profiling::Supervisor::GetInstance();
   supervisor->SetClientConnectionManagerConstructor(
       &CreateClientConnectionManager);
-  supervisor->Start(content::GetSystemConnector(), base::NullCallback());
+  supervisor->Start(base::NullCallback());
 #endif  // !defined(OS_FUCHSIA)
 }
 
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 15430db..1e14cb01 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -210,6 +210,7 @@
     "//chromeos/dbus/biod:test_support",
     "//chromeos/dbus/cryptohome",
     "//chromeos/dbus/cryptohome:attestation_proto",
+    "//chromeos/dbus/dlcservice:test_support",
     "//chromeos/dbus/power:power_manager_proto",
     "//chromeos/dbus/power:test_support",
     "//chromeos/dbus/session_manager",
diff --git a/chromeos/dbus/dlcservice/BUILD.gn b/chromeos/dbus/dlcservice/BUILD.gn
new file mode 100644
index 0000000..b98070f7
--- /dev/null
+++ b/chromeos/dbus/dlcservice/BUILD.gn
@@ -0,0 +1,57 @@
+# 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/protobuf/proto_library.gni")
+
+assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
+
+component("dlcservice") {
+  defines = [ "IS_DLCSERVICE_CLIENT_IMPL" ]
+
+  public_deps = [
+    ":dlcservice_proto",
+    "//chromeos/dbus:common",
+    "//chromeos/dbus:dbus",
+  ]
+
+  deps = [
+    "//base",
+    "//dbus",
+  ]
+
+  sources = [
+    "dlcservice_client.cc",
+    "dlcservice_client.h",
+    "fake_dlcservice_client.cc",
+    "fake_dlcservice_client.h",
+  ]
+}
+
+source_set("test_support") {
+  testonly = true
+
+  public_deps = [
+    ":dlcservice",
+  ]
+  deps = [
+    ":dlcservice_proto",
+    "//base",
+    "//base/test:test_support",
+    "//dbus:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+
+  sources = [
+    "dlcservice_client_unittest.cc",
+  ]
+}
+
+proto_library("dlcservice_proto") {
+  sources = [
+    "//third_party/cros_system_api/dbus/dlcservice/dlcservice.proto",
+  ]
+
+  proto_out_dir = "chromeos/dbus/dlcservice"
+}
diff --git a/chromeos/dbus/dlcservice/dlcservice_client.cc b/chromeos/dbus/dlcservice/dlcservice_client.cc
new file mode 100644
index 0000000..24fc7745
--- /dev/null
+++ b/chromeos/dbus/dlcservice/dlcservice_client.cc
@@ -0,0 +1,362 @@
+// 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 "chromeos/dbus/dlcservice/dlcservice_client.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <deque>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/dbus/constants/dbus_switches.h"
+#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_path.h"
+#include "dbus/object_proxy.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+
+const char kOnInstallStatus[] = "OnInstallStatus";
+
+DlcserviceClient* g_instance = nullptr;
+
+class DlcserviceErrorResponseHandler {
+ public:
+  explicit DlcserviceErrorResponseHandler(dbus::ErrorResponse* err_response)
+      : err(dlcservice::kErrorInternal) {
+    if (err_response && dbus::MessageReader(err_response).PopString(&err_msg) &&
+        DlcserviceErrorFromString(err_msg, &err)) {
+      VLOG(1) << "Handling error response err=" << err
+              << " err_msg=" << err_msg;
+    } else {
+      LOG(ERROR) << "Failed to set err based on error response "
+                 << "defaulted to kErrorInternal.";
+    }
+  }
+
+  ~DlcserviceErrorResponseHandler() = default;
+
+  std::string get_err() { return err; }
+
+  std::string get_err_msg() { return err_msg; }
+
+ private:
+  bool DlcserviceErrorFromString(const std::string& err_msg, std::string* err) {
+    static const base::NoDestructor<std::unordered_set<std::string>> err_set({
+        dlcservice::kErrorNone,
+        dlcservice::kErrorInternal,
+        dlcservice::kErrorBusy,
+        dlcservice::kErrorNeedReboot,
+        dlcservice::kErrorInvalidDlc,
+    });
+    static const std::pair<std::string, std::string> delims = {"dlcservice/",
+                                                               ":"};
+
+    if (!err) {
+      LOG(ERROR) << "err passed is nullptr.";
+      return false;
+    }
+
+    // Clear to empty out |err|.
+    err->clear();
+
+    // Verify dlcservice error code.
+    if (err_msg.find(delims.first) == std::string::npos) {
+      LOG(ERROR) << "Dlcservice did not send valid error message: " << err_msg;
+      *err = dlcservice::kErrorInternal;
+      return true;
+    }
+
+    // Extract the dlcservice error code.
+    size_t padding = delims.first.size();
+    size_t second_idx = err_msg.find(delims.second, padding);
+    *err = err_msg.substr(padding, second_idx - padding);
+
+    // Lookup the dlcservice error code and provide default on failure.
+    auto itr = err_set->find(*err);
+    *err = itr != err_set->end() ? *itr : dlcservice::kErrorInternal;
+    return true;
+  }
+
+  // Holds the dlcservice specific error.
+  std::string err;
+
+  // Holds the entire error message from error response.
+  std::string err_msg;
+
+  DISALLOW_COPY_AND_ASSIGN(DlcserviceErrorResponseHandler);
+};
+
+}  // namespace
+
+// The DlcserviceClient implementation used in production.
+class DlcserviceClientImpl : public DlcserviceClient {
+ public:
+  DlcserviceClientImpl() : dlcservice_proxy_(nullptr) {}
+
+  ~DlcserviceClientImpl() override = default;
+
+  void Install(const dlcservice::DlcModuleList& dlc_module_list,
+               InstallCallback callback) override {
+    if (!service_available_) {
+      pending_tasks_.emplace_back(base::BindOnce(
+          &DlcserviceClientImpl::Install, weak_ptr_factory_.GetWeakPtr(),
+          std::move(dlc_module_list), std::move(callback)));
+      return;
+    }
+
+    if (install_callback_holder_.has_value()) {
+      pending_installs_.emplace_back(base::BindOnce(
+          &DlcserviceClientImpl::Install, weak_ptr_factory_.GetWeakPtr(),
+          std::move(dlc_module_list), std::move(callback)));
+      return;
+    }
+
+    dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                                 dlcservice::kInstallMethod);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendProtoAsArrayOfBytes(dlc_module_list);
+
+    install_callback_holder_ = std::move(callback);
+
+    VLOG(1) << "Requesting to install DLC(s).";
+    dlcservice_proxy_->CallMethodWithErrorResponse(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&DlcserviceClientImpl::OnInstall,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  void Uninstall(const std::string& dlc_id,
+                 UninstallCallback callback) override {
+    if (!service_available_) {
+      pending_tasks_.emplace_back(base::BindOnce(
+          &DlcserviceClientImpl::Uninstall, weak_ptr_factory_.GetWeakPtr(),
+          dlc_id, std::move(callback)));
+      return;
+    }
+
+    dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                                 dlcservice::kUninstallMethod);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendString(dlc_id);
+
+    VLOG(1) << "Requesting to uninstall DLC=" << dlc_id;
+    dlcservice_proxy_->CallMethodWithErrorResponse(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&DlcserviceClientImpl::OnUninstall,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void GetInstalled(GetInstalledCallback callback) override {
+    if (!service_available_) {
+      pending_tasks_.emplace_back(
+          base::BindOnce(&DlcserviceClientImpl::GetInstalled,
+                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+      return;
+    }
+
+    dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                                 dlcservice::kGetInstalledMethod);
+
+    VLOG(1) << "Requesting to get installed DLC(s).";
+    dlcservice_proxy_->CallMethodWithErrorResponse(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&DlcserviceClientImpl::OnGetInstalled,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void Init(dbus::Bus* bus) {
+    dlcservice_proxy_ = bus->GetObjectProxy(
+        dlcservice::kDlcServiceServiceName,
+        dbus::ObjectPath(dlcservice::kDlcServiceServicePath));
+    // TODO(kimjae): Use from cros_system_api the const once sync'ed for
+    // kOnInstallStatus as dlcservice::kOnInstallStatus and delete the
+    // definition of kOnInstallStatus.
+    dlcservice_proxy_->ConnectToSignal(
+        dlcservice::kDlcServiceInterface, kOnInstallStatus,
+        base::Bind(&DlcserviceClientImpl::OnInstallStatus,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&DlcserviceClientImpl::OnInstallStatusConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
+  }
+
+ private:
+  void OnInstallStatus(dbus::Signal* signal) {
+    if (!install_callback_holder_.has_value())
+      return;
+
+    dlcservice::InstallStatus install_status;
+    if (!dbus::MessageReader(signal).PopArrayOfBytesAsProto(&install_status)) {
+      LOG(ERROR) << "Failed to parse proto as install status.";
+      return;
+    }
+
+    auto SendSignal = [this, &install_status]() {
+      base::Optional<InstallCallback> install_callback;
+      std::swap(install_callback, install_callback_holder_);
+      std::move(install_callback.value())
+          .Run(install_status.error_code(), install_status.dlc_module_list());
+    };
+
+    switch (install_status.status()) {
+      case dlcservice::Status::COMPLETED:
+        VLOG(1) << "DLC(s) install successful.";
+        SendSignal();
+        break;
+      case dlcservice::Status::RUNNING:
+        VLOG(2) << "Install in progress: " << install_status.progress();
+        // Need to return here since we don't want to try starting another
+        // pending install from the queue (would waste time checking).
+        return;
+      case dlcservice::Status::FAILED:
+        LOG(ERROR) << "Failed to install with error code: "
+                   << install_status.error_code();
+        SendSignal();
+        break;
+      default:
+        NOTREACHED();
+    }
+
+    // Try to run a pending install since we have complete/failed the current
+    // install, but do not waste trying to run a pending install when the
+    // current install is running at the moment.
+    if (!pending_installs_.empty()) {
+      std::move(pending_installs_.front()).Run();
+      pending_installs_.pop_front();
+    }
+  }
+
+  void OnInstallStatusConnected(const std::string& interface,
+                                const std::string& signal,
+                                bool success) {
+    // When the connected to dlcservice daemon's |OnInstallStatus| signal we can
+    // go ahead and mark the service as being available and not queue up tasks
+    // that came in before dlcservice daemon was available.
+    if (success) {
+      service_available_ = true;
+      std::vector<base::OnceClosure> callbacks;
+      callbacks.swap(pending_tasks_);
+      for (auto&& callback : callbacks) {
+        std::move(callback).Run();
+      }
+    } else {
+      LOG(ERROR) << "Failed to connect to install status signal.";
+      pending_tasks_.clear();
+    }
+  }
+
+  void OnInstall(dbus::Response* response, dbus::ErrorResponse* err_response) {
+    if (response)
+      return;
+
+    base::Optional<InstallCallback> install_callback;
+    std::swap(install_callback, install_callback_holder_);
+    std::move(install_callback.value())
+        .Run(DlcserviceErrorResponseHandler(err_response).get_err(),
+             dlcservice::DlcModuleList());
+  }
+
+  void OnUninstall(UninstallCallback callback,
+                   dbus::Response* response,
+                   dbus::ErrorResponse* err_response) {
+    if (response) {
+      std::move(callback).Run(dlcservice::kErrorNone);
+      return;
+    }
+
+    std::move(callback).Run(
+        DlcserviceErrorResponseHandler(err_response).get_err());
+  }
+
+  void OnGetInstalled(GetInstalledCallback callback,
+                      dbus::Response* response,
+                      dbus::ErrorResponse* err_response) {
+    dlcservice::DlcModuleList dlc_module_list;
+    if (response && dbus::MessageReader(response).PopArrayOfBytesAsProto(
+                        &dlc_module_list)) {
+      std::move(callback).Run(dlcservice::kErrorNone, dlc_module_list);
+      return;
+    }
+
+    std::move(callback).Run(
+        DlcserviceErrorResponseHandler(err_response).get_err(),
+        dlcservice::DlcModuleList());
+  }
+
+  dbus::ObjectProxy* dlcservice_proxy_;
+
+  // True after dlcservice's D-Bus service has become available.
+  bool service_available_ = false;
+
+  // The cached callback to call on a finished |Install()|.
+  base::Optional<InstallCallback> install_callback_holder_;
+
+  // A list of postponed calls to dlcservice to install only used after
+  // the dlcservice is already available.
+  std::deque<base::OnceClosure> pending_installs_;
+
+  // A list of postponed calls to dlcservice to be called after it becomes
+  // available.
+  std::vector<base::OnceClosure> pending_tasks_;
+
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate its weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<DlcserviceClientImpl> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(DlcserviceClientImpl);
+};
+
+DlcserviceClient::DlcserviceClient() {
+  CHECK(!g_instance);
+  g_instance = this;
+}
+
+DlcserviceClient::~DlcserviceClient() {
+  CHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+// static
+void DlcserviceClient::Initialize(dbus::Bus* bus) {
+  CHECK(bus);
+  (new DlcserviceClientImpl())->Init(bus);
+}
+
+// static
+void DlcserviceClient::InitializeFake() {
+  new FakeDlcserviceClient();
+}
+
+// static
+void DlcserviceClient::Shutdown() {
+  CHECK(g_instance);
+  delete g_instance;
+}
+
+// static
+DlcserviceClient* DlcserviceClient::Get() {
+  return g_instance;
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/dlcservice/dlcservice_client.h b/chromeos/dbus/dlcservice/dlcservice_client.h
new file mode 100644
index 0000000..160abde8
--- /dev/null
+++ b/chromeos/dbus/dlcservice/dlcservice_client.h
@@ -0,0 +1,84 @@
+// 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.
+
+#ifndef CHROMEOS_DBUS_DLCSERVICE_DLCSERVICE_CLIENT_H_
+#define CHROMEOS_DBUS_DLCSERVICE_DLCSERVICE_CLIENT_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/optional.h"
+#include "chromeos/dbus/dbus_client.h"
+#include "chromeos/dbus/dbus_client_implementation_type.h"
+#include "chromeos/dbus/dlcservice/dlcservice.pb.h"
+#include "dbus/message.h"
+#include "third_party/cros_system_api/dbus/dlcservice/dbus-constants.h"
+
+namespace chromeos {
+
+// DlcserviceClient is used to communicate with the dlcservice daemon which
+// manages DLC (Downloadable Content) modules. DlcserviceClient will allow for
+// CrOS features to be installed and uninstalled at runtime of the system. If
+// more details about dlcservice are required, please consult
+// https://chromium.git.corp.google.com/chromiumos/platform2/+/HEAD/dlcservice
+class COMPONENT_EXPORT(DLCSERVICE_CLIENT) DlcserviceClient {
+ public:
+  // The callback used for |Install()|, if the error is something other than
+  // |dlcservice::kErrorNone| the call has failed. For large DLC(s) to install,
+  // there may be delay between the time of this call and the callback being
+  // invoked.
+  using InstallCallback = base::OnceCallback<void(
+      const std::string& err,
+      const dlcservice::DlcModuleList& dlc_module_list)>;
+
+  // The callback used for |Uninstall()|, if the error is something other than
+  // |dlcservice::kErrorNone| the call has failed.
+  using UninstallCallback = base::OnceCallback<void(const std::string& err)>;
+
+  // The callback used for |GetInstalled()|, if the error is something other
+  // than |dlcservice::kErrorNone| the call has failed. It is very rare case for
+  // |GetInstalled()| call to fail.
+  using GetInstalledCallback = base::OnceCallback<void(
+      const std::string& err,
+      const dlcservice::DlcModuleList& dlc_module_list)>;
+
+  virtual void Install(const dlcservice::DlcModuleList& dlc_module_list,
+                       InstallCallback callback) = 0;
+
+  virtual void Uninstall(const std::string& dlc_id,
+                         UninstallCallback callback) = 0;
+
+  virtual void GetInstalled(GetInstalledCallback callback) = 0;
+
+  // Creates and initializes the global instance. |bus| must not be nullptr.
+  static void Initialize(dbus::Bus* bus);
+
+  // Creates and initializes a fake global instance if not already created.
+  static void InitializeFake();
+
+  // Destroys the global instance.
+  static void Shutdown();
+
+  // Returns the global instance which may be nullptr if not initialized.
+  static DlcserviceClient* Get();
+
+ protected:
+  friend class DlcserviceClientTest;
+
+  // Initialize/Shutdown should be used instead.
+  DlcserviceClient();
+  virtual ~DlcserviceClient();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DlcserviceClient);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_DLCSERVICE_DLCSERVICE_CLIENT_H_
diff --git a/chromeos/dbus/dlcservice/dlcservice_client_unittest.cc b/chromeos/dbus/dlcservice/dlcservice_client_unittest.cc
new file mode 100644
index 0000000..3cd0488
--- /dev/null
+++ b/chromeos/dbus/dlcservice/dlcservice_client_unittest.cc
@@ -0,0 +1,162 @@
+// 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 "chromeos/dbus/dlcservice/dlcservice_client.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "dbus/mock_bus.h"
+#include "dbus/mock_object_proxy.h"
+#include "dbus/object_path.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::WithArg;
+
+namespace chromeos {
+
+class DlcserviceClientTest : public testing::Test {
+ public:
+  void SetUp() override {
+    dbus::Bus::Options options;
+    options.bus_type = dbus::Bus::SYSTEM;
+
+    mock_bus_ = base::MakeRefCounted<::testing::NiceMock<dbus::MockBus>>(
+        dbus::Bus::Options());
+
+    mock_proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>(
+        mock_bus_.get(), dlcservice::kDlcServiceServiceName,
+        dbus::ObjectPath(dlcservice::kDlcServiceServicePath));
+
+    EXPECT_CALL(
+        *mock_bus_.get(),
+        GetObjectProxy(dlcservice::kDlcServiceServiceName,
+                       dbus::ObjectPath(dlcservice::kDlcServiceServicePath)))
+        .WillOnce(Return(mock_proxy_.get()));
+
+    EXPECT_CALL(*mock_proxy_.get(),
+                DoConnectToSignal(dlcservice::kDlcServiceInterface, _, _, _))
+        .WillOnce(Invoke(this, &DlcserviceClientTest::ConnectToSignal));
+
+    EXPECT_CALL(*mock_proxy_.get(), DoCallMethodWithErrorResponse(_, _, _))
+        .WillOnce(
+            Invoke(this, &DlcserviceClientTest::CallMethodWithErrorResponse));
+
+    DlcserviceClient::Initialize(mock_bus_.get());
+    client_ = DlcserviceClient::Get();
+
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void TearDown() override { DlcserviceClient::Shutdown(); }
+
+ protected:
+  base::test::SingleThreadTaskEnvironment task_environment_;
+  DlcserviceClient* client_;
+  scoped_refptr<dbus::MockBus> mock_bus_;
+  scoped_refptr<dbus::MockObjectProxy> mock_proxy_;
+  std::unique_ptr<dbus::Response> response_;
+  std::unique_ptr<dbus::ErrorResponse> err_response_;
+
+ private:
+  void ConnectToSignal(
+      const std::string& interface_name,
+      const std::string& signal_name,
+      dbus::ObjectProxy::SignalCallback signal_callback,
+      dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
+    EXPECT_EQ(interface_name, dlcservice::kDlcServiceInterface);
+    task_environment_.GetMainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(*on_connected_callback), interface_name,
+                       signal_name, true /* success */));
+  }
+
+  void CallMethodWithErrorResponse(
+      dbus::MethodCall* method_call,
+      int timeout_ms,
+      dbus::ObjectProxy::ResponseOrErrorCallback* callback) {
+    task_environment_.GetMainThreadTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(*callback), response_.get(),
+                                  err_response_.get()));
+  }
+};
+
+TEST_F(DlcserviceClientTest, GetInstalledSuccessTest) {
+  response_ = dbus::Response::CreateEmpty();
+  dbus::MessageWriter writer(response_.get());
+  dlcservice::DlcModuleList dlc_module_list;
+  writer.AppendProtoAsArrayOfBytes(dlc_module_list);
+
+  DlcserviceClient::GetInstalledCallback callback = base::BindOnce(
+      [](const std::string& err, const dlcservice::DlcModuleList&) {
+        EXPECT_EQ(dlcservice::kErrorNone, err);
+      });
+  client_->GetInstalled(std::move(callback));
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(DlcserviceClientTest, GetInstalledFailureTest) {
+  dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                               dlcservice::kGetInstalledMethod);
+  method_call.SetSerial(123);
+  err_response_ = dbus::ErrorResponse::FromMethodCall(
+      &method_call, DBUS_ERROR_FAILED, "dlcservice/INTERNAL:msg");
+
+  DlcserviceClient::GetInstalledCallback callback = base::BindOnce(
+      [](const std::string& err, const dlcservice::DlcModuleList&) {
+        EXPECT_EQ(dlcservice::kErrorInternal, err);
+      });
+  client_->GetInstalled(std::move(callback));
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(DlcserviceClientTest, UninstallSuccessTest) {
+  response_ = dbus::Response::CreateEmpty();
+
+  DlcserviceClient::UninstallCallback callback = base::BindOnce(
+      [](const std::string& err) { EXPECT_EQ(dlcservice::kErrorNone, err); });
+  client_->Uninstall("some-dlc-id", std::move(callback));
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(DlcserviceClientTest, UninstallFailureTest) {
+  dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                               dlcservice::kUninstallMethod);
+  method_call.SetSerial(123);
+  err_response_ = dbus::ErrorResponse::FromMethodCall(
+      &method_call, DBUS_ERROR_FAILED, "dlcservice/INTERNAL:msg");
+
+  DlcserviceClient::UninstallCallback callback =
+      base::BindOnce([](const std::string& err) {
+        EXPECT_EQ(dlcservice::kErrorInternal, err);
+      });
+  client_->Uninstall("some-dlc-id", std::move(callback));
+  base::RunLoop().RunUntilIdle();
+}
+
+// TODO(kimjae): Add test for |DlcserviceClient::Install()|.
+
+TEST_F(DlcserviceClientTest, InstallFailureTest) {
+  dbus::MethodCall method_call(dlcservice::kDlcServiceInterface,
+                               dlcservice::kInstallMethod);
+  method_call.SetSerial(123);
+  err_response_ = dbus::ErrorResponse::FromMethodCall(
+      &method_call, DBUS_ERROR_FAILED, "dlcservice/INTERNAL:msg");
+
+  DlcserviceClient::InstallCallback callback = base::BindOnce(
+      [](const std::string& err, const dlcservice::DlcModuleList&) {
+        EXPECT_EQ(dlcservice::kErrorInternal, err);
+      });
+  client_->Install(dlcservice::DlcModuleList(), std::move(callback));
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/dlcservice/fake_dlcservice_client.cc b/chromeos/dbus/dlcservice/fake_dlcservice_client.cc
new file mode 100644
index 0000000..7fda69d
--- /dev/null
+++ b/chromeos/dbus/dlcservice/fake_dlcservice_client.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace chromeos {
+
+FakeDlcserviceClient::FakeDlcserviceClient() = default;
+
+FakeDlcserviceClient::~FakeDlcserviceClient() = default;
+
+void FakeDlcserviceClient::Install(
+    const dlcservice::DlcModuleList& dlc_module_list,
+    InstallCallback callback) {
+  VLOG(1) << "Requesting to install DLC(s).";
+  std::move(callback).Run(dlcservice::kErrorNone, dlcservice::DlcModuleList());
+}
+
+void FakeDlcserviceClient::Uninstall(const std::string& dlc_id,
+                                     UninstallCallback callback) {
+  VLOG(1) << "Requesting to uninstall DLC=" << dlc_id;
+  std::move(callback).Run(dlcservice::kErrorNone);
+}
+
+void FakeDlcserviceClient::GetInstalled(GetInstalledCallback callback) {
+  VLOG(1) << "Requesting to get installed DLC(s).";
+  std::move(callback).Run(dlcservice::kErrorNone, dlcservice::DlcModuleList());
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/dlcservice/fake_dlcservice_client.h b/chromeos/dbus/dlcservice/fake_dlcservice_client.h
new file mode 100644
index 0000000..147ebcf
--- /dev/null
+++ b/chromeos/dbus/dlcservice/fake_dlcservice_client.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_DLCSERVICE_FAKE_DLCSERVICE_CLIENT_H_
+#define CHROMEOS_DBUS_DLCSERVICE_FAKE_DLCSERVICE_CLIENT_H_
+
+#include <string>
+
+#include "base/component_export.h"
+#include "base/containers/queue.h"
+#include "chromeos/dbus/dlcservice/dlcservice_client.h"
+
+namespace chromeos {
+
+// A fake implementation of DlcserviceClient. The user of this class can
+// use set_update_engine_client_status() to set a fake last Status and
+// GetLastStatus() returns the fake with no modification. Other methods do
+// nothing.
+class COMPONENT_EXPORT(DLCSERVICE_CLIENT) FakeDlcserviceClient
+    : public DlcserviceClient {
+ public:
+  FakeDlcserviceClient();
+  ~FakeDlcserviceClient() override;
+
+  // DlcserviceClient:
+  void Install(const dlcservice::DlcModuleList& dlc_module_list,
+               InstallCallback callback) override;
+  void Uninstall(const std::string& dlc_id,
+                 UninstallCallback callback) override;
+  void GetInstalled(GetInstalledCallback callback) override;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_DLCSERVICE_FAKE_DLCSERVICE_CLIENT_H_
diff --git a/chromeos/services/assistant/chromium_http_connection.cc b/chromeos/services/assistant/chromium_http_connection.cc
index cfde911e..7b42afa 100644
--- a/chromeos/services/assistant/chromium_http_connection.cc
+++ b/chromeos/services/assistant/chromium_http_connection.cc
@@ -17,6 +17,7 @@
 #include "services/network/public/cpp/header_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 using assistant_client::HttpConnection;
 using network::SharedURLLoaderFactory;
@@ -395,7 +396,7 @@
 
 void ChromiumHttpConnection::OnResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_header) {
+    const network::mojom::URLResponseHead& response_header) {
   if (enable_header_response_ && response_header.headers) {
     // Only propagate |OnHeaderResponse()| once before any |OnPartialResponse()|
     // invoked to honor the API contract.
diff --git a/chromeos/services/assistant/chromium_http_connection.h b/chromeos/services/assistant/chromium_http_connection.h
index dd904dc..47e2d9a 100644
--- a/chromeos/services/assistant/chromium_http_connection.h
+++ b/chromeos/services/assistant/chromium_http_connection.h
@@ -17,9 +17,9 @@
 #include "libassistant/shared/internal_api/http_connection.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "net/http/http_request_headers.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace network {
@@ -89,8 +89,9 @@
   void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
 
   // Callback invoked when the response of the http connection has started.
-  void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_header);
+  void OnResponseStarted(
+      const GURL& final_url,
+      const network::mojom::URLResponseHead& response_header);
 
   Delegate* const delegate_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/chromeos/services/device_sync/cryptauth_api_call_flow.cc b/chromeos/services/device_sync/cryptauth_api_call_flow.cc
index ec01c92..ba6037f 100644
--- a/chromeos/services/device_sync/cryptauth_api_call_flow.cc
+++ b/chromeos/services/device_sync/cryptauth_api_call_flow.cc
@@ -9,6 +9,7 @@
 #include "net/base/url_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace chromeos {
 
@@ -115,7 +116,7 @@
 }
 
 void CryptAuthApiCallFlow::ProcessApiCallSuccess(
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   if (!body) {
     error_callback_.Run(NetworkRequestError::kResponseMalformed);
@@ -126,7 +127,7 @@
 
 void CryptAuthApiCallFlow::ProcessApiCallFailure(
     int net_error,
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   base::Optional<NetworkRequestError> error;
   std::string error_message;
diff --git a/chromeos/services/device_sync/cryptauth_api_call_flow.h b/chromeos/services/device_sync/cryptauth_api_call_flow.h
index 06da1c7..d69dd645 100644
--- a/chromeos/services/device_sync/cryptauth_api_call_flow.h
+++ b/chromeos/services/device_sync/cryptauth_api_call_flow.h
@@ -88,10 +88,10 @@
   std::string CreateApiCallBody() override;
   std::string CreateApiCallBodyContentType() override;
   std::string GetRequestTypeForBody(const std::string& body) override;
-  void ProcessApiCallSuccess(const network::ResourceResponseHead* head,
+  void ProcessApiCallSuccess(const network::mojom::URLResponseHead* head,
                              std::unique_ptr<std::string> body) override;
   void ProcessApiCallFailure(int net_error,
-                             const network::ResourceResponseHead* head,
+                             const network::mojom::URLResponseHead* head,
                              std::unique_ptr<std::string> body) override;
   net::PartialNetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag()
       override;
diff --git a/chromeos/test/data/oobe_configuration/TestLeaveWelcomeScreen.json b/chromeos/test/data/oobe_configuration/TestLeaveWelcomeScreen.json
index 9a17f15..babeb398 100644
--- a/chromeos/test/data/oobe_configuration/TestLeaveWelcomeScreen.json
+++ b/chromeos/test/data/oobe_configuration/TestLeaveWelcomeScreen.json
@@ -1,3 +1,3 @@
 {
-  "welcomeNext": true
-}
+  "welcomeNext": true,
+}
\ No newline at end of file
diff --git a/chromeos/test/data/oobe_configuration/TestShowHID.json b/chromeos/test/data/oobe_configuration/TestShowHID.json
deleted file mode 100644
index 43bc317..0000000
--- a/chromeos/test/data/oobe_configuration/TestShowHID.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "welcomeNext" : false,
-  "desc" : "Skip welcomeNext as this will trigger an action on the hidden welcome screen"
-}
\ No newline at end of file
diff --git a/components/crash/content/app/run_as_crashpad_handler_win.cc b/components/crash/content/app/run_as_crashpad_handler_win.cc
index 2192d06..e7f0d9b 100644
--- a/components/crash/content/app/run_as_crashpad_handler_win.cc
+++ b/components/crash/content/app/run_as_crashpad_handler_win.cc
@@ -15,6 +15,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/threading/platform_thread.h"
 #include "components/browser_watcher/stability_report_user_stream_data_source.h"
 #include "components/gwp_asan/buildflags/buildflags.h"
 #include "third_party/crashpad/crashpad/client/crashpad_info.h"
@@ -36,6 +37,8 @@
   // processes.
   base::EnableTerminationOnOutOfMemory();
 
+  base::PlatformThread::SetName("CrashpadMainThread");
+
   // If the handler is started with --monitor-self, it'll need a ptype
   // annotation set. It'll normally set one itself by being invoked with
   // --monitor-self-annotation=ptype=crashpad-handler, but that leaves a window
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index 05d0a31..29b1b97 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -543,7 +543,7 @@
     config_storer_.Run(encoded_config);
 
     // Record timing metrics on successful requests only.
-    const network::ResourceResponseHead* info = url_loader_->ResponseInfo();
+    const network::mojom::URLResponseHead* info = url_loader_->ResponseInfo();
     base::TimeDelta http_request_rtt =
         info->response_start - info->request_start;
     UMA_HISTOGRAM_TIMES("DataReductionProxy.ConfigService.HttpRequestRTT",
diff --git a/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc b/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
index 4fd75d0..bb02f89 100644
--- a/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
+++ b/components/data_reduction_proxy/core/browser/secure_proxy_checker.cc
@@ -11,6 +11,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace {
 
@@ -59,7 +60,7 @@
 
 void SecureProxyChecker::OnURLLoaderRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   OnURLLoadCompleteOrRedirect(std::string(), net::ERR_ABORTED,
                               redirect_info.status_code);
diff --git a/components/data_reduction_proxy/core/browser/secure_proxy_checker.h b/components/data_reduction_proxy/core/browser/secure_proxy_checker.h
index ecc86d3..03f196f 100644
--- a/components/data_reduction_proxy/core/browser/secure_proxy_checker.h
+++ b/components/data_reduction_proxy/core/browser/secure_proxy_checker.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 namespace net {
 struct RedirectInfo;
@@ -19,7 +20,6 @@
 namespace network {
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
-struct ResourceResponseHead;
 }  // namespace network
 
 namespace data_reduction_proxy {
@@ -44,7 +44,7 @@
                                    int response_code);
 
   void OnURLLoaderRedirect(const net::RedirectInfo& redirect_info,
-                           const network::ResourceResponseHead& response_head,
+                           const network::mojom::URLResponseHead& response_head,
                            std::vector<std::string>* to_be_removed_headers);
 
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
index 32f7ce59..ffc1e5f 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -24,6 +24,7 @@
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace data_reduction_proxy {
 
@@ -200,14 +201,14 @@
 
 void WarmupURLFetcher::OnURLLoadResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   proxy_server_ = response_head.proxy_server;
 }
 
 void WarmupURLFetcher::OnURLLoaderRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   proxy_server_ = response_head.proxy_server;
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
index 51a1c48d..3a2a52bf 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
@@ -16,6 +16,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/proxy_server.h"
 #include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 class GURL;
 
@@ -24,7 +25,6 @@
 }  // namespace net
 
 namespace network {
-struct ResourceResponseHead;
 class SimpleURLLoader;
 }  // namespace network
 
@@ -86,11 +86,11 @@
   // URL loader callback when response starts.
   void OnURLLoadResponseStarted(
       const GURL& final_url,
-      const network::ResourceResponseHead& response_head);
+      const network::mojom::URLResponseHead& response_head);
 
   // URL loader callback for redirections.
   void OnURLLoaderRedirect(const net::RedirectInfo& redirect_info,
-                           const network::ResourceResponseHead& response_head,
+                           const network::mojom::URLResponseHead& response_head,
                            std::vector<std::string>* to_be_removed_headers);
 
   // URL loader completion callback.
diff --git a/components/dom_distiller/content/browser/distillability_driver.cc b/components/dom_distiller/content/browser/distillability_driver.cc
index 42ae0003..04816925 100644
--- a/components/dom_distiller/content/browser/distillability_driver.cc
+++ b/components/dom_distiller/content/browser/distillability_driver.cc
@@ -46,7 +46,8 @@
 };
 
 DistillabilityDriver::DistillabilityDriver(content::WebContents* web_contents)
-    : content::WebContentsObserver(web_contents) {
+    : content::WebContentsObserver(web_contents),
+      latest_result_(base::nullopt) {
   if (!web_contents)
     return;
   frame_interfaces_.AddInterface(
@@ -73,6 +74,7 @@
 
 void DistillabilityDriver::OnDistillability(
     const DistillabilityResult& result) {
+  latest_result_ = result;
   for (auto& observer : observers_)
     observer.OnResult(result);
 }
diff --git a/components/dom_distiller/content/browser/distillability_driver.h b/components/dom_distiller/content/browser/distillability_driver.h
index 423c55d..2590e50 100644
--- a/components/dom_distiller/content/browser/distillability_driver.h
+++ b/components/dom_distiller/content/browser/distillability_driver.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "components/dom_distiller/content/browser/distillable_page_utils.h"
 #include "components/dom_distiller/content/common/mojom/distillability_service.mojom.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -28,6 +29,9 @@
   void CreateDistillabilityService(mojom::DistillabilityServiceRequest request);
 
   void AddObserver(DistillabilityObserver* observer);
+  base::Optional<DistillabilityResult> GetLatestResult() const {
+    return latest_result_;
+  }
 
   // content::WebContentsObserver implementation.
   void OnInterfaceRequestFromFrame(
@@ -44,6 +48,12 @@
 
   base::ObserverList<DistillabilityObserver> observers_;
 
+  // The most recently received result from the distillability service.
+  //
+  // TODO(https://crbug.com/952042): Set this to nullopt when navigating to a
+  // new page, accounting for same-document navigation.
+  base::Optional<DistillabilityResult> latest_result_;
+
   service_manager::BinderRegistry frame_interfaces_;
 
   base::WeakPtrFactory<DistillabilityDriver> weak_factory_{this};
diff --git a/components/dom_distiller/content/browser/distillable_page_utils.cc b/components/dom_distiller/content/browser/distillable_page_utils.cc
index a0a32c11..33a768f4 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils.cc
+++ b/components/dom_distiller/content/browser/distillable_page_utils.cc
@@ -68,4 +68,15 @@
   driver->AddObserver(observer);
 }
 
+base::Optional<DistillabilityResult> GetLatestResult(
+    content::WebContents* web_contents) {
+  CHECK(web_contents);
+  DistillabilityDriver::CreateForWebContents(web_contents);
+
+  DistillabilityDriver* driver =
+      DistillabilityDriver::FromWebContents(web_contents);
+  CHECK(driver);
+  return driver->GetLatestResult();
+}
+
 }  // namespace dom_distiller
diff --git a/components/dom_distiller/content/browser/distillable_page_utils.h b/components/dom_distiller/content/browser/distillable_page_utils.h
index 83cee04efa..3754622 100644
--- a/components/dom_distiller/content/browser/distillable_page_utils.h
+++ b/components/dom_distiller/content/browser/distillable_page_utils.h
@@ -9,6 +9,7 @@
 
 #include "base/callback.h"
 #include "base/observer_list_types.h"
+#include "base/optional.h"
 
 namespace content {
 class WebContents;
@@ -45,6 +46,9 @@
 void AddObserver(content::WebContents* web_contents,
                  DistillabilityObserver* observer);
 
+base::Optional<DistillabilityResult> GetLatestResult(
+    content::WebContents* web_contents);
+
 }  // namespace dom_distiller
 
 #endif  // COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABLE_PAGE_UTILS_H_
diff --git a/components/dom_distiller/core/distiller.cc b/components/dom_distiller/core/distiller.cc
index 791d6db..3e51669 100644
--- a/components/dom_distiller/core/distiller.cc
+++ b/components/dom_distiller/core/distiller.cc
@@ -167,7 +167,14 @@
   }
 
   DCHECK(distiller_result);
+  CHECK_LT(started_pages_index_[page_num], pages_.size())
+      << "started_pages_index_[" << page_num
+      << "] (=" << started_pages_index_[page_num] << ") is out of range.";
   DistilledPageData* page_data = GetPageAtIndex(started_pages_index_[page_num]);
+  CHECK(page_data) << "GetPageAtIndex(started_pages_index_[" << page_num
+                   << "] (=" << started_pages_index_[page_num]
+                   << ")) returns nullptr. pages_.size() = " << pages_.size()
+                   << ".";
   page_data->distilled_page_proto =
       new base::RefCountedData<DistilledPageProto>();
   page_data->page_num = page_num;
diff --git a/components/download/internal/background_service/in_memory_download.cc b/components/download/internal/background_service/in_memory_download.cc
index c992622..f5e369f 100644
--- a/components/download/internal/background_service/in_memory_download.cc
+++ b/components/download/internal/background_service/in_memory_download.cc
@@ -11,6 +11,7 @@
 #include "components/download/internal/background_service/blob_task_proxy.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_storage_context.h"
 
@@ -140,7 +141,7 @@
   // OnComplete() called without OnResponseStarted(). This will happen when the
   // request was aborted.
   if (!started_)
-    OnResponseStarted(GURL(), network::ResourceResponseHead());
+    OnResponseStarted(GURL(), network::mojom::URLResponseHead());
 
   NotifyDelegateDownloadComplete();
 }
@@ -223,14 +224,14 @@
 
 void InMemoryDownloadImpl::OnRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   url_chain_.push_back(redirect_info.new_url);
 }
 
 void InMemoryDownloadImpl::OnResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   started_ = true;
   response_headers_ = response_head.headers;
 
diff --git a/components/download/internal/background_service/in_memory_download.h b/components/download/internal/background_service/in_memory_download.h
index ec7ea9d..cd1a9a3 100644
--- a/components/download/internal/background_service/in_memory_download.h
+++ b/components/download/internal/background_service/in_memory_download.h
@@ -20,6 +20,7 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 class GURL;
 
@@ -207,12 +208,12 @@
 
   // Called when the server redirects to another URL.
   void OnRedirect(const net::RedirectInfo& redirect_info,
-                  const network::ResourceResponseHead& response_head,
+                  const network::mojom::URLResponseHead& response_head,
                   std::vector<std::string>* to_be_removed_headers);
 
   // Called when the response of the final URL is received.
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head);
+                         const network::mojom::URLResponseHead& response_head);
 
   void OnUploadProgress(uint64_t position, uint64_t total);
 
diff --git a/components/heap_profiling/supervisor.cc b/components/heap_profiling/supervisor.cc
index fecdbf45..c4e153e5 100644
--- a/components/heap_profiling/supervisor.cc
+++ b/components/heap_profiling/supervisor.cc
@@ -14,11 +14,10 @@
 #include "components/services/heap_profiling/public/cpp/settings.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_coordinator_service.h"
 #include "content/public/browser/tracing_controller.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace heap_profiling {
 
@@ -60,24 +59,28 @@
   constructor_ = constructor;
 }
 
-void Supervisor::Start(service_manager::Connector* connector,
-                       base::OnceClosure closure) {
-  Start(connector, GetModeForStartup(), GetStackModeForStartup(),
+void Supervisor::Start(base::OnceClosure closure) {
+  Start(GetModeForStartup(), GetStackModeForStartup(),
         GetSamplingRateForStartup(), std::move(closure));
 }
 
-void Supervisor::Start(service_manager::Connector* connector,
-                       Mode mode,
+void Supervisor::Start(Mode mode,
                        mojom::StackMode stack_mode,
                        uint32_t sampling_rate,
                        base::OnceClosure closure) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!started_);
 
+  mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper> helper;
+  mojo::PendingRemote<memory_instrumentation::mojom::HeapProfiler> profiler;
+  auto profiler_receiver = profiler.InitWithNewPipeAndPassReceiver();
+  content::GetResourceCoordinatorService()->RegisterHeapProfiler(
+      std::move(profiler), helper.InitWithNewPipeAndPassReceiver());
   base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
       ->PostTask(FROM_HERE, base::BindOnce(&Supervisor::StartServiceOnIOThread,
                                            base::Unretained(this),
-                                           connector->Clone(), mode, stack_mode,
+                                           std::move(profiler_receiver),
+                                           std::move(helper), mode, stack_mode,
                                            sampling_rate, std::move(closure)));
 }
 
@@ -166,28 +169,17 @@
 }
 
 void Supervisor::StartServiceOnIOThread(
-    std::unique_ptr<service_manager::Connector> connector,
+    mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler> receiver,
+    mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+        remote_helper,
     Mode mode,
     mojom::StackMode stack_mode,
     uint32_t sampling_rate,
     base::OnceClosure closure) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
 
-  // The heap profiling service requires the injection of a few Resource
-  // Coordinator dependencies.
-  mojo::Remote<memory_instrumentation::mojom::Coordinator> coordinator;
-  connector->Connect(resource_coordinator::mojom::kServiceName,
-                     coordinator.BindNewPipeAndPassReceiver());
-  mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper> helper;
-  connector->Connect(resource_coordinator::mojom::kServiceName,
-                     helper.InitWithNewPipeAndPassReceiver());
-
-  memory_instrumentation::mojom::HeapProfilerPtr heap_profiler;
-  auto profiler_request = mojo::MakeRequest(&heap_profiler);
-  coordinator->RegisterHeapProfiler(std::move(heap_profiler));
-
   mojo::PendingRemote<mojom::ProfilingService> service =
-      LaunchService(std::move(profiler_request), std::move(helper));
+      LaunchService(std::move(receiver), std::move(remote_helper));
 
   controller_ = std::make_unique<Controller>(std::move(service), stack_mode,
                                              sampling_rate);
diff --git a/components/heap_profiling/supervisor.h b/components/heap_profiling/supervisor.h
index 889ce93..6907d0aa 100644
--- a/components/heap_profiling/supervisor.h
+++ b/components/heap_profiling/supervisor.h
@@ -9,10 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/process/process.h"
 #include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
-
-namespace service_manager {
-class Connector;
-}  // namespace service_manager
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 
 namespace heap_profiling {
 
@@ -63,9 +60,8 @@
   //   * Relying on the assumption that in all other cases, the object is either
   //     fully initialized or not initialized. There are DCHECKs to enforce this
   //     assumption.
-  void Start(service_manager::Connector* connector, base::OnceClosure callback);
-  void Start(service_manager::Connector* connector,
-             Mode mode,
+  void Start(base::OnceClosure callback);
+  void Start(Mode mode,
              mojom::StackMode stack_mode,
              uint32_t sampling_rate,
              base::OnceClosure callback);
@@ -104,7 +100,10 @@
 
   // Initialization stage 1: Start the Service on the IO thread.
   void StartServiceOnIOThread(
-      std::unique_ptr<service_manager::Connector> connector,
+      mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
+          receiver,
+      mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
+          remote_helper,
       Mode mode,
       mojom::StackMode stack_mode,
       uint32_t sampling_rate,
diff --git a/components/heap_profiling/test_driver.cc b/components/heap_profiling/test_driver.cc
index f9ecf1c..31360904 100644
--- a/components/heap_profiling/test_driver.cc
+++ b/components/heap_profiling/test_driver.cc
@@ -26,7 +26,6 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
 #include "content/public/browser/tracing_controller.h"
 
 namespace heap_profiling {
@@ -683,12 +682,6 @@
     return true;
   }
 
-  service_manager::Connector* connector = content::GetSystemConnector();
-  if (!connector) {
-    LOG(ERROR) << "A system Connector is not available in this environment.";
-    return false;
-  }
-
   wait_for_profiling_to_start_ = true;
   base::OnceClosure start_callback;
 
@@ -707,9 +700,8 @@
   uint32_t sampling_rate = options_.should_sample
                                ? (options_.sample_everything ? 2 : kSampleRate)
                                : 1;
-  Supervisor::GetInstance()->Start(connector, options_.mode,
-                                   options_.stack_mode, sampling_rate,
-                                   std::move(start_callback));
+  Supervisor::GetInstance()->Start(options_.mode, options_.stack_mode,
+                                   sampling_rate, std::move(start_callback));
 
   return true;
 }
@@ -735,12 +727,6 @@
     return true;
   }
 
-  service_manager::Connector* connector = content::GetSystemConnector();
-  if (!connector) {
-    LOG(ERROR) << "A system Connector is not available in this environment.";
-    return false;
-  }
-
   // When this is not-null, initialization should wait for the QuitClosure to be
   // called.
   std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop);
@@ -758,9 +744,8 @@
   uint32_t sampling_rate = options_.should_sample
                                ? (options_.sample_everything ? 2 : kSampleRate)
                                : 1;
-  Supervisor::GetInstance()->Start(connector, options_.mode,
-                                   options_.stack_mode, sampling_rate,
-                                   std::move(start_callback));
+  Supervisor::GetInstance()->Start(options_.mode, options_.stack_mode,
+                                   sampling_rate, std::move(start_callback));
 
   run_loop->Run();
 
diff --git a/components/net_log/net_export_file_writer_unittest.cc b/components/net_log/net_export_file_writer_unittest.cc
index 28f43d4..f75ec6a 100644
--- a/components/net_log/net_export_file_writer_unittest.cc
+++ b/components/net_log/net_export_file_writer_unittest.cc
@@ -738,7 +738,7 @@
   simple_loader->SetOnRedirectCallback(base::BindRepeating(
       [](base::RepeatingClosure notify_log,
          const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) { notify_log.Run(); },
       run_loop.QuitClosure()));
   simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
diff --git a/components/payments/core/DEPS b/components/payments/core/DEPS
index da2b4b68..06ce7a9 100644
--- a/components/payments/core/DEPS
+++ b/components/payments/core/DEPS
@@ -11,6 +11,7 @@
   "+net",
   "+services/metrics/public",
   "+services/network/public/cpp",
+  "+services/network/public/mojom",
   "+services/network/test",
   "+third_party/libaddressinput",
   "+third_party/re2",
diff --git a/components/payments/core/payment_manifest_downloader.cc b/components/payments/core/payment_manifest_downloader.cc
index edc6776..21d9d82 100644
--- a/components/payments/core/payment_manifest_downloader.cc
+++ b/components/payments/core/payment_manifest_downloader.cc
@@ -27,6 +27,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/url_constants.h"
 
 namespace payments {
@@ -181,7 +182,7 @@
 void PaymentManifestDownloader::OnURLLoaderRedirect(
     network::SimpleURLLoader* url_loader,
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   auto download_it = downloads_.find(url_loader);
   DCHECK(download_it != downloads_.end());
diff --git a/components/payments/core/payment_manifest_downloader.h b/components/payments/core/payment_manifest_downloader.h
index 214d846..099d5ce 100644
--- a/components/payments/core/payment_manifest_downloader.h
+++ b/components/payments/core/payment_manifest_downloader.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace net {
@@ -24,7 +25,6 @@
 namespace network {
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
-struct ResourceResponseHead;
 }  // namespace network
 
 namespace payments {
@@ -128,7 +128,7 @@
   // Called by SimpleURLLoader on a redirect.
   void OnURLLoaderRedirect(network::SimpleURLLoader* url_loader,
                            const net::RedirectInfo& redirect_info,
-                           const network::ResourceResponseHead& response_head,
+                           const network::mojom::URLResponseHead& response_head,
                            std::vector<std::string>* to_be_removed_headers);
 
   // Called by SimpleURLLoader on completion.
diff --git a/components/payments/core/payment_manifest_downloader_unittest.cc b/components/payments/core/payment_manifest_downloader_unittest.cc
index c6edd15..d60c654 100644
--- a/components/payments/core/payment_manifest_downloader_unittest.cc
+++ b/components/payments/core/payment_manifest_downloader_unittest.cc
@@ -77,7 +77,7 @@
 
     downloader_.OnURLLoaderRedirect(
         downloader_.GetLoaderForTesting(), redirect_info,
-        network::ResourceResponseHead(), &to_be_removed_headers);
+        network::mojom::URLResponseHead(), &to_be_removed_headers);
   }
 
   GURL GetOriginalURL() { return downloader_.GetLoaderOriginalURLForTesting(); }
diff --git a/components/policy/core/common/cloud/external_policy_data_fetcher.cc b/components/policy/core/common/cloud/external_policy_data_fetcher.cc
index 6a574cd..27658cac 100644
--- a/components/policy/core/common/cloud/external_policy_data_fetcher.cc
+++ b/components/policy/core/common/cloud/external_policy_data_fetcher.cc
@@ -46,7 +46,7 @@
              int64_t max_size);
   void Cancel();
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head);
+                         const network::mojom::URLResponseHead& response_head);
 
   // network::SimpleURLLoaderStreamConsumer implementation
   void OnDataReceived(base::StringPiece string_piece,
@@ -134,7 +134,7 @@
 
 void ExternalPolicyDataFetcher::Job::OnResponseStarted(
     const GURL& /* final_url */,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   if (response_head.content_length != -1 &&
       response_head.content_length > max_size_) {
     url_loader_.reset();
diff --git a/components/prefs/testing_pref_service.h b/components/prefs/testing_pref_service.h
index f10e0cb..badf4c1 100644
--- a/components/prefs/testing_pref_service.h
+++ b/components/prefs/testing_pref_service.h
@@ -64,6 +64,9 @@
   // Do-nothing implementation for TestingPrefService.
   static void HandleReadError(PersistentPrefStore::PrefReadError error) {}
 
+  // Set initialization status of pref stores.
+  void SetInitializationCompleted();
+
  protected:
   TestingPrefServiceBase(TestingPrefStore* managed_prefs,
                          TestingPrefStore* extension_prefs,
@@ -230,4 +233,14 @@
   pref_store->RemoveValue(path, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 }
 
+template <class SuperPrefService, class ConstructionPrefRegistry>
+void TestingPrefServiceBase<SuperPrefService, ConstructionPrefRegistry>::
+    SetInitializationCompleted() {
+  managed_prefs_->SetInitializationCompleted();
+  extension_prefs_->SetInitializationCompleted();
+  recommended_prefs_->SetInitializationCompleted();
+  // |user_prefs_| is initialized in PrefService constructor so no need to
+  // set initialization status again.
+}
+
 #endif  // COMPONENTS_PREFS_TESTING_PREF_SERVICE_H_
diff --git a/components/previews/core/previews_experiments.cc b/components/previews/core/previews_experiments.cc
index 6958134..ca59fbf 100644
--- a/components/previews/core/previews_experiments.cc
+++ b/components/previews/core/previews_experiments.cc
@@ -159,11 +159,6 @@
                                              30 * 1000));
 }
 
-size_t LitePageRedirectPreviewMaxNavigationRestarts() {
-  return base::GetFieldTrialParamByFeatureAsInt(
-      features::kLitePageServerPreviews, "max_navigation_restart", 5);
-}
-
 int PreviewServerLoadshedMaxSeconds() {
   return base::GetFieldTrialParamByFeatureAsInt(
       features::kLitePageServerPreviews, "loadshed_max_seconds",
diff --git a/components/previews/core/previews_experiments.h b/components/previews/core/previews_experiments.h
index 992f25d5..73d1a911 100644
--- a/components/previews/core/previews_experiments.h
+++ b/components/previews/core/previews_experiments.h
@@ -126,10 +126,6 @@
 // page hints for the host.
 bool LitePagePreviewsOverridePageHints();
 
-// The maximum number of times that a Lite Page Redirect preview should restart
-// a navigation.
-size_t LitePageRedirectPreviewMaxNavigationRestarts();
-
 // Whether we should preconnect to the lite page redirect server or the origin.
 bool LitePageRedirectPreviewShouldPreconnect();
 
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 6dfaa36..4b77677a 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1195,8 +1195,10 @@
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
   IPCReceived();
 
-  if (ipc_nesting_level_ > 1)
+  if (ipc_nesting_level_ > 1) {
+    IPCProcessed();
     return;
+  }
 
   if (print_renderer)
     print_renderer_.Bind(std::move(print_renderer));
@@ -1208,13 +1210,13 @@
   auto plugin = delegate_->GetPdfElement(frame);
   if (!plugin.IsNull()) {
     PrintNode(plugin);
+    IPCProcessed();
     return;
   }
   print_preview_context_.InitWithFrame(frame);
   RequestPrintPreview(has_selection
                           ? PRINT_PREVIEW_USER_INITIATED_SELECTION
                           : PRINT_PREVIEW_USER_INITIATED_ENTIRE_FRAME);
-
   IPCProcessed();
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 }
diff --git a/components/services/heap_profiling/heap_profiling_service.cc b/components/services/heap_profiling/heap_profiling_service.cc
index 5900052..1b66c1b 100644
--- a/components/services/heap_profiling/heap_profiling_service.cc
+++ b/components/services/heap_profiling/heap_profiling_service.cc
@@ -20,7 +20,6 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 
 namespace heap_profiling {
 
diff --git a/components/translate/DEPS b/components/translate/DEPS
index c4f4ea2d..3825a03 100644
--- a/components/translate/DEPS
+++ b/components/translate/DEPS
@@ -13,6 +13,7 @@
   "+google_apis",
   "+net",
   "+services/network/public/cpp",
+  "+services/network/public/mojom",
   "+ui",
   "+third_party/metrics_proto",
 
diff --git a/components/translate/ios/browser/translate_controller.mm b/components/translate/ios/browser/translate_controller.mm
index b433524..cea25c4f 100644
--- a/components/translate/ios/browser/translate_controller.mm
+++ b/components/translate/ios/browser/translate_controller.mm
@@ -24,7 +24,7 @@
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -258,7 +258,7 @@
   // |ResponseInfo()| may be a nullptr if response is incomplete.
   int response_code = 0;
   std::string status_text;
-  const network::ResourceResponseHead* response_head =
+  const network::mojom::URLResponseHead* response_head =
       url_loader->ResponseInfo();
   if (response_head && response_head->headers) {
     net::HttpResponseHeaders* headers = response_head->headers.get();
diff --git a/components/update_client/net/DEPS b/components/update_client/net/DEPS
index efe07ca..e298d5b 100644
--- a/components/update_client/net/DEPS
+++ b/components/update_client/net/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+net",
   "+services/network/public/cpp",
+  "+services/network/public/mojom",
   "+services/network/test",
 ]
diff --git a/components/update_client/net/network_impl.cc b/components/update_client/net/network_impl.cc
index 1e241a6..a08d9f1 100644
--- a/components/update_client/net/network_impl.cc
+++ b/components/update_client/net/network_impl.cc
@@ -15,6 +15,7 @@
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 namespace {
@@ -180,7 +181,7 @@
 void NetworkFetcherImpl::OnResponseStartedCallback(
     ResponseStartedCallback response_started_callback,
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   std::move(response_started_callback)
       .Run(final_url,
            response_head.headers ? response_head.headers->response_code() : -1,
diff --git a/components/update_client/net/network_impl.h b/components/update_client/net/network_impl.h
index f28cf2f..69a18273 100644
--- a/components/update_client/net/network_impl.h
+++ b/components/update_client/net/network_impl.h
@@ -13,9 +13,9 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/update_client/network.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 namespace network {
-struct ResourceResponseHead;
 class SharedURLLoaderFactory;
 class SimpleURLLoader;
 }  // namespace network
@@ -47,7 +47,7 @@
   void OnResponseStartedCallback(
       ResponseStartedCallback response_started_callback,
       const GURL& final_url,
-      const network::ResourceResponseHead& response_head);
+      const network::mojom::URLResponseHead& response_head);
 
   void OnProgressCallback(ProgressCallback response_started_callback,
                           uint64_t current);
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc
index eeed186..c22c206b 100644
--- a/components/variations/net/variations_http_headers.cc
+++ b/components/variations/net/variations_http_headers.cc
@@ -23,6 +23,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 namespace variations {
@@ -173,7 +174,7 @@
 
 void RemoveVariationsHeaderIfNeeded(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   if (!ShouldAppendVariationsHeader(redirect_info.new_url))
     to_be_removed_headers->push_back(kClientDataHeader);
diff --git a/components/variations/net/variations_http_headers.h b/components/variations/net/variations_http_headers.h
index b414549..cc2ae592 100644
--- a/components/variations/net/variations_http_headers.h
+++ b/components/variations/net/variations_http_headers.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 namespace net {
 struct NetworkTrafficAnnotationTag;
@@ -19,7 +20,6 @@
 
 namespace network {
 struct ResourceRequest;
-struct ResourceResponseHead;
 class SimpleURLLoader;
 }  // namespace network
 
@@ -61,7 +61,7 @@
 // URL occurs.
 void RemoveVariationsHeaderIfNeeded(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers);
 
 // Creates a SimpleURLLoader that will include the variations header for
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc
index 29a7f35..14e60656 100644
--- a/components/variations/service/variations_service.cc
+++ b/components/variations/service/variations_service.cc
@@ -57,6 +57,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "ui/base/device_form_factor.h"
 #include "url/gurl.h"
 
@@ -685,7 +686,7 @@
 
 void VariationsService::OnSimpleLoaderRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const network::mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   OnSimpleLoaderCompleteOrRedirect(nullptr, true);
@@ -716,7 +717,7 @@
   if (!was_redirect) {
     final_url_was_https =
         pending_seed_request_->GetFinalURL().SchemeIs(url::kHttpsScheme);
-    const network::ResourceResponseHead* response_info =
+    const network::mojom::URLResponseHead* response_info =
         pending_seed_request_->ResponseInfo();
     if (response_info && response_info->headers) {
       headers = response_info->headers;
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h
index dbc17ce..43f89ad9 100644
--- a/components/variations/service/variations_service.h
+++ b/components/variations/service/variations_service.h
@@ -28,7 +28,7 @@
 #include "components/version_info/version_info.h"
 #include "components/web_resource/resource_request_allowed_notifier.h"
 #include "net/url_request/redirect_info.h"
-#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 class PrefService;
@@ -317,7 +317,7 @@
   // Called by SimpleURLLoader when |pending_seed_request_| load is redirected.
   void OnSimpleLoaderRedirect(
       const net::RedirectInfo& redirect_info,
-      const network::ResourceResponseHead& response_head,
+      const network::mojom::URLResponseHead& response_head,
       std::vector<std::string>* to_be_removed_headers);
 
   // Handles post-fetch events.
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 00d43e3..250fa6b 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -252,6 +252,7 @@
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/client:raster",
     "//gpu/command_buffer/client:raster_interface",
+    "//gpu/config",
     "//gpu/ipc/common:common",
     "//gpu/vulkan:buildflags",
     "//mojo/public/cpp/base",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 1707297..a9cefca 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -7,10 +7,7 @@
 #include "base/command_line.h"
 #include "build/build_config.h"
 #include "components/viz/common/switches.h"
-
-#if defined(OS_ANDROID)
-#include "gpu/config/gpu_finch_features.h"  // nogncheck
-#endif
+#include "gpu/config/gpu_finch_features.h"
 
 namespace features {
 
@@ -75,7 +72,8 @@
 
 bool IsUsingSkiaRenderer() {
   // We require OOP-D everywhere but WebView.
-  bool enabled = base::FeatureList::IsEnabled(kUseSkiaRenderer);
+  bool enabled = base::FeatureList::IsEnabled(kUseSkiaRenderer) ||
+                 base::FeatureList::IsEnabled(kVulkan);
 #if !defined(OS_ANDROID)
   if (enabled && !IsVizDisplayCompositorEnabled()) {
     DLOG(ERROR) << "UseSkiaRenderer requires VizDisplayCompositor.";
diff --git a/components/viz/host/gpu_host_impl.cc b/components/viz/host/gpu_host_impl.cc
index b2442ed8..2c811e3d 100644
--- a/components/viz/host/gpu_host_impl.cc
+++ b/components/viz/host/gpu_host_impl.cc
@@ -424,10 +424,9 @@
     if (oopd_enabled)
       CreateChannelCache(gpu::kInProcessCommandBufferClientId);
 
-    bool use_gr_shader_cache =
-        base::FeatureList::IsEnabled(
-            features::kDefaultEnableOopRasterization) ||
-        base::FeatureList::IsEnabled(features::kUseSkiaRenderer);
+    bool use_gr_shader_cache = base::FeatureList::IsEnabled(
+                                   features::kDefaultEnableOopRasterization) ||
+                               features::IsUsingSkiaRenderer();
     if (use_gr_shader_cache)
       CreateChannelCache(gpu::kGrShaderCacheClientId);
   }
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
index cd763e49..2af4f9c 100644
--- a/components/viz/service/display/direct_renderer.cc
+++ b/components/viz/service/display/direct_renderer.cc
@@ -381,7 +381,7 @@
     current_frame()->output_surface_plane =
         overlay_processor_->ProcessOutputSurfaceAsOverlay(
             device_viewport_size, output_surface_->GetOverlayBufferFormat(),
-            reshape_device_color_space_);
+            reshape_device_color_space_, reshape_has_alpha_);
     primary_plane = &(current_frame()->output_surface_plane.value());
   }
 
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index b525f75..ec38206c 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -703,7 +703,7 @@
       "benchmark,viz", "Display::FrameDisplayed", TRACE_EVENT_SCOPE_THREAD,
       copy_feedback.timestamp);
   for (auto& presentation_helper : presentation_helper_list) {
-    presentation_helper->DidPresent(feedback);
+    presentation_helper->DidPresent(copy_feedback);
   }
   pending_surfaces_with_presentation_helpers_.pop_front();
 }
diff --git a/components/viz/service/display/overlay_processor.cc b/components/viz/service/display/overlay_processor.cc
index ef41cbb..3d9c76b 100644
--- a/components/viz/service/display/overlay_processor.cc
+++ b/components/viz/service/display/overlay_processor.cc
@@ -339,13 +339,14 @@
 OverlayProcessor::ProcessOutputSurfaceAsOverlay(
     const gfx::Size& viewport_size,
     const gfx::BufferFormat& buffer_format,
-    const gfx::ColorSpace& color_space) const {
+    const gfx::ColorSpace& color_space,
+    bool has_alpha) const {
   OutputSurfaceOverlayPlane overlay_plane;
   overlay_plane.transform = gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE;
   overlay_plane.resource_size = viewport_size;
   overlay_plane.format = buffer_format;
   overlay_plane.color_space = color_space;
-  overlay_plane.enable_blending = false;
+  overlay_plane.enable_blending = has_alpha;
 
   // Adjust transformation and display_rect based on display rotation.
   overlay_plane.display_rect =
diff --git a/components/viz/service/display/overlay_processor.h b/components/viz/service/display/overlay_processor.h
index 66d7b95..591cd4d 100644
--- a/components/viz/service/display/overlay_processor.h
+++ b/components/viz/service/display/overlay_processor.h
@@ -133,7 +133,8 @@
   OutputSurfaceOverlayPlane ProcessOutputSurfaceAsOverlay(
       const gfx::Size& viewport_size,
       const gfx::BufferFormat& buffer_format,
-      const gfx::ColorSpace& color_space) const;
+      const gfx::ColorSpace& color_space,
+      bool has_alpha) const;
 
   // For Mac, if we successfully generated a candidate list for CALayerOverlay,
   // we no longer need the |output_surface_plane|. This function takes a pointer
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index aa340b5b..48c5c3f 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -1930,7 +1930,8 @@
   pass_list.push_back(std::move(pass));
 
   auto output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay(
-      kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace());
+      kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace(),
+      false /* has_alpha */);
   OverlayProcessor::OutputSurfaceOverlayPlane* primary_plane =
       &output_surface_plane;
 
diff --git a/components/viz/service/main/viz_main_impl.h b/components/viz/service/main/viz_main_impl.h
index 66f57ea..ff907ed 100644
--- a/components/viz/service/main/viz_main_impl.h
+++ b/components/viz/service/main/viz_main_impl.h
@@ -44,12 +44,6 @@
 namespace viz {
 class GpuServiceImpl;
 
-#if defined(OS_ANDROID)
-using CompositorThreadType = base::android::JavaHandlerThread;
-#else
-using CompositorThreadType = base::Thread;
-#endif
-
 class VizMainImpl : public mojom::VizMain {
  public:
   struct LogMessage {
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 579f176..da0cafc8 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -55,6 +55,7 @@
 #include "content/common/content_constants_internal.h"
 #include "content/common/url_schemes.h"
 #include "content/public/app/content_main_delegate.h"
+#include "content/public/browser/resource_coordinator_service.h"
 #include "content/public/browser/system_connector.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_descriptor_keys.h"
@@ -71,7 +72,6 @@
 #include "services/network/public/cpp/features.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/sandbox/switches.h"
@@ -419,10 +419,18 @@
 
 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
 void InitializeBrowserClientProcessImpl() {
-  memory_instrumentation::ClientProcessImpl::Config config(
-      GetSystemConnector(), resource_coordinator::mojom::kServiceName,
-      memory_instrumentation::mojom::ProcessType::BROWSER);
-  memory_instrumentation::ClientProcessImpl::CreateInstance(config);
+  // Registers the browser process as a memory-instrumentation client, so
+  // that data for the browser process will be available in memory dumps.
+  mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator;
+  mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess> process;
+  auto process_receiver = process.InitWithNewPipeAndPassReceiver();
+  GetMemoryInstrumentationCoordinatorController()->RegisterClientProcess(
+      coordinator.InitWithNewPipeAndPassReceiver(), std::move(process),
+      memory_instrumentation::mojom::ProcessType::BROWSER,
+      base::GetCurrentProcId(), /*service_name=*/base::nullopt);
+  memory_instrumentation::ClientProcessImpl::CreateInstance(
+      std::move(process_receiver), std::move(coordinator),
+      /*is_browser_process=*/true);
 }
 #endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 2373983..7955eb7 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -168,7 +168,6 @@
     "//services/network/public/cpp:manifest",
     "//services/network/public/mojom",
     "//services/resource_coordinator:lib",
-    "//services/resource_coordinator/public/cpp:manifest",
     "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//services/service_manager",
     "//services/service_manager/embedder",
@@ -1602,6 +1601,7 @@
     "resolve_proxy_msg_helper.h",
     "resource_context_impl.cc",
     "resource_context_impl.h",
+    "resource_coordinator_service.cc",
     "sandbox_host_linux.cc",
     "sandbox_host_linux.h",
     "sandbox_ipc_linux.cc",
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 5f77bc1..57cbf02 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -237,6 +237,11 @@
 }
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityCSSDisplayToNone) {
+  RunCSSTest(FILE_PATH_LITERAL("display-to-none.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilityCSSDisplayToInline) {
   RunCSSTest(FILE_PATH_LITERAL("display-to-inline.html"));
 }
@@ -277,6 +282,21 @@
   RunCSSTest(FILE_PATH_LITERAL("visibility.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityCSSVisibilityToHidden) {
+  RunCSSTest(FILE_PATH_LITERAL("visibility-to-hidden.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityCSSVisibilityToCollapsed) {
+  RunCSSTest(FILE_PATH_LITERAL("visibility-to-collapsed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityCSSVisibilityToVisible) {
+  RunCSSTest(FILE_PATH_LITERAL("visibility-to-visible.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityA) {
   RunHtmlTest(FILE_PATH_LITERAL("a.html"));
 }
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index af58856..58843d36 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -43,6 +43,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/resource_coordinator_service.h"
 #include "content/public/common/connection_filter.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -100,6 +101,24 @@
     observer.BrowserChildProcessKilled(data, info);
 }
 
+memory_instrumentation::mojom::ProcessType GetCoordinatorClientProcessType(
+    ProcessType process_type) {
+  switch (process_type) {
+    case PROCESS_TYPE_RENDERER:
+      return memory_instrumentation::mojom::ProcessType::RENDERER;
+    case PROCESS_TYPE_UTILITY:
+      return memory_instrumentation::mojom::ProcessType::UTILITY;
+    case PROCESS_TYPE_GPU:
+      return memory_instrumentation::mojom::ProcessType::GPU;
+    case PROCESS_TYPE_PPAPI_PLUGIN:
+    case PROCESS_TYPE_PPAPI_BROKER:
+      return memory_instrumentation::mojom::ProcessType::PLUGIN;
+    default:
+      NOTREACHED();
+      return memory_instrumentation::mojom::ProcessType::OTHER;
+  }
+}
+
 }  // namespace
 
 BrowserChildProcessHost* BrowserChildProcessHost::Create(
@@ -371,6 +390,14 @@
 
 void BrowserChildProcessHostImpl::BindHostReceiver(
     mojo::GenericPendingReceiver receiver) {
+  if (auto connector_receiver =
+          receiver.As<memory_instrumentation::mojom::CoordinatorConnector>()) {
+    // Well-behaved child processes do not bind this interface more than once.
+    if (!coordinator_connector_receiver_.is_bound())
+      coordinator_connector_receiver_.Bind(std::move(connector_receiver));
+    return;
+  }
+
   delegate_->BindHostReceiver(std::move(receiver));
 }
 
@@ -652,6 +679,31 @@
   }
 }
 
+void BrowserChildProcessHostImpl::RegisterCoordinatorClient(
+    mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
+    mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
+        client_process) {
+  base::PostTask(
+      FROM_HERE, BrowserThread::UI,
+      base::BindOnce(
+          [](mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator>
+                 receiver,
+             mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
+                 client_process,
+             memory_instrumentation::mojom::ProcessType process_type,
+             base::ProcessId process_id,
+             base::Optional<std::string> service_name) {
+            GetMemoryInstrumentationCoordinatorController()
+                ->RegisterClientProcess(std::move(receiver),
+                                        std::move(client_process), process_type,
+                                        process_id, std::move(service_name));
+          },
+          std::move(receiver), std::move(client_process),
+          GetCoordinatorClientProcessType(
+              static_cast<ProcessType>(data_.process_type)),
+          child_process_->GetProcess().Pid(), delegate_->GetServiceName()));
+}
+
 bool BrowserChildProcessHostImpl::IsProcessLaunched() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
diff --git a/content/browser/browser_child_process_host_impl.h b/content/browser/browser_child_process_host_impl.h
index fecea70..62f6f76 100644
--- a/content/browser/browser_child_process_host_impl.h
+++ b/content/browser/browser_child_process_host_impl.h
@@ -25,6 +25,7 @@
 #include "content/public/browser/child_process_data.h"
 #include "content/public/common/child_process_host_delegate.h"
 #include "mojo/public/cpp/system/invitation.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 
 #if defined(OS_WIN)
 #include "base/win/object_watcher.h"
@@ -50,7 +51,8 @@
 #if defined(OS_WIN)
       public base::win::ObjectWatcher::Delegate,
 #endif
-      public ChildProcessLauncher::Client {
+      public ChildProcessLauncher::Client,
+      public memory_instrumentation::mojom::CoordinatorConnector {
  public:
   BrowserChildProcessHostImpl(content::ProcessType process_type,
                               BrowserChildProcessHostDelegate* delegate,
@@ -164,6 +166,13 @@
   bool CanUseWarmUpConnection() override;
 #endif
 
+  // memory_instrumentation::mojom::CoordinatorConnector implementation:
+  void RegisterCoordinatorClient(
+      mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator>
+          receiver,
+      mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
+          client_process) override;
+
   // Returns true if the process has successfully launched. Must only be called
   // on the IO thread.
   bool IsProcessLaunched() const;
@@ -182,6 +191,8 @@
   std::string metrics_name_;
   BrowserChildProcessHostDelegate* delegate_;
   std::unique_ptr<ChildProcessHost> child_process_host_;
+  mojo::Receiver<memory_instrumentation::mojom::CoordinatorConnector>
+      coordinator_connector_receiver_{this};
 
   mojo::OutgoingInvitation mojo_invitation_;
   std::unique_ptr<ChildConnection> child_connection_;
diff --git a/content/browser/builtin_service_manifests.cc b/content/browser/builtin_service_manifests.cc
index 8f9164d6..7d7b13e 100644
--- a/content/browser/builtin_service_manifests.cc
+++ b/content/browser/builtin_service_manifests.cc
@@ -25,7 +25,6 @@
 #include "services/media_session/public/cpp/manifest.h"
 #include "services/metrics/public/cpp/manifest.h"
 #include "services/network/public/cpp/manifest.h"
-#include "services/resource_coordinator/public/cpp/manifest.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/tracing/manifest.h"
 
@@ -73,7 +72,6 @@
                   ? service_manager::Manifest::ExecutionMode::kInProcessBuiltin
                   : service_manager::Manifest::ExecutionMode::
                         kOutOfProcessBuiltin),
-          resource_coordinator::GetManifest(),
           tracing::GetManifest(),
       }};
   return *manifests;
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
index d468089b..61dc065f 100644
--- a/content/browser/download/save_file_manager.cc
+++ b/content/browser/download/save_file_manager.cc
@@ -36,6 +36,7 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -95,7 +96,7 @@
                          int render_process_id,
                          int render_frame_routing_id,
                          const GURL& final_url,
-                         const network::ResourceResponseHead& response_head) {
+                         const network::mojom::URLResponseHead& response_head) {
     std::string content_disposition;
     if (response_head.headers) {
       response_head.headers->GetNormalizedHeader("Content-Disposition",
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index 4666b18..fb67fb4 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -273,10 +273,9 @@
               gpu_client_id_, cache_dir));
     }
 
-    bool use_gr_shader_cache =
-        base::FeatureList::IsEnabled(
-            features::kDefaultEnableOopRasterization) ||
-        base::FeatureList::IsEnabled(features::kUseSkiaRenderer);
+    bool use_gr_shader_cache = base::FeatureList::IsEnabled(
+                                   features::kDefaultEnableOopRasterization) ||
+                               features::IsUsingSkiaRenderer();
     if (use_gr_shader_cache) {
       base::FilePath gr_cache_dir =
           GetContentClient()->browser()->GetGrShaderDiskCacheDirectory();
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index d37e3cf..2e38480 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -120,8 +120,6 @@
   return gfx::OVERLAY_TRANSFORM_NONE;
 }
 
-const unsigned int kMaxDisplaySwapBuffers = 1U;
-
 gpu::SharedMemoryLimits GetCompositorContextSharedMemoryLimits(
     gfx::NativeWindow window) {
   const gfx::Size screen_size = display::Screen::GetScreen()
@@ -213,121 +211,6 @@
   callback.Run(std::move(context_provider));
 }
 
-class AndroidOutputSurface : public viz::OutputSurface {
- public:
-  AndroidOutputSurface(
-      scoped_refptr<viz::ContextProviderCommandBuffer> context_provider,
-      base::RepeatingCallback<void(const gfx::Size&)> swap_buffers_callback)
-      : viz::OutputSurface(std::move(context_provider)),
-        swap_buffers_callback_(std::move(swap_buffers_callback)) {
-    capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
-  }
-
-  ~AndroidOutputSurface() override = default;
-
-  void SwapBuffers(viz::OutputSurfaceFrame frame) override {
-    auto callback =
-        base::BindOnce(&AndroidOutputSurface::OnSwapBuffersCompleted,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       std::move(frame.latency_info), frame.size);
-    uint32_t flags = 0;
-    gpu::ContextSupport::PresentationCallback presentation_callback;
-    presentation_callback = base::BindOnce(
-        &AndroidOutputSurface::OnPresentation, weak_ptr_factory_.GetWeakPtr());
-    if (frame.sub_buffer_rect) {
-      DCHECK(frame.sub_buffer_rect->IsEmpty());
-      context_provider_->ContextSupport()->CommitOverlayPlanes(
-          flags, std::move(callback), std::move(presentation_callback));
-    } else {
-      context_provider_->ContextSupport()->Swap(
-          flags, std::move(callback), std::move(presentation_callback));
-    }
-  }
-
-  void BindToClient(viz::OutputSurfaceClient* client) override {
-    DCHECK(client);
-    DCHECK(!client_);
-    client_ = client;
-  }
-
-  void EnsureBackbuffer() override {}
-
-  void DiscardBackbuffer() override {
-    context_provider()->ContextGL()->DiscardBackbufferCHROMIUM();
-  }
-
-  void BindFramebuffer() override {
-    context_provider()->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, 0);
-  }
-
-  void SetDrawRectangle(const gfx::Rect& rect) override {}
-
-  void Reshape(const gfx::Size& size,
-               float device_scale_factor,
-               const gfx::ColorSpace& color_space,
-               bool has_alpha,
-               bool use_stencil) override {
-    context_provider()->ContextGL()->ResizeCHROMIUM(
-        size.width(), size.height(), device_scale_factor,
-        gl::ColorSpaceUtils::GetGLColorSpace(color_space), has_alpha);
-  }
-
-  bool IsDisplayedAsOverlayPlane() const override { return false; }
-  unsigned GetOverlayTextureId() const override { return 0; }
-  gfx::BufferFormat GetOverlayBufferFormat() const override {
-    return gfx::BufferFormat::RGBX_8888;
-  }
-  bool HasExternalStencilTest() const override { return false; }
-  void ApplyExternalStencil() override {}
-
-  uint32_t GetFramebufferCopyTextureFormat() override {
-    auto* gl =
-        static_cast<viz::ContextProviderCommandBuffer*>(context_provider());
-    return gl->GetCopyTextureInternalFormat();
-  }
-
-  unsigned UpdateGpuFence() override { return 0; }
-
-  void SetUpdateVSyncParametersCallback(
-      viz::UpdateVSyncParametersCallback callback) override {}
-
-  void SetDisplayTransformHint(gfx::OverlayTransform transform) override {}
-  gfx::OverlayTransform GetDisplayTransform() override {
-    return gfx::OVERLAY_TRANSFORM_NONE;
-  }
-
- private:
-  gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
-    viz::ContextProviderCommandBuffer* provider_command_buffer =
-        static_cast<viz::ContextProviderCommandBuffer*>(
-            context_provider_.get());
-    gpu::CommandBufferProxyImpl* command_buffer_proxy =
-        provider_command_buffer->GetCommandBufferProxy();
-    DCHECK(command_buffer_proxy);
-    return command_buffer_proxy;
-  }
-
-  void OnSwapBuffersCompleted(std::vector<ui::LatencyInfo> latency_info,
-                              gfx::Size swap_size,
-                              const gpu::SwapBuffersCompleteParams& params) {
-    client_->DidReceiveSwapBuffersAck(params.swap_response.timings);
-    swap_buffers_callback_.Run(swap_size);
-    UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
-    latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
-  }
-
-  void OnPresentation(const gfx::PresentationFeedback& feedback) {
-    client_->DidReceivePresentationFeedback(feedback);
-  }
-
- private:
-  viz::OutputSurfaceClient* client_ = nullptr;
-  base::RepeatingCallback<void(const gfx::Size&)> swap_buffers_callback_;
-  ui::LatencyTracker latency_tracker_;
-
-  base::WeakPtrFactory<AndroidOutputSurface> weak_ptr_factory_{this};
-};
-
 static bool g_initialized = false;
 
 }  // anonymous namespace
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 6b02e98..7718d40 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -160,6 +160,7 @@
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_coordinator_service.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/system_connector.h"
 #include "content/public/browser/webrtc_log.h"
@@ -203,6 +204,7 @@
 #include "services/network/cross_origin_read_blocking.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "services/network/public/mojom/network_service.mojom.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -2020,6 +2022,22 @@
       base::BindRepeating(&RenderProcessHostImpl::BindWebDatabaseHostImpl,
                           base::Unretained(this)));
 
+  AddUIThreadInterface(
+      registry.get(),
+      base::BindRepeating(
+          [](RenderProcessHostImpl* host,
+             memory_instrumentation::mojom::CoordinatorConnectorRequest
+                 request) {
+            host->coordinator_connector_receiver_.reset();
+            host->coordinator_connector_receiver_.Bind(std::move(request));
+            if (!host->GetProcess().IsValid()) {
+              // We only want to accept messages from this interface once we
+              // have a known PID.
+              host->coordinator_connector_receiver_.Pause();
+            }
+          },
+          base::Unretained(this)));
+
   registry->AddInterface(base::BindRepeating(&MimeRegistryImpl::Create),
                          base::CreateSequencedTaskRunner(
                              {base::ThreadPool(), base::MayBlock(),
@@ -2284,6 +2302,23 @@
                      base::WrapRefCounted(db_tracker), std::move(receiver)));
 }
 
+void RenderProcessHostImpl::RegisterCoordinatorClient(
+    mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
+    mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
+        client_process) {
+  if (!GetProcess().IsValid()) {
+    // If the process dies before we get this message. we have no valid PID and
+    // there's nothing to register.
+    return;
+  }
+
+  GetMemoryInstrumentationCoordinatorController()->RegisterClientProcess(
+      std::move(receiver), std::move(client_process),
+      memory_instrumentation::mojom::ProcessType::RENDERER, GetProcess().Pid(),
+      /*service_name=*/base::nullopt);
+  coordinator_connector_receiver_.reset();
+}
+
 void RenderProcessHostImpl::CreateRendererHost(
     mojom::RendererHostAssociatedRequest request) {
   renderer_host_binding_.Bind(std::move(request));
@@ -4164,6 +4199,7 @@
   route_provider_receiver_.reset();
   associated_interface_provider_receivers_.Clear();
   associated_interfaces_.reset();
+  coordinator_connector_receiver_.reset();
 
   // Destroy all embedded CompositorFrameSinks.
   embedded_frame_sink_provider_.reset();
@@ -4397,6 +4433,9 @@
           child_process_launcher_->GetProcess().Duplicate());
     }
 
+    if (coordinator_connector_receiver_.is_bound())
+      coordinator_connector_receiver_.Resume();
+
 // Not all platforms launch processes in the same backgrounded state. Make
 // sure |priority_.visible| reflects this platform's initial process
 // state.
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 55e0b12..01747d09 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -62,6 +62,7 @@
 #include "net/base/network_isolation_key.h"
 #include "services/network/public/mojom/mdns_responder.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 #include "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom.h"
@@ -138,7 +139,8 @@
       public ChildProcessLauncher::Client,
       public mojom::RouteProvider,
       public blink::mojom::AssociatedInterfaceProvider,
-      public mojom::RendererHost {
+      public mojom::RendererHost,
+      public memory_instrumentation::mojom::CoordinatorConnector {
  public:
   // Special depth used when there are no PriorityClients.
   static const unsigned int kMaxFrameDepthForPriority;
@@ -602,6 +604,13 @@
   void BindWebDatabaseHostImpl(
       mojo::PendingReceiver<blink::mojom::WebDatabaseHost> receiver);
 
+  // memory_instrumentation::mojom::CoordinatorConnector implementation:
+  void RegisterCoordinatorClient(
+      mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator>
+          receiver,
+      mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
+          client_process) override;
+
   // Control message handlers.
   void OnUserMetricsRecordAction(const std::string& action);
   void OnCloseACK(int closed_widget_route_id);
@@ -929,6 +938,8 @@
   mojo::AssociatedRemote<mojom::RouteProvider> remote_route_provider_;
   mojo::AssociatedRemote<mojom::Renderer> renderer_interface_;
   mojo::AssociatedBinding<mojom::RendererHost> renderer_host_binding_;
+  mojo::Receiver<memory_instrumentation::mojom::CoordinatorConnector>
+      coordinator_connector_receiver_{this};
 
   // Tracks active audio and video streams within the render process; used to
   // determine if if a process should be backgrounded.
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index a10f6f6..6c0aa947e 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -70,8 +70,6 @@
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h"
 #include "services/network/public/mojom/network_service_test.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
-#include "services/resource_coordinator/resource_coordinator_service.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/cpp/manifest.h"
@@ -318,12 +316,6 @@
                      BrowserMainLoop::GetAudioManager(), std::move(request)));
 }
 
-std::unique_ptr<service_manager::Service> CreateResourceCoordinatorService(
-    service_manager::mojom::ServiceRequest request) {
-  return std::make_unique<resource_coordinator::ResourceCoordinatorService>(
-      std::move(request));
-}
-
 std::unique_ptr<service_manager::Service> CreateTracingService(
     service_manager::mojom::ServiceRequest request) {
   return std::make_unique<tracing::TracingService>(std::move(request));
@@ -592,11 +584,6 @@
   auto* system_connection = ServiceManagerConnection::GetForProcess();
   SetSystemConnector(system_connection->GetConnector()->Clone());
 
-  RegisterInProcessService(
-      resource_coordinator::mojom::kServiceName,
-      service_manager_thread_task_runner_,
-      base::BindRepeating(&CreateResourceCoordinatorService));
-
   RegisterInProcessService(metrics::mojom::kMetricsServiceName,
                            service_manager_thread_task_runner_,
                            base::BindRepeating(&metrics::CreateMetricsService));
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index ea6ac1c..6dac3df2 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -953,6 +953,7 @@
   EXPECT_EQ(expected_dip_scale, GetFrameDeviceScaleFactor(web_contents()));
 
   FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+  EXPECT_EQ(expected_dip_scale, GetFrameDeviceScaleFactor(root));
   ASSERT_EQ(1U, root->child_count());
 
   FrameTreeNode* child = root->child_at(0);
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index c5fc2e5..910762c 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -513,6 +513,12 @@
   client->OnProcessCrashed();
 }
 
+base::Optional<std::string> UtilityProcessHost::GetServiceName() {
+  if (!service_identity_)
+    return base::nullopt;
+  return service_identity_->name();
+}
+
 void UtilityProcessHost::BindHostReceiver(
     mojo::GenericPendingReceiver receiver) {
 #if defined(OS_LINUX)
diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
index 5136379a..7ce622a 100644
--- a/content/browser/utility_process_host.h
+++ b/content/browser/utility_process_host.h
@@ -135,6 +135,7 @@
   void OnProcessLaunched() override;
   void OnProcessLaunchFailed(int error_code) override;
   void OnProcessCrashed(int exit_code) override;
+  base::Optional<std::string> GetServiceName() override;
   void BindHostReceiver(mojo::GenericPendingReceiver receiver) override;
 
   // Launch the child process with switches that will setup this sandbox type.
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index 462b6f3..7fb7b06 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -770,9 +770,7 @@
 
   bool resident_key = options->authenticator_selection &&
                       options->authenticator_selection->require_resident_key();
-  if (resident_key &&
-      (!base::FeatureList::IsEnabled(device::kWebAuthResidentKeys) ||
-       !request_delegate_->SupportsResidentKeys())) {
+  if (resident_key && !request_delegate_->SupportsResidentKeys()) {
     // Disallow the creation of resident credentials.
     InvokeCallbackAndCleanup(
         std::move(callback),
@@ -962,8 +960,7 @@
   }
 
   if (options->allow_credentials.empty()) {
-    if (!base::FeatureList::IsEnabled(device::kWebAuthResidentKeys) ||
-        !request_delegate_->SupportsResidentKeys()) {
+    if (!request_delegate_->SupportsResidentKeys()) {
       InvokeCallbackAndCleanup(
           std::move(callback),
           blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED);
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 612f0ff..fbffd5c 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3686,8 +3686,6 @@
   ResidentKeyAuthenticatorImplTest() = default;
 
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures({device::kWebAuthResidentKeys}, {});
-
     UVAuthenticatorImplTest::SetUp();
     old_client_ = SetBrowserClientForTesting(&test_client_);
     device::VirtualCtap2Device::Config config;
@@ -3724,7 +3722,6 @@
 
  private:
   ContentBrowserClient* old_client_ = nullptr;
-  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(ResidentKeyAuthenticatorImplTest);
 };
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc
index 1c2a28b..1690af4d 100644
--- a/content/browser/worker_host/shared_worker_service_impl.cc
+++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -117,11 +117,23 @@
     return;
   }
 
+  // Enforce same-origin policy.
+  // data: URLs are not considered a different origin.
+  url::Origin constructor_origin = render_frame_host->GetLastCommittedOrigin();
+  bool is_cross_origin = !info->url.SchemeIs(url::kDataScheme) &&
+                         url::Origin::Create(info->url) != constructor_origin;
+  if (is_cross_origin &&
+      !GetContentClient()->browser()->DoesSchemeAllowCrossOriginSharedWorker(
+          constructor_origin.scheme())) {
+    ScriptLoadFailed(std::move(client));
+    return;
+  }
+
   RenderFrameHost* main_frame =
       render_frame_host->frame_tree_node()->frame_tree()->GetMainFrame();
   if (!GetContentClient()->browser()->AllowSharedWorker(
           info->url, main_frame->GetLastCommittedURL(), info->name,
-          render_frame_host->GetLastCommittedOrigin(),
+          constructor_origin,
           WebContentsImpl::FromRenderFrameHostID(client_process_id, frame_id)
               ->GetBrowserContext(),
           client_process_id, frame_id)) {
@@ -130,9 +142,9 @@
   }
 
   SharedWorkerInstance instance(
-      info->url, info->name, render_frame_host->GetLastCommittedOrigin(),
-      info->content_security_policy, info->content_security_policy_type,
-      info->creation_address_space, creation_context_type);
+      info->url, info->name, constructor_origin, info->content_security_policy,
+      info->content_security_policy_type, info->creation_address_space,
+      creation_context_type);
 
   SharedWorkerHost* host = FindMatchingSharedWorkerHost(
       instance.url(), instance.name(), instance.constructor_origin());
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index d1a8042d..e9e4ce0 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -75,7 +75,6 @@
 #include "services/device/public/cpp/power_monitor/power_monitor_broadcast_source.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -641,25 +640,15 @@
   // In single process mode, browser-side tracing and memory will cover the
   // whole process including renderers.
   if (!IsInBrowserProcess()) {
-    if (service_manager_connection_) {
-      std::string process_type_str =
-          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              switches::kProcessType);
-      auto process_type = memory_instrumentation::mojom::ProcessType::OTHER;
-      if (process_type_str == switches::kRendererProcess)
-        process_type = memory_instrumentation::mojom::ProcessType::RENDERER;
-      else if (process_type_str == switches::kGpuProcess)
-        process_type = memory_instrumentation::mojom::ProcessType::GPU;
-      else if (process_type_str == switches::kUtilityProcess)
-        process_type = memory_instrumentation::mojom::ProcessType::UTILITY;
-      else if (process_type_str == switches::kPpapiPluginProcess)
-        process_type = memory_instrumentation::mojom::ProcessType::PLUGIN;
-
-      memory_instrumentation::ClientProcessImpl::Config config(
-          GetConnector(), resource_coordinator::mojom::kServiceName,
-          process_type);
-      memory_instrumentation::ClientProcessImpl::CreateInstance(config);
-    }
+    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator;
+    mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess> process;
+    auto process_receiver = process.InitWithNewPipeAndPassReceiver();
+    mojo::Remote<memory_instrumentation::mojom::CoordinatorConnector> connector;
+    BindHostReceiver(connector.BindNewPipeAndPassReceiver());
+    connector->RegisterCoordinatorClient(
+        coordinator.InitWithNewPipeAndPassReceiver(), std::move(process));
+    memory_instrumentation::ClientProcessImpl::CreateInstance(
+        std::move(process_receiver), std::move(coordinator));
   }
 
   // In single process mode we may already have initialized the power monitor,
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 7aea98c2..6795e63 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -76,6 +76,7 @@
     "browser_accessibility_state.h",
     "browser_associated_interface.h",
     "browser_child_process_host.h",
+    "browser_child_process_host_delegate.cc",
     "browser_child_process_host_delegate.h",
     "browser_child_process_host_iterator.cc",
     "browser_child_process_host_iterator.h",
@@ -283,6 +284,7 @@
     "renderer_preferences_util.h",
     "replaced_navigation_entry_data.h",
     "resource_context.h",
+    "resource_coordinator_service.h",
     "restore_type.h",
     "same_site_data_remover.h",
     "sandbox_type.h",
diff --git a/content/public/browser/DEPS b/content/public/browser/DEPS
index 9373ad4..57a51260 100644
--- a/content/public/browser/DEPS
+++ b/content/public/browser/DEPS
@@ -9,6 +9,7 @@
   "+services/media_session/public",
   "+services/metrics/public/cpp",
   "+services/network/public/cpp",
+  "+services/resource_coordinator/public",
   "+services/service_manager/sandbox",
   "+services/video_capture/public/mojom",
   "+services/viz/public/mojom",
diff --git a/content/public/browser/browser_child_process_host_delegate.cc b/content/public/browser/browser_child_process_host_delegate.cc
new file mode 100644
index 0000000..b77023b
--- /dev/null
+++ b/content/public/browser/browser_child_process_host_delegate.cc
@@ -0,0 +1,13 @@
+// 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/public/browser/browser_child_process_host_delegate.h"
+
+namespace content {
+
+base::Optional<std::string> BrowserChildProcessHostDelegate::GetServiceName() {
+  return base::nullopt;
+}
+
+}  // namespace content
diff --git a/content/public/browser/browser_child_process_host_delegate.h b/content/public/browser/browser_child_process_host_delegate.h
index 33319d0..6f1f0fd 100644
--- a/content/public/browser/browser_child_process_host_delegate.h
+++ b/content/public/browser/browser_child_process_host_delegate.h
@@ -5,6 +5,9 @@
 #ifndef CONTENT_PUBLIC_BROWSER_BROWSER_CHILD_PROCESS_HOST_DELEGATE_H_
 #define CONTENT_PUBLIC_BROWSER_BROWSER_CHILD_PROCESS_HOST_DELEGATE_H_
 
+#include <string>
+
+#include "base/optional.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_listener.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
@@ -28,6 +31,10 @@
   // returned from GetExitCodeProcess()).
   virtual void OnProcessCrashed(int exit_code) {}
 
+  // Returns a string identifying the primary service running in the child
+  // process, if any.
+  virtual base::Optional<std::string> GetServiceName();
+
   // Binds an interface receiver in the host process, as requested by the child
   // process.
   virtual void BindHostReceiver(mojo::GenericPendingReceiver receiver) {}
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 16ad4be..64e7acb 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -326,6 +326,11 @@
   return true;
 }
 
+bool ContentBrowserClient::DoesSchemeAllowCrossOriginSharedWorker(
+    const std::string& scheme) {
+  return false;
+}
+
 bool ContentBrowserClient::AllowSignedExchange(BrowserContext* context) {
   return true;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 97d1018..84a8e2f 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -578,6 +578,11 @@
                                  int render_process_id,
                                  int render_frame_id);
 
+  // Allow the embedder to control if a page/worker with |scheme| URL can create
+  // a cross-origin shared workers.
+  virtual bool DoesSchemeAllowCrossOriginSharedWorker(
+      const std::string& scheme);
+
   // Allows the embedder to control whether Signed HTTP Exchanges (SXG) can be
   // loaded. This is called on the UI thread.
   virtual bool AllowSignedExchange(BrowserContext* context);
diff --git a/content/public/browser/resource_coordinator_service.h b/content/public/browser/resource_coordinator_service.h
new file mode 100644
index 0000000..9a59cf7
--- /dev/null
+++ b/content/public/browser/resource_coordinator_service.h
@@ -0,0 +1,25 @@
+// 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_PUBLIC_BROWSER_RESOURCE_COORDINATOR_SERVICE_H_
+#define CONTENT_PUBLIC_BROWSER_RESOURCE_COORDINATOR_SERVICE_H_
+
+#include "content/common/content_export.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
+#include "services/resource_coordinator/public/mojom/resource_coordinator_service.mojom.h"
+
+namespace content {
+
+// Gets the browser's connection to the in-process Resource Coordinator service.
+CONTENT_EXPORT resource_coordinator::mojom::ResourceCoordinatorService*
+GetResourceCoordinatorService();
+
+// Gets the browser's connection to the Resource Coordinator's
+// memory instrumentation CoordinatorController.
+CONTENT_EXPORT memory_instrumentation::mojom::CoordinatorController*
+GetMemoryInstrumentationCoordinatorController();
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_RESOURCE_COORDINATOR_SERVICE_H_
diff --git a/content/public/browser/shared_worker_instance.cc b/content/public/browser/shared_worker_instance.cc
index 2d20614..2837b51 100644
--- a/content/public/browser/shared_worker_instance.cc
+++ b/content/public/browser/shared_worker_instance.cc
@@ -7,6 +7,8 @@
 #include <tuple>
 
 #include "base/logging.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
 
 namespace content {
 
@@ -24,7 +26,13 @@
       content_security_policy_(content_security_policy),
       content_security_policy_type_(security_policy_type),
       creation_address_space_(creation_address_space),
-      creation_context_type_(creation_context_type) {}
+      creation_context_type_(creation_context_type) {
+  // Ensure the same-origin policy is enforced correctly.
+  DCHECK(url.SchemeIs(url::kDataScheme) ||
+         GetContentClient()->browser()->DoesSchemeAllowCrossOriginSharedWorker(
+             constructor_origin.scheme()) ||
+         url::Origin::Create(url).IsSameOriginWith(constructor_origin));
+}
 
 SharedWorkerInstance::SharedWorkerInstance(const SharedWorkerInstance& other) =
     default;
@@ -44,11 +52,6 @@
     const GURL& url,
     const std::string& name,
     const url::Origin& constructor_origin) const {
-  // |url| and |constructor_origin| should be in the same origin, or |url|
-  // should be a data: URL.
-  DCHECK(url::Origin::Create(url).IsSameOriginWith(constructor_origin) ||
-         url.SchemeIs(url::kDataScheme));
-
   // Step 11.2: "If there exists a SharedWorkerGlobalScope object whose closing
   // flag is false, constructor origin is same origin with outside settings's
   // origin, constructor url equals urlRecord, and name equals the value of
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 188d1ef..eeb36546 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -244,12 +244,6 @@
                                size_t offset,
                                const gfx::Range& range) = 0;
 
-  // Notifies the frame's RenderView that the zoom has changed.
-  virtual void SetZoomLevel(double zoom_level) = 0;
-
-  // Returns the page's zoom level from the frame's RenderView.
-  virtual double GetZoomLevel() = 0;
-
   // Adds |message| to the DevTools console.
   virtual void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,
                                    const std::string& message) = 0;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5b75317a..b9ce1744 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1480,11 +1480,6 @@
   render_widget->Init(std::move(show_callback), web_frame_widget);
   render_view->AttachWebFrameWidget(web_frame_widget);
 
-  // This call makes sure the page zoom is propagated to the provisional frame
-  // since it has to go through the WebViewImpl, and it may not be be changed
-  // in OnSynchronizeVisualProperties(), which would pass it along if it did
-  // change.
-  render_widget->UpdateWebViewWithDeviceScaleFactor();
   render_widget->OnSynchronizeVisualProperties(params->visual_properties);
 
   // The WebFrame created here was already attached to the Page as its
@@ -1651,12 +1646,6 @@
     // WebFrameWidget since that would be part of creating the RenderWidget).
     render_widget->SetIsUndead(false);
 
-    // TODO(crbug.com/419087): This was added in 6ccadf770766e89c3 to prevent
-    // an empty ScreenInfo, but the WebView has already been created and
-    // initialized by RenderViewImpl, so this is surely redundant? It will be
-    // pulling the device scale factor off the WebView itself.
-    render_widget->UpdateWebViewWithDeviceScaleFactor();
-
     // Note that we do *not* call WebViewImpl's DidAttachLocalMainFrame() here
     // yet because this frame is provisional and not attached to the Page yet.
     // We will tell WebViewImpl about it once it is swapped in.
@@ -1695,11 +1684,6 @@
     // will not be destroyed by scoped_refptr unless Close() has been called
     // and run.
     render_widget->InitForChildLocalRoot(web_frame_widget);
-    // TODO(crbug.com/419087): This was added in 6ccadf770766e89c3 to prevent
-    // an empty ScreenInfo, but the WebView has already been created and
-    // initialized by RenderViewImpl, so this is surely redundant? It will be
-    // pulling the device scale factor off the WebView itself.
-    render_widget->UpdateWebViewWithDeviceScaleFactor();
 
     render_frame->render_widget_ = render_widget.get();
     render_frame->owned_render_widget_ = std::move(render_widget);
@@ -3279,12 +3263,19 @@
                                          static_cast<uint32_t>(offset), range));
 }
 
-void RenderFrameImpl::SetZoomLevel(double zoom_level) {
-  render_view_->UpdateZoomLevel(zoom_level);
+bool RenderFrameImpl::SetZoomLevelOnRenderView(double zoom_level) {
+  return render_view_->SetZoomLevel(zoom_level);
 }
 
-double RenderFrameImpl::GetZoomLevel() {
-  return render_view_->page_zoom_level();
+void RenderFrameImpl::SetPreferCompositingToLCDTextEnabledOnRenderView(
+    bool prefer) {
+  render_view_->SetPreferCompositingToLCDTextEnabled(prefer);
+}
+
+void RenderFrameImpl::SetDeviceScaleFactorOnRenderView(
+    bool use_zoom_for_dsf,
+    float device_scale_factor) {
+  render_view_->SetDeviceScaleFactor(use_zoom_for_dsf, device_scale_factor);
 }
 
 void RenderFrameImpl::AddMessageToConsole(
@@ -4067,17 +4058,8 @@
 // mojom::HostZoom implementation ----------------------------------------------
 
 void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
-  // TODO(wjmaclean): We should see if this restriction is really necessary,
-  // since it isn't enforced in other parts of the page zoom system (e.g.
-  // when a users changes the zoom of a currently displayed page). Android
-  // has no UI for this, so in theory the following code would normally just use
-  // the default zoom anyways.
-#if !defined(OS_ANDROID)
-  // On Android, page zoom isn't used, and in case of WebView, text zoom is used
-  // for legacy WebView text scaling emulation. Thus, the code that resets
-  // the zoom level from this map will be effectively resetting text zoom level.
-  host_zoom_levels_[url] = zoom_level;
-#endif
+  DCHECK(is_main_frame_);
+  render_view_->SetHostZoomLevel(url, zoom_level);
 }
 
 // blink::WebLocalFrameClient implementation
@@ -6092,45 +6074,6 @@
   return params;
 }
 
-void RenderFrameImpl::UpdateZoomLevel() {
-  if (!frame_->Parent()) {
-    // Reset the zoom limits in case a plugin had changed them previously. This
-    // will also call us back which will cause us to send a message to
-    // update WebContentsImpl.
-    render_view_->webview()->ZoomLimitsChanged(
-        ZoomFactorToZoomLevel(kMinimumZoomFactor),
-        ZoomFactorToZoomLevel(kMaximumZoomFactor));
-
-    // Set zoom level, but don't do it for full-page plugin since they don't use
-    // the same zoom settings.
-    auto host_zoom = host_zoom_levels_.find(GetLoadingUrl());
-    if (render_view_->webview()->MainFrame()->IsWebLocalFrame() &&
-        render_view_->webview()
-            ->MainFrame()
-            ->ToWebLocalFrame()
-            ->GetDocument()
-            .IsPluginDocument()) {
-      // Reset the zoom levels for plugins.
-      render_view_->SetZoomLevel(0);
-    } else {
-      // If the zoom level is not found, then do nothing. In-page navigation
-      // relies on not changing the zoom level in this case.
-      if (host_zoom != host_zoom_levels_.end())
-        render_view_->SetZoomLevel(host_zoom->second);
-    }
-
-    if (host_zoom != host_zoom_levels_.end()) {
-      // This zoom level was merely recorded transiently for this load.  We can
-      // erase it now.  If at some point we reload this page, the browser will
-      // send us a new, up-to-date zoom level.
-      host_zoom_levels_.erase(host_zoom);
-    }
-  } else {
-    // Subframes should match the zoom level of the main frame.
-    render_view_->SetZoomLevel(render_view_->page_zoom_level());
-  }
-}
-
 bool RenderFrameImpl::UpdateNavigationHistory(
     const blink::WebHistoryItem& item,
     blink::WebHistoryCommitType commit_type) {
@@ -6202,9 +6145,12 @@
     render_view_->webview()->ResetScrollAndScaleState();
     internal_data->set_must_reset_scroll_and_scale_state(false);
   }
-  UpdateZoomLevel();
-
   if (!frame_->Parent()) {  // Only for top frames.
+    // TODO(danakj): This seems redundant, the RenderWidget has the zoom set
+    // already via VisualProperties. Remove it.
+    render_view_->UpdateZoomLevelForNavigationCommitOfMainFrame(
+        GetLoadingUrl());
+
     RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
     if (render_thread_impl) {  // Can be NULL in tests.
       render_thread_impl->histogram_customizer()->RenderViewNavigatedToHost(
@@ -6212,6 +6158,26 @@
     }
   }
 
+  if (render_widget_) {
+    // This goes to WebViewImpl and sets the zoom factor which will be
+    // propagated down to this RenderFrameImpl's LocalFrame in blink.
+    // Non-local-roots are able to grab the value off their parents but local
+    // roots can not and this is a huge action-at-a-distance to make up for that
+    // flaw in how LocalFrame determines the zoom factor.
+    // TODO(danakj): This should not be needed if the zoom factor/device scale
+    // factor did not need to be propagated to each frame. Since they are a
+    // global that should be okay?? The test that fails without this, for
+    // child frames, is in content_browsertests:
+    //     SitePerProcessHighDPIBrowserTest.
+    //         SubframeLoadsWithCorrectDeviceScaleFactor
+    // And when UseZoomForDSF is disabled, in content_browsertests:
+    //     IFrameZoomBrowserTest.SubframesDontZoomIndependently (and the whole
+    //     suite).
+    render_view_->PropagatePageZoomToNewlyAttachedFrame(
+        render_widget_->compositor_deps()->IsUseZoomForDSFEnabled(),
+        render_view_->page_properties()->GetDeviceScaleFactor());
+  }
+
   // Remember that we've already processed this request, so we don't update
   // the session history again.  We do this regardless of whether this is
   // a session history navigation, because if we attempted a session history
@@ -6382,11 +6348,6 @@
     CHECK(!render_view_->main_render_frame_);
     render_view_->main_render_frame_ = this;
 
-    // TODO(danakj): This was added in 02dffc89d823832ac8 due to the zoom factor
-    // not being scaled by DSF when the frame was provisional. We should
-    // properly scale the zoom factor all along.
-    render_view_->GetWidget()->UpdateWebViewWithDeviceScaleFactor();
-
     // The WebFrame being swapped in here has now been attached to the Page as
     // its main frame, and the WebFrameWidget was previously initialized when
     // the frame was created, so we can call WebViewImpl's
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 6c428a1..805bd94 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -489,8 +489,6 @@
   void SetSelectedText(const base::string16& selection_text,
                        size_t offset,
                        const gfx::Range& range) override;
-  void SetZoomLevel(double zoom_level) override;
-  double GetZoomLevel() override;
   void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,
                            const std::string& message) override;
   void SetPreviewsState(PreviewsState previews_state) override;
@@ -915,6 +913,16 @@
 
   media::MediaPermission* GetMediaPermission();
 
+  // Proxies the call to set the zoom level over to the RenderViewImpl and
+  // returns its result.
+  bool SetZoomLevelOnRenderView(double zoom_level);
+  // Proxies the call to set the prefer compositing flag over to the
+  // RenderViewImpl.
+  void SetPreferCompositingToLCDTextEnabledOnRenderView(bool prefer);
+  // Proxies the call to set the device scale factor over to the RenderViewImpl.
+  void SetDeviceScaleFactorOnRenderView(bool use_zoom_for_dsf,
+                                        float device_scale_factor);
+
   // Sends the current frame's navigation state to the browser.
   void SendUpdateState();
 
@@ -1081,8 +1089,6 @@
 
   class FrameURLLoaderFactory;
 
-  typedef std::map<GURL, double> HostZoomLevels;
-
   // 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,
@@ -1348,9 +1354,6 @@
   MakeDidCommitProvisionalLoadParams(blink::WebHistoryCommitType commit_type,
                                      ui::PageTransition transition);
 
-  // Updates the Zoom level of the render view to match current content.
-  void UpdateZoomLevel();
-
   // Updates the navigation history depending on the passed parameters.
   // This could result either in the creation of a new entry or a modification
   // of the current entry or nothing. If a new entry was created,
@@ -1676,8 +1679,6 @@
   PepperPluginInstanceImpl* pepper_last_mouse_event_target_;
 #endif
 
-  HostZoomLevels host_zoom_levels_;
-
   using AutoplayOriginAndFlags = std::pair<url::Origin, int32_t>;
   AutoplayOriginAndFlags autoplay_flags_;
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index ad99d68..7f82f28 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -425,10 +425,6 @@
     return view()->preferred_size_;
   }
 
-  void SetZoomLevel(double level) { view()->UpdateZoomLevel(level); }
-
-  double GetZoomLevel() { return view()->page_zoom_level(); }
-
   int GetScrollbarWidth() {
     blink::WebView* webview = view()->webview();
     return webview->MainFrameWidget()->Size().width -
@@ -2351,7 +2347,7 @@
   gfx::Size size = GetPreferredSize();
   EXPECT_EQ(gfx::Size(400 + scrollbar_width, 400), size);
 
-  SetZoomLevel(ZoomFactorToZoomLevel(2.0));
+  EXPECT_TRUE(view()->SetZoomLevel(ZoomFactorToZoomLevel(2.0)));
   size = GetPreferredSize();
   EXPECT_EQ(gfx::Size(800 + scrollbar_width, 800), size);
 }
@@ -2732,13 +2728,12 @@
 }
 
 TEST_F(RenderViewImplTest, ZoomLevelUpdate) {
-  // 0 is the default zoom level, nothing will change.
-  SetZoomLevel(0);
-  EXPECT_NEAR(0.0, GetZoomLevel(), 0.01);
+  // 0 will use the minimum zoom level, which is the default, nothing will
+  // change.
+  EXPECT_FALSE(view()->SetZoomLevel(0));
 
   // Change the zoom level to 25% and check if the view gets the change.
-  SetZoomLevel(content::ZoomFactorToZoomLevel(0.25));
-  EXPECT_NEAR(content::ZoomFactorToZoomLevel(0.25), GetZoomLevel(), 0.01);
+  EXPECT_TRUE(view()->SetZoomLevel(content::ZoomFactorToZoomLevel(0.25)));
 }
 
 #endif
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 5d1e6c8e..866f7e7 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1544,14 +1544,79 @@
   GetWidget()->SetWebWidgetInternal(nullptr);
 }
 
-void RenderViewImpl::SetZoomLevel(double zoom_level) {
+void RenderViewImpl::SetHostZoomLevel(const GURL& url, double zoom_level) {
+  // TODO(wjmaclean): We should see if this restriction is really necessary,
+  // since it isn't enforced in other parts of the page zoom system (e.g.
+  // when a users changes the zoom of a currently displayed page). Android
+  // has no UI for this, so in theory the following code would normally just use
+  // the default zoom anyways.
+#if !defined(OS_ANDROID)
+  // On Android, page zoom isn't used, and in case of WebView, text zoom is used
+  // for legacy WebView text scaling emulation. Thus, the code that resets
+  // the zoom level from this map will be effectively resetting text zoom level.
+  host_zoom_levels_[url] = zoom_level;
+#endif
+}
+
+void RenderViewImpl::UpdateZoomLevelForNavigationCommitOfMainFrame(
+    const GURL& loading_url) {
+  // Reset the zoom limits in case a plugin had changed them previously. This
+  // will also call us back via ZoomLimitsChanged() which will cause us to send
+  // a message to update WebContentsImpl.
+  webview()->ZoomLimitsChanged(ZoomFactorToZoomLevel(kMinimumZoomFactor),
+                               ZoomFactorToZoomLevel(kMaximumZoomFactor));
+
+  auto host_zoom_it = host_zoom_levels_.find(loading_url);
+
+  // Full-page plugin documents always use the default zoom level. Otherwise,
+  // apply the zoom level specified by the browser in the |host_zoom_levels_|
+  // map, if present.
+  WebFrame* main_frame = webview()->MainFrame();
+  if (main_frame->IsWebLocalFrame() &&
+      main_frame->ToWebLocalFrame()->GetDocument().IsPluginDocument()) {
+    SetZoomLevel(0);
+  } else if (host_zoom_it != host_zoom_levels_.end()) {
+    SetZoomLevel(host_zoom_it->second);
+  }
+
+  // This zoom level was merely recorded transiently for a single navigation.
+  // We can erase it now. On another navigation/reload, the browser will another
+  // zoom level.
+  host_zoom_levels_.clear();
+}
+
+bool RenderViewImpl::SetZoomLevel(double zoom_level) {
+  if (zoom_level == page_zoom_level_)
+    return false;
+
   // If we change the zoom level for the view, make sure any subsequent subframe
   // loads reflect the current zoom level.
   page_zoom_level_ = zoom_level;
-
   webview()->SetZoomLevel(zoom_level);
   for (auto& observer : observers_)
     observer.OnZoomLevelChanged();
+  return true;
+}
+
+void RenderViewImpl::SetPreferCompositingToLCDTextEnabled(bool prefer) {
+  webview()->GetSettings()->SetPreferCompositingToLCDTextEnabled(prefer);
+}
+
+void RenderViewImpl::SetDeviceScaleFactor(bool use_zoom_for_dsf,
+                                          float device_scale_factor) {
+  if (use_zoom_for_dsf)
+    webview()->SetZoomFactorForDeviceScaleFactor(device_scale_factor);
+  else
+    webview()->SetDeviceScaleFactor(device_scale_factor);
+}
+
+void RenderViewImpl::PropagatePageZoomToNewlyAttachedFrame(
+    bool use_zoom_for_dsf,
+    float device_scale_factor) {
+  if (use_zoom_for_dsf)
+    webview()->SetZoomFactorForDeviceScaleFactor(device_scale_factor);
+  else
+    webview()->SetZoomLevel(page_zoom_level_);
 }
 
 void RenderViewImpl::SetValidationMessageDirection(
@@ -1879,11 +1944,6 @@
   webview()->SetPageScaleFactor(page_scale_factor);
 }
 
-void RenderViewImpl::UpdateZoomLevel(double zoom_level) {
-  webview()->CancelPagePopup();
-  SetZoomLevel(zoom_level);
-}
-
 void RenderViewImpl::ApplyPageHidden(bool hidden, bool initial_setting) {
   webview()->SetIsHidden(hidden, initial_setting);
   // Note: RenderWidget visibility is separately set from the IPC handlers, and
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 025be54..75724b0 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -14,6 +14,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/containers/id_map.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -166,12 +167,26 @@
   void AddObserver(RenderViewObserver* observer);
   void RemoveObserver(RenderViewObserver* observer);
 
-  // Sets the zoom level and notifies observers.
-  void SetZoomLevel(double zoom_level);
+  // Stores a map of url to zoom level, specified by the browser.
+  void SetHostZoomLevel(const GURL& url, double zoom_level);
 
-  double page_zoom_level() {
-    return page_zoom_level_;
-  }
+  // When the main frame commits, the zoom level may need to be changed.
+  void UpdateZoomLevelForNavigationCommitOfMainFrame(const GURL& loading_url);
+
+  // Sets the zoom level and notifies observers. Returns true if the zoom level
+  // changed. A value of 0 means the default zoom level.
+  bool SetZoomLevel(double zoom_level);
+
+  // Passes along the prefer compositing preference to the WebView's settings.
+  void SetPreferCompositingToLCDTextEnabled(bool prefer);
+
+  // Passes along the device scale factor to the WebView.
+  void SetDeviceScaleFactor(bool use_zoom_for_dsf, float device_scale_factor);
+
+  // Passes along the page zoom to the WebView to set it on a newly attached
+  // LocalFrame.
+  void PropagatePageZoomToNewlyAttachedFrame(bool use_zoom_for_dsf,
+                                             float device_scale_factor);
 
   // Sets page-level focus in this view and notifies plugins and Blink's
   // FocusController.
@@ -302,7 +317,6 @@
   bool renderer_wide_named_frame_lookup() {
     return renderer_wide_named_frame_lookup_;
   }
-  void UpdateZoomLevel(double zoom_level);
 
  protected:
   RenderViewImpl(CompositorDependencies* compositor_deps,
@@ -645,6 +659,9 @@
   // they should match page zoom level.
   double page_zoom_level_ = 0;
 
+  // A map of urls to zoom levels specified by the browser.
+  base::flat_map<GURL, double> host_zoom_levels_;
+
   // Helper objects ------------------------------------------------------------
 
   RenderFrameImpl* main_render_frame_ = nullptr;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 5824f46..a910da7 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -391,8 +391,9 @@
 #endif
 }
 
-static bool PreferCompositingToLCDText(CompositorDependencies* compositor_deps,
-                                       float device_scale_factor) {
+static bool ComputePreferCompositingToLCDText(
+    CompositorDependencies* compositor_deps,
+    float device_scale_factor) {
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kDisablePreferCompositingToLCDText))
@@ -786,6 +787,9 @@
   if (delegate()) {
     if (size_ != visual_properties.new_size) {
       // Only hide popups when the size changes. Eg https://crbug.com/761908.
+      // TODO(danakj): If OnSynchronizeVisualProperties doesn't happen on an
+      // undead widget then this can go through the WebFrameWidget->WebView
+      // instead of through the delegate, letting us delete that delegate API.
       delegate()->CancelPagePopupForWidget();
     }
 
@@ -835,6 +839,65 @@
       ignore_resize_ipc = true;
   }
 
+  if (for_frame()) {
+    // TODO(danakj): This should not need to go through RenderFrame to set
+    // Page-level properties.
+    blink::WebFrameWidget* frame_widget = GetFrameWidget();
+    DCHECK(frame_widget);
+    RenderFrameImpl* render_frame =
+        RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot());
+
+    bool zoom_level_changed =
+        render_frame->SetZoomLevelOnRenderView(visual_properties.zoom_level);
+    if (zoom_level_changed) {
+      // Hide popups when the zoom changes.
+      blink::WebView* web_view = frame_widget->LocalRoot()->View();
+      web_view->CancelPagePopup();
+
+      // Propagate changes down to child local root RenderWidgets and
+      // BrowserPlugins in other frame trees/processes.
+      for (auto& observer : render_frame_proxies_)
+        observer.OnZoomLevelChanged(visual_properties.zoom_level);
+      for (auto& plugin : browser_plugins_)
+        plugin.OnZoomLevelChanged(visual_properties.zoom_level);
+    }
+
+    bool capture_sequence_number_changed =
+        visual_properties.capture_sequence_number !=
+        last_capture_sequence_number_;
+    if (capture_sequence_number_changed) {
+      last_capture_sequence_number_ = visual_properties.capture_sequence_number;
+
+      // Propagate changes down to child local root RenderWidgets and
+      // BrowserPlugins in other frame trees/processes.
+      for (auto& observer : render_frame_proxies_) {
+        observer.UpdateCaptureSequenceNumber(
+            visual_properties.capture_sequence_number);
+      }
+      for (auto& observer : browser_plugins_) {
+        observer.UpdateCaptureSequenceNumber(
+            visual_properties.capture_sequence_number);
+      }
+    }
+  }
+
+  layer_tree_view_->layer_tree_host()->SetBrowserControlsHeight(
+      visual_properties.top_controls_height,
+      visual_properties.bottom_controls_height,
+      visual_properties.browser_controls_shrink_blink_size);
+
+  if (!visual_properties.auto_resize_enabled) {
+    if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_) {
+      is_fullscreen_granted_ = visual_properties.is_fullscreen_granted;
+      if (is_fullscreen_granted_)
+        GetWebWidget()->DidEnterFullscreen();
+      else
+        GetWebWidget()->DidExitFullscreen();
+    }
+  }
+
+  gfx::Size old_visible_viewport_size = visible_viewport_size_;
+
   // When controlling the size in the renderer, we should ignore sizes given by
   // the browser IPC here.
   // TODO(danakj): There are many things also being ignored that aren't the
@@ -859,6 +922,8 @@
       screen_metrics_emulator_->OnSynchronizeVisualProperties(
           visual_properties);
     } else {
+      SynchronizeVisualProperties(visual_properties);
+
       if (!delegate()) {
         // The main frame controls the page scale factor, from blink. For other
         // frame widgets, the page scale is received from its parent as part of
@@ -892,16 +957,13 @@
               visual_properties.is_pinch_gesture_active);
         }
       }
-
-      gfx::Size old_visible_viewport_size = visible_viewport_size_;
-      SynchronizeVisualProperties(visual_properties);
-      if (old_visible_viewport_size != visible_viewport_size_) {
-        for (auto& render_frame : render_frames_)
-          render_frame.ResetHasScrolledFocusedEditableIntoView();
-      }
     }
   }
 
+  if (old_visible_viewport_size != visible_viewport_size_) {
+    for (auto& render_frame : render_frames_)
+      render_frame.ResetHasScrolledFocusedEditableIntoView();
+  }
   // TODO(crbug.com/939118): ScrollFocusedNodeIntoViewForWidget does not work
   // when the focused node is inside an OOPIF. This code path where
   // scroll_focused_node_into_view is set is used only for WebView, crbug
@@ -1640,29 +1702,13 @@
   return layer_tree_view_->layer_tree_host()->device_viewport_rect();
 }
 
-void RenderWidget::UpdateZoom(double zoom_level) {
-  blink::WebFrameWidget* frame_widget = GetFrameWidget();
-  if (!frame_widget)
-    return;
-  RenderFrameImpl* render_frame =
-      RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot());
-
-  // Return early if zoom level is unchanged.
-  if (render_frame->GetZoomLevel() == zoom_level) {
-    return;
-  }
-
-  render_frame->SetZoomLevel(zoom_level);
-
-  for (auto& observer : render_frame_proxies_)
-    observer.OnZoomLevelChanged(zoom_level);
-
-  for (auto& plugin : browser_plugins_)
-    plugin.OnZoomLevelChanged(zoom_level);
-}
-
 void RenderWidget::SynchronizeVisualProperties(
     const VisualProperties& visual_properties) {
+  // This method needs to handle changes to the screen_info, new_size, and
+  // visible_viewport_size fields in |visual_properties|, as this method is
+  // called from the |screen_metrics_emulator_| and it changes those fields
+  // but not others.
+
   gfx::Rect new_compositor_viewport_pixel_rect =
       visual_properties.auto_resize_enabled
           ? gfx::Rect(gfx::ScaleToCeiledSize(
@@ -1672,13 +1718,27 @@
       visual_properties.local_surface_id_allocation.value_or(
           viz::LocalSurfaceIdAllocation()),
       new_compositor_viewport_pixel_rect, visual_properties.screen_info);
-  UpdateCaptureSequenceNumber(visual_properties.capture_sequence_number);
-  layer_tree_view_->layer_tree_host()->SetBrowserControlsHeight(
-      visual_properties.top_controls_height,
-      visual_properties.bottom_controls_height,
-      visual_properties.browser_controls_shrink_blink_size);
 
-  UpdateZoom(visual_properties.zoom_level);
+  if (for_frame()) {
+    // TODO(danakj): This should not need to go through RenderFrame to set
+    // Page-level properties.
+    blink::WebFrameWidget* frame_widget = GetFrameWidget();
+    // TODO(danakj): Stop doing SynchronizeVisualProperties() (due to emulation)
+    // while undead, and change this to a DCHECK.
+    if (frame_widget) {
+      RenderFrameImpl* render_frame =
+          RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot());
+
+      // This causes compositing state to be modified which dirties the document
+      // lifecycle. Android Webview relies on the document lifecycle being clean
+      // after the RenderWidget is initialized, in order to send IPCs that query
+      // and change compositing state. So ResizeWebWidget() must come after this
+      // call, as it runs the entire document lifecycle.
+      render_frame->SetPreferCompositingToLCDTextEnabledOnRenderView(
+          ComputePreferCompositingToLCDText(
+              compositor_deps_, page_properties_->GetDeviceScaleFactor()));
+    }
+  }
 
   if (!visual_properties.auto_resize_enabled) {
     visible_viewport_size_ = visual_properties.visible_viewport_size;
@@ -1698,9 +1758,6 @@
     // viewport is updated through the RenderView.
     if (delegate())
       delegate()->ResizeVisualViewportForWidget(visual_viewport_size);
-
-    // NOTE: We may have entered fullscreen mode without changing our size.
-    SetIsFullscreen(visual_properties.is_fullscreen_granted);
   }
 }
 
@@ -1981,24 +2038,6 @@
   close_weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
-void RenderWidget::UpdateWebViewWithDeviceScaleFactor() {
-  blink::WebFrameWidget* frame_widget = GetFrameWidget();
-  blink::WebFrame* current_frame =
-      frame_widget ? frame_widget->LocalRoot() : nullptr;
-  blink::WebView* webview = current_frame ? current_frame->View() : nullptr;
-  if (webview) {
-    if (compositor_deps_->IsUseZoomForDSFEnabled())
-      webview->SetZoomFactorForDeviceScaleFactor(
-          page_properties_->GetDeviceScaleFactor());
-    else
-      webview->SetDeviceScaleFactor(page_properties_->GetDeviceScaleFactor());
-
-    webview->GetSettings()->SetPreferCompositingToLCDTextEnabled(
-        PreferCompositingToLCDText(compositor_deps_,
-                                   page_properties_->GetDeviceScaleFactor()));
-  }
-}
-
 blink::WebFrameWidget* RenderWidget::GetFrameWidget() const {
   // TODO(danakj): Remove this check and don't call this method for non-frames.
   if (!for_frame())
@@ -2226,9 +2265,6 @@
           new_screen_info.orientation_angle ||
       page_properties_->GetScreenInfo().orientation_type !=
           new_screen_info.orientation_type;
-  bool web_device_scale_factor_changed =
-      page_properties_->GetScreenInfo().device_scale_factor !=
-      new_screen_info.device_scale_factor;
   ScreenInfo previous_original_screen_info = GetOriginalScreenInfo();
 
   local_surface_id_allocation_from_parent_ = new_local_surface_id_allocation;
@@ -2250,17 +2286,35 @@
   if (orientation_changed)
     OnOrientationChange();
 
+  if (for_frame()) {
+    // TODO(danakj): This should not need to go through RenderFrame to set
+    // Page-level properties.
+    blink::WebFrameWidget* frame_widget = GetFrameWidget();
+    // TODO(danakj): Stop sending/receiving visual properties while undead, and
+    // change this to a DCHECK.
+    if (frame_widget) {
+      RenderFrameImpl* render_frame =
+          RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot());
+      // TODO(danakj): RenderWidget knows the DSF and could avoid calling into
+      // blink when it hasn't changed, but it sets an initial |screen_info_|
+      // during construction, so it is hard to tell if the value is not the
+      // default value once we get to OnSynchronizeVisualProperties. Thus we
+      // call into blink unconditionally and let it early out if it's already
+      // set.
+      render_frame->SetDeviceScaleFactorOnRenderView(
+          compositor_deps_->IsUseZoomForDSFEnabled(),
+          page_properties_->GetDeviceScaleFactor());
+    }
+  }
+
+  // Propagate changes down to child local root RenderWidgets and BrowserPlugins
+  // in other frame trees/processes.
   if (previous_original_screen_info != GetOriginalScreenInfo()) {
     for (auto& observer : render_frame_proxies_)
       observer.OnScreenInfoChanged(GetOriginalScreenInfo());
-
-    // Notify all embedded BrowserPlugins of the updated ScreenInfo.
     for (auto& observer : browser_plugins_)
       observer.ScreenInfoChanged(GetOriginalScreenInfo());
   }
-
-  if (web_device_scale_factor_changed)
-    UpdateWebViewWithDeviceScaleFactor();
 }
 
 void RenderWidget::SetWindowRectSynchronously(
@@ -2291,19 +2345,6 @@
   }
 }
 
-void RenderWidget::UpdateCaptureSequenceNumber(
-    uint32_t capture_sequence_number) {
-  if (capture_sequence_number == last_capture_sequence_number_)
-    return;
-  last_capture_sequence_number_ = capture_sequence_number;
-
-  // Notify observers of the new capture sequence number.
-  for (auto& observer : render_frame_proxies_)
-    observer.UpdateCaptureSequenceNumber(capture_sequence_number);
-  for (auto& observer : browser_plugins_)
-    observer.UpdateCaptureSequenceNumber(capture_sequence_number);
-}
-
 void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
   if (auto* frame = GetFocusedWebLocalFrameInWidget())
     frame->SetTextDirection(direction);
@@ -2573,26 +2614,6 @@
   StartStopCompositor();
 }
 
-void RenderWidget::SetIsFullscreen(bool fullscreen) {
-  // TODO:(https://crbug.com/995981): If there is no WebWidget, then the
-  // RenderWidget should also be destroyed, and this conditional should not be
-  // necessary.
-  // We intentionally avoid setting internal state so that the next time visual
-  // properties are synchronized, state will be correctly propagated to the
-  // WebWidget.
-  if (!GetWebWidget())
-    return;
-
-  if (fullscreen == is_fullscreen_granted_)
-    return;
-  is_fullscreen_granted_ = fullscreen;
-  if (is_fullscreen_granted_) {
-    GetWebWidget()->DidEnterFullscreen();
-  } else {
-    GetWebWidget()->DidExitFullscreen();
-  }
-}
-
 void RenderWidget::OnImeEventGuardStart(ImeEventGuard* guard) {
   if (!ime_event_guard_)
     ime_event_guard_ = guard;
@@ -3781,6 +3802,15 @@
                         "must be done via the RenderView.";
   delegate()->ResizeVisualViewportForWidget(visible_viewport_size);
 
+  // TODO(danakj): This should not need to go through RenderFrame to set
+  // Page-level properties.
+  blink::WebFrameWidget* frame_widget = GetFrameWidget();
+  RenderFrameImpl* render_frame =
+      RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot());
+  render_frame->SetPreferCompositingToLCDTextEnabledOnRenderView(
+      ComputePreferCompositingToLCDText(
+          compositor_deps_, page_properties_->GetDeviceScaleFactor()));
+
   // Make sure the DSF override stays for future VisualProperties updates, and
   // that includes overriding the VisualProperties'
   // compositor_viewport_pixel_rect with size * this for-testing DSF.
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 1b702e8..7189fae 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -668,15 +668,12 @@
   void UseSynchronousResizeModeForTesting(bool enable);
   void SetDeviceScaleFactorForTesting(float factor);
   void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space);
+  void SetPageZoomLevelForTesting(double zoom_level);
   void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect);
   void EnableAutoResizeForTesting(const gfx::Size& min_size,
                                   const gfx::Size& max_size);
   void DisableAutoResizeForTesting(const gfx::Size& new_size);
 
-  // Update the WebView's device scale factor.
-  // TODO(ajwong): This should be moved into RenderView.
-  void UpdateWebViewWithDeviceScaleFactor();
-
   // Forces a redraw and invokes the callback once the frame's been displayed
   // to the user.
   using PresentationTimeCallback =
@@ -829,11 +826,6 @@
   // our state.
   void SetHidden(bool hidden);
 
-  // Sets the fullscreen state for the WebView.
-  // TODO(danakj): This is currently located on RenderWidget but is a page/view
-  // state, and should move to RenderView.
-  void SetIsFullscreen(bool fullscreen);
-
   // Returns a rect that the compositor needs to raster. For a main frame this
   // is always the entire viewport, but for out-of-process iframes this can be
   // constrained to limit overdraw.
@@ -889,8 +881,6 @@
   // Used to force the size of a window when running web tests.
   void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
 
-  void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
-
   // A variant of Send but is fatal if it fails. The browser may
   // be waiting for this IPC Message and if the send fails the browser will
   // be left in a state waiting for something that never comes. And if it
@@ -908,8 +898,6 @@
 
   gfx::ColorSpace GetRasterColorSpace() const;
 
-  void UpdateZoom(double zoom_level);
-
 #if BUILDFLAG(ENABLE_PLUGINS)
   // Returns the focused pepper plugin, if any, inside the WebWidget. That is
   // the pepper plugin which is focused inside a frame which belongs to the
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc
index 6551538..adb46dd7 100644
--- a/content/shell/browser/shell_devtools_bindings.cc
+++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -38,6 +38,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 #if !defined(OS_ANDROID)
 #include "content/public/browser/devtools_frontend_host.h"
@@ -86,7 +87,7 @@
 
  private:
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head) {
+                         const network::mojom::URLResponseHead& response_head) {
     response_headers_ = response_head.headers;
   }
 
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc
index 36e4ca3..ce1d0b6 100644
--- a/content/shell/test_runner/event_sender.cc
+++ b/content/shell/test_runner/event_sender.cc
@@ -23,6 +23,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "content/common/input/web_mouse_wheel_event_traits.h"
+#include "content/renderer/render_widget.h"
 #include "content/shell/test_runner/mock_spell_check.h"
 #include "content/shell/test_runner/test_interfaces.h"
 #include "content/shell/test_runner/web_test_delegate.h"
@@ -1811,32 +1812,29 @@
 }
 
 void EventSender::ZoomPageIn() {
-  const std::vector<WebViewTestProxy*>& window_list =
-      interfaces()->GetWindowList();
-
-  for (size_t i = 0; i < window_list.size(); ++i) {
-    window_list.at(i)->webview()->SetZoomLevel(
-        window_list.at(i)->webview()->ZoomLevel() + 1);
+  for (WebViewTestProxy* view_proxy : interfaces()->GetWindowList()) {
+    // TODO(danakj): Child frame widgets in other frame trees (ie OOPIFs) won't
+    // get the zoom level though. So this only works in tests with a single
+    // origin.
+    view_proxy->SetZoomLevel(view_proxy->webview()->ZoomLevel() + 1);
   }
 }
 
 void EventSender::ZoomPageOut() {
-  const std::vector<WebViewTestProxy*>& window_list =
-      interfaces()->GetWindowList();
-
-  for (size_t i = 0; i < window_list.size(); ++i) {
-    window_list.at(i)->webview()->SetZoomLevel(
-        window_list.at(i)->webview()->ZoomLevel() - 1);
+  for (WebViewTestProxy* view_proxy : interfaces()->GetWindowList()) {
+    // TODO(danakj): Child frame widgets in other frame trees (ie OOPIFs) won't
+    // get the zoom level though. So this only works in tests with a single
+    // origin.
+    view_proxy->SetZoomLevel(view_proxy->webview()->ZoomLevel() - 1);
   }
 }
 
 void EventSender::SetPageZoomFactor(double zoom_factor) {
-  const std::vector<WebViewTestProxy*>& window_list =
-      interfaces()->GetWindowList();
-
-  for (size_t i = 0; i < window_list.size(); ++i) {
-    window_list.at(i)->webview()->SetZoomLevel(std::log(zoom_factor) /
-                                               std::log(1.2));
+  for (WebViewTestProxy* view_proxy : interfaces()->GetWindowList()) {
+    // TODO(danakj): Child frame widgets in other frame trees (ie OOPIFs) won't
+    // get the zoom level though. So this only works in tests with a single
+    // origin.
+    view_proxy->SetZoomLevel(std::log(zoom_factor) / std::log(1.2));
   }
 }
 
diff --git a/content/test/data/accessibility/css/display-to-block-expected-blink.txt b/content/test/data/accessibility/css/display-to-block-expected-blink.txt
index 187d11c..90a4ac47 100644
--- a/content/test/data/accessibility/css/display-to-block-expected-blink.txt
+++ b/content/test/data/accessibility/css/display-to-block-expected-blink.txt
@@ -5,5 +5,7 @@
 ++++++++staticText name='Cats'
 ++++++++++inlineTextBox name='Cats'
 ++++++genericContainer
-++++++++checkBox name='done' checkedState=false
-++++++genericContainer ignored
+++++++++checkBox name='checkbox' checkedState=false
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/display-to-block.html b/content/test/data/accessibility/css/display-to-block.html
index fbfb25f..379a9692 100644
--- a/content/test/data/accessibility/css/display-to-block.html
+++ b/content/test/data/accessibility/css/display-to-block.html
@@ -4,13 +4,14 @@
 <div>
   <div>Cats</div>
   <div id="block" style="display:none;">
-      <input type="checkbox" aria-label="done">
+      <input type="checkbox" aria-label="checkbox">
   </div>
-  <div></div>
+  <div><code>pending</code></div>
 </div>
 
 <script>
   setTimeout(()=> {
     document.getElementById('block').style.display = 'block';
+    document.querySelector('code').innerText = 'done';
   }, 100);
 </script>
diff --git a/content/test/data/accessibility/css/display-to-inline-expected-blink.txt b/content/test/data/accessibility/css/display-to-inline-expected-blink.txt
index 6abd4a4..868de71a 100644
--- a/content/test/data/accessibility/css/display-to-inline-expected-blink.txt
+++ b/content/test/data/accessibility/css/display-to-inline-expected-blink.txt
@@ -4,5 +4,7 @@
 ++++++staticText name='Cats '
 ++++++++inlineTextBox name='Cats '
 ++++++genericContainer
-++++++++checkBox name='done' checkedState=false
-++++++genericContainer ignored
+++++++++checkBox name='checkbox' checkedState=false
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/display-to-inline.html b/content/test/data/accessibility/css/display-to-inline.html
index 0cac539..8dc792f 100644
--- a/content/test/data/accessibility/css/display-to-inline.html
+++ b/content/test/data/accessibility/css/display-to-inline.html
@@ -4,13 +4,14 @@
 <div>
   Cats
   <span id="inline" style="display:none;">
-      <input type="checkbox" aria-label="done">
+      <input type="checkbox" aria-label="checkbox">
   </span>
-  <div></div>
+  <div><code>pending</code></div>
 </div>
 
 <script>
   setTimeout(()=> {
     document.getElementById('inline').style.display = 'inline';
+    document.querySelector('code').innerText = 'done';
   }, 200);
 </script>
diff --git a/content/test/data/accessibility/css/display-to-none-expected-blink.txt b/content/test/data/accessibility/css/display-to-none-expected-blink.txt
new file mode 100644
index 0000000..d854908
--- /dev/null
+++ b/content/test/data/accessibility/css/display-to-none-expected-blink.txt
@@ -0,0 +1,9 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++genericContainer
+++++++++staticText name='Cats'
+++++++++++inlineTextBox name='Cats'
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/display-to-none.html b/content/test/data/accessibility/css/display-to-none.html
new file mode 100644
index 0000000..e20ae9d6
--- /dev/null
+++ b/content/test/data/accessibility/css/display-to-none.html
@@ -0,0 +1,17 @@
+<!--
+@WAIT-FOR:done
+-->
+<div>
+  <div>Cats</div>
+  <div id="none">
+      <input type="checkbox" aria-label="checkbox">
+  </div>
+  <div><code>pending</code></div>
+</div>
+
+<script>
+  setTimeout(()=> {
+    document.getElementById('none').style.display = 'none';
+    document.querySelector('code').innerText = 'done';
+  }, 100);
+</script>
diff --git a/content/test/data/accessibility/css/visibility-to-collapsed-expected-blink.txt b/content/test/data/accessibility/css/visibility-to-collapsed-expected-blink.txt
new file mode 100644
index 0000000..868de71a
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-collapsed-expected-blink.txt
@@ -0,0 +1,10 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++staticText name='Cats '
+++++++++inlineTextBox name='Cats '
+++++++genericContainer
+++++++++checkBox name='checkbox' checkedState=false
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/visibility-to-collapsed.html b/content/test/data/accessibility/css/visibility-to-collapsed.html
new file mode 100644
index 0000000..1172f3963
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-collapsed.html
@@ -0,0 +1,17 @@
+<!--
+@WAIT-FOR:done
+-->
+<div>
+  Cats
+  <span id="collapsed" style="visibility:visible;">
+      <input type="checkbox" aria-label="checkbox">
+  </span>
+  <div><code>pending</code></div>
+</div>
+
+<script>
+  setTimeout(()=> {
+    document.getElementById('collapsed').style.visibility = 'collapsed';
+    document.querySelector('code').innerText = 'done';
+  }, 200);
+</script>
diff --git a/content/test/data/accessibility/css/visibility-to-hidden-expected-blink.txt b/content/test/data/accessibility/css/visibility-to-hidden-expected-blink.txt
new file mode 100644
index 0000000..cf0d83e2
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-hidden-expected-blink.txt
@@ -0,0 +1,12 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++staticText name='Cats '
+++++++++inlineTextBox name='Cats '
+++++++genericContainer ignored invisible
+++++++++staticText ignored invisible
+++++++++checkBox ignored invisible name='checkbox' checkedState=false
+++++++++staticText ignored invisible
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/visibility-to-hidden.html b/content/test/data/accessibility/css/visibility-to-hidden.html
new file mode 100644
index 0000000..147cc61
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-hidden.html
@@ -0,0 +1,17 @@
+<!--
+@WAIT-FOR:done
+-->
+<div>
+  Cats
+  <span id="hidden" style="visibility:visible;">
+      <input type="checkbox" aria-label="checkbox">
+  </span>
+  <div><code>pending</code></div>
+</div>
+
+<script>
+  setTimeout(()=> {
+    document.getElementById('hidden').style.visibility = 'hidden';
+    document.querySelector('code').innerText = 'done';
+  }, 200);
+</script>
diff --git a/content/test/data/accessibility/css/visibility-to-visible-expected-blink.txt b/content/test/data/accessibility/css/visibility-to-visible-expected-blink.txt
new file mode 100644
index 0000000..868de71a
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-visible-expected-blink.txt
@@ -0,0 +1,10 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++staticText name='Cats '
+++++++++inlineTextBox name='Cats '
+++++++genericContainer
+++++++++checkBox name='checkbox' checkedState=false
+++++++genericContainer
+++++++++staticText name='done'
+++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/css/visibility-to-visible.html b/content/test/data/accessibility/css/visibility-to-visible.html
new file mode 100644
index 0000000..4d08744f
--- /dev/null
+++ b/content/test/data/accessibility/css/visibility-to-visible.html
@@ -0,0 +1,17 @@
+<!--
+@WAIT-FOR:done
+-->
+<div>
+  Cats
+  <span id="visible" style="visibility:hidden;">
+      <input type="checkbox" aria-label="checkbox">
+  </span>
+  <div><code>pending</code></div>
+</div>
+
+<script>
+  setTimeout(()=> {
+    document.getElementById('visible').style.visibility = 'visible';
+    document.querySelector('code').innerText = 'done';
+  }, 200);
+</script>
diff --git a/device/fido/features.cc b/device/fido/features.cc
index d80f894..f0a0b1e 100644
--- a/device/fido/features.cc
+++ b/device/fido/features.cc
@@ -16,9 +16,6 @@
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_WIN)
 
-extern const base::Feature kWebAuthResidentKeys{
-    "WebAuthenticationResidentKeys", base::FEATURE_ENABLED_BY_DEFAULT};
-
 extern const base::Feature kWebAuthBiometricEnrollment{
     "WebAuthenticationBiometricEnrollment", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/device/fido/features.h b/device/fido/features.h
index 24f04e1..78c83ed 100644
--- a/device/fido/features.h
+++ b/device/fido/features.h
@@ -16,10 +16,6 @@
 extern const base::Feature kWebAuthUseNativeWinApi;
 #endif  // defined(OS_WIN)
 
-// Enable support for resident keys.
-COMPONENT_EXPORT(DEVICE_FIDO)
-extern const base::Feature kWebAuthResidentKeys;
-
 // Enable biometric enrollment in the security keys settings UI.
 COMPONENT_EXPORT(DEVICE_FIDO)
 extern const base::Feature kWebAuthBiometricEnrollment;
diff --git a/device/gamepad/gamepad_monitor.cc b/device/gamepad/gamepad_monitor.cc
index f88e28b..a4e24a81 100644
--- a/device/gamepad/gamepad_monitor.cc
+++ b/device/gamepad/gamepad_monitor.cc
@@ -10,6 +10,7 @@
 #include "base/memory/shared_memory.h"
 #include "device/gamepad/gamepad_service.h"
 #include "device/gamepad/gamepad_shared_buffer.h"
+#include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
 namespace device {
@@ -52,7 +53,9 @@
   is_registered_consumer_ = true;
 
   GamepadService* service = GamepadService::GetInstance();
-  service->ConsumerBecameActive(this);
+  if (!service->ConsumerBecameActive(this)) {
+    mojo::ReportBadMessage("GamepadMonitor::GamepadStartPolling failed");
+  }
   std::move(callback).Run(service->DuplicateSharedMemoryRegion());
 }
 
@@ -60,7 +63,9 @@
   DCHECK(is_started_);
   is_started_ = false;
 
-  GamepadService::GetInstance()->ConsumerBecameInactive(this);
+  if (!GamepadService::GetInstance()->ConsumerBecameInactive(this)) {
+    mojo::ReportBadMessage("GamepadMonitor::GamepadStopPolling failed");
+  }
   std::move(callback).Run();
 }
 
diff --git a/device/gamepad/gamepad_service.cc b/device/gamepad/gamepad_service.cc
index b655144..2795589 100644
--- a/device/gamepad/gamepad_service.cc
+++ b/device/gamepad/gamepad_service.cc
@@ -69,7 +69,7 @@
   GamepadDataFetcherManager::GetInstance();
 }
 
-void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
+bool GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
   DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
 
   if (!provider_) {
@@ -80,6 +80,8 @@
   std::pair<ConsumerSet::iterator, bool> insert_result =
       consumers_.insert(consumer);
   const ConsumerInfo& info = *insert_result.first;
+  if (info.is_active)
+    return false;
   info.is_active = true;
   if (info.did_observe_user_gesture) {
     auto consumer_state_it = inactive_consumer_state_.find(consumer);
@@ -105,15 +107,18 @@
 
   if (num_active_consumers_++ == 0)
     provider_->Resume();
+  return true;
 }
 
-void GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
+bool GamepadService::ConsumerBecameInactive(GamepadConsumer* consumer) {
   DCHECK(provider_);
-  DCHECK(num_active_consumers_ > 0);
   auto consumer_it = consumers_.find(consumer);
-  DCHECK(consumer_it != consumers_.end());
+  if (consumer_it == consumers_.end())
+    return false;
   const ConsumerInfo& info = *consumer_it;
-  DCHECK(info.is_active);
+  if (!info.is_active)
+    return false;
+  DCHECK_GT(num_active_consumers_, 0);
 
   info.is_active = false;
   if (--num_active_consumers_ == 0)
@@ -128,16 +133,21 @@
       connected_state[i] = gamepads.items[i].connected;
     inactive_consumer_state_[consumer] = connected_state;
   }
+  return true;
 }
 
-void GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
+bool GamepadService::RemoveConsumer(GamepadConsumer* consumer) {
   DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
 
   auto it = consumers_.find(consumer);
+  if (it == consumers_.end())
+    return false;
+  DCHECK_GT(num_active_consumers_, 0);
   if (it->is_active && --num_active_consumers_ == 0)
     provider_->Pause();
   consumers_.erase(it);
   inactive_consumer_state_.erase(consumer);
+  return true;
 }
 
 void GamepadService::RegisterForUserGesture(const base::Closure& closure) {
diff --git a/device/gamepad/gamepad_service.h b/device/gamepad/gamepad_service.h
index fe0ae8c..cbfe581 100644
--- a/device/gamepad/gamepad_service.h
+++ b/device/gamepad/gamepad_service.h
@@ -10,6 +10,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/shared_memory.h"
@@ -51,28 +52,37 @@
 
   // Increments the number of users of the provider. The Provider is running
   // when there's > 0 users, and is paused when the count drops to 0.
-  // consumer is registered to listen for gamepad connections. If this is the
+  // |consumer| is registered to listen for gamepad connections. If this is the
   // first time it is added to the set of consumers it will be treated
   // specially: it will not be informed about connections before a new user
   // gesture is observed at which point it will be notified for every connected
   // gamepads.
   //
-  // Must be called on the I/O thread.
-  void ConsumerBecameActive(GamepadConsumer* consumer);
-
-  // Decrements the number of users of the provider. consumer will not be
-  // informed about connections until it's added back via ConsumerBecameActive.
-  // Must be matched with a ConsumerBecameActive call.
+  // Returns true on success. If |consumer| is already active, returns false and
+  // exits without modifying the consumer set.
   //
   // Must be called on the I/O thread.
-  void ConsumerBecameInactive(GamepadConsumer* consumer);
+  bool ConsumerBecameActive(GamepadConsumer* consumer);
 
-  // Decrements the number of users of the provider and removes consumer from
+  // Decrements the number of users of the provider. |consumer| will not be
+  // informed about connections until it's added back via ConsumerBecameActive.
+  //
+  // Returns true on success. If |consumer| is not in the consumer set or is
+  // already inactive, returns false and exits without modifying the consumer
+  // set.
+  //
+  // Must be called on the I/O thread.
+  bool ConsumerBecameInactive(GamepadConsumer* consumer);
+
+  // Decrements the number of users of the provider and removes |consumer| from
   // the set of consumers. Should be matched with a a ConsumerBecameActive
   // call.
   //
+  // Returns true on success, or false if |consumer| was not in the consumer
+  // set.
+  //
   // Must be called on the I/O thread.
-  void RemoveConsumer(GamepadConsumer* consumer);
+  bool RemoveConsumer(GamepadConsumer* consumer);
 
   // Registers the given closure for calling when the user has interacted with
   // the device. This callback will only be issued once. Should only be called
@@ -151,6 +161,7 @@
 
   ConsumerConnectedStateMap inactive_consumer_state_;
 
+  // The number of active consumers in |consumers_|.
   int num_active_consumers_ = 0;
 
   bool gesture_callback_pending_ = false;
diff --git a/device/gamepad/gamepad_service_unittest.cc b/device/gamepad/gamepad_service_unittest.cc
index e6fcac15..8160222 100644
--- a/device/gamepad/gamepad_service_unittest.cc
+++ b/device/gamepad/gamepad_service_unittest.cc
@@ -18,13 +18,14 @@
 namespace device {
 
 namespace {
-static const int kNumberOfGamepads = Gamepads::kItemsLengthCap;
-}
+constexpr int kNumberOfGamepads = Gamepads::kItemsLengthCap;
+}  // namespace
 
 class ConnectionListener : public GamepadConsumer {
  public:
-  ConnectionListener() { ClearCounters(); }
+  ConnectionListener() = default;
 
+  // GamepadConsumer implementation.
   void OnGamepadConnected(uint32_t index, const Gamepad& gamepad) override {
     connected_counter_++;
   }
@@ -43,211 +44,186 @@
   int disconnected_counter() const { return disconnected_counter_; }
 
  private:
-  int connected_counter_;
-  int disconnected_counter_;
+  int connected_counter_ = 0;
+  int disconnected_counter_ = 0;
 };
 
 class GamepadServiceTest : public testing::Test {
  protected:
-  GamepadServiceTest();
-  ~GamepadServiceTest() override;
+  GamepadServiceTest() {
+    memset(&test_data_, 0, sizeof(test_data_));
 
-  void InitializeSecondConsumer();
-  void SetSecondConsumerActive(bool active);
-  void SetPadsConnected(bool connected);
-  void SimulateUserGesture(bool has_gesture);
-  void SimulatePageReload();
-  void ClearCounters();
-  void WaitForData();
-
-  int GetConnectedCounter() const {
-    return connection_listener_->connected_counter();
-  }
-  int GetDisconnectedCounter() const {
-    return connection_listener_->disconnected_counter();
+    // Configure the pad to have one button. We need our mock gamepad
+    // to have at least one input so we can simulate a user gesture.
+    test_data_.items[0].buttons_length = 1;
   }
 
-  int GetConnectedCounter2() const {
-    if (!connection_listener2_)
-      return 0;
-    return connection_listener2_->connected_counter();
-  }
-  int GetDisconnectedCounter2() const {
-    if (!connection_listener2_)
-      return 0;
-    return connection_listener2_->disconnected_counter();
+  ~GamepadServiceTest() override = default;
+
+  GamepadService* service() const { return service_; }
+
+  void SetUp() override {
+    auto fetcher = std::make_unique<MockGamepadDataFetcher>(test_data_);
+    fetcher_ = fetcher.get();
+    service_ = new GamepadService(std::move(fetcher));
+    service_->SetSanitizationEnabled(false);
   }
 
-  void SetUp() override;
-  void TearDown() override;
+  void TearDown() override {
+    // Calling SetInstance will destroy the GamepadService instance.
+    GamepadService::SetInstance(nullptr);
+  }
+
+  ConnectionListener* CreateConsumer() {
+    consumers_.push_back(std::make_unique<ConnectionListener>());
+    return consumers_.back().get();
+  }
+
+  void ClearCounters() {
+    for (auto& consumer : consumers_)
+      consumer->ClearCounters();
+  }
+
+  void SetPadsConnected(bool connected) {
+    for (int i = 0; i < kNumberOfGamepads; ++i)
+      test_data_.items[i].connected = connected;
+    fetcher_->SetTestData(test_data_);
+  }
+
+  void SimulateUserGesture(bool has_gesture) {
+    test_data_.items[0].buttons[0].value = has_gesture ? 1.f : 0.f;
+    test_data_.items[0].buttons[0].pressed = has_gesture ? true : false;
+    fetcher_->SetTestData(test_data_);
+  }
+
+  void SimulatePageReload(GamepadConsumer* consumer) {
+    EXPECT_TRUE(service_->ConsumerBecameInactive(consumer));
+    EXPECT_TRUE(service_->ConsumerBecameActive(consumer));
+  }
+
+  void WaitForData() {
+    // Block until work on the polling thread is complete. The data fetcher will
+    // read gamepad data on the polling thread, which may cause the provider to
+    // post user gesture or gamepad connection callbacks to the main thread.
+    fetcher_->WaitForDataReadAndCallbacksIssued();
+
+    // Allow the user gesture and gamepad connection callbacks to run.
+    base::RunLoop().RunUntilIdle();
+  }
 
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
   MockGamepadDataFetcher* fetcher_;
   GamepadService* service_;
-  std::unique_ptr<ConnectionListener> connection_listener_;
-  std::unique_ptr<ConnectionListener> connection_listener2_;
+  std::vector<std::unique_ptr<ConnectionListener>> consumers_;
   Gamepads test_data_;
 
   DISALLOW_COPY_AND_ASSIGN(GamepadServiceTest);
 };
 
-GamepadServiceTest::GamepadServiceTest() {
-  memset(&test_data_, 0, sizeof(test_data_));
-
-  // Configure the pad to have one button. We need our mock gamepad
-  // to have at least one input so we can simulate a user gesture.
-  test_data_.items[0].buttons_length = 1;
-}
-
-GamepadServiceTest::~GamepadServiceTest() = default;
-
-void GamepadServiceTest::SetUp() {
-  auto fetcher = std::make_unique<MockGamepadDataFetcher>(test_data_);
-  fetcher_ = fetcher.get();
-  service_ = new GamepadService(std::move(fetcher));
-  connection_listener_ = std::make_unique<ConnectionListener>();
-  service_->SetSanitizationEnabled(false);
-  service_->ConsumerBecameActive(connection_listener_.get());
-}
-
-void GamepadServiceTest::TearDown() {
-  // Calling SetInstance will destroy the GamepadService instance.
-  GamepadService::SetInstance(nullptr);
-}
-
-void GamepadServiceTest::InitializeSecondConsumer() {
-  connection_listener2_.reset((new ConnectionListener));
-  service_->ConsumerBecameActive(connection_listener2_.get());
-}
-
-void GamepadServiceTest::SetSecondConsumerActive(bool active) {
-  if (active) {
-    service_->ConsumerBecameActive(connection_listener2_.get());
-  } else {
-    service_->ConsumerBecameInactive(connection_listener2_.get());
-  }
-}
-
-void GamepadServiceTest::SetPadsConnected(bool connected) {
-  for (int i = 0; i < kNumberOfGamepads; ++i) {
-    test_data_.items[i].connected = connected;
-  }
-  fetcher_->SetTestData(test_data_);
-}
-
-void GamepadServiceTest::SimulateUserGesture(bool has_gesture) {
-  test_data_.items[0].buttons[0].value = has_gesture ? 1.f : 0.f;
-  test_data_.items[0].buttons[0].pressed = has_gesture ? true : false;
-  fetcher_->SetTestData(test_data_);
-}
-
-void GamepadServiceTest::SimulatePageReload() {
-  service_->ConsumerBecameInactive(connection_listener_.get());
-  service_->ConsumerBecameActive(connection_listener_.get());
-}
-
-void GamepadServiceTest::ClearCounters() {
-  connection_listener_->ClearCounters();
-  if (connection_listener2_)
-    connection_listener2_->ClearCounters();
-}
-
-void GamepadServiceTest::WaitForData() {
-  fetcher_->WaitForDataReadAndCallbacksIssued();
-  base::RunLoop().RunUntilIdle();
-}
-
 TEST_F(GamepadServiceTest, ConnectionsTest) {
+  auto* consumer = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer));
+
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
   SimulateUserGesture(true);
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(kNumberOfGamepads, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, ConnectionThenGestureTest) {
+  auto* consumer = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer));
+
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   // No connection events are sent until a user gesture is seen.
   ClearCounters();
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
   SimulateUserGesture(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(kNumberOfGamepads, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, ReloadTest) {
+  auto* consumer = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer));
+
   // No connection events are sent until a user gesture is seen.
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
-  SimulatePageReload();
+  SimulatePageReload(consumer);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   // After a user gesture, the connection listener is notified about connected
   // gamepads.
   ClearCounters();
   SimulateUserGesture(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(kNumberOfGamepads, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   // After a reload, if the gamepads were already connected (and we have seen
   // a user gesture) then the connection listener is notified about connected
   // gamepads.
   ClearCounters();
-  SimulatePageReload();
+  SimulatePageReload(consumer);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(kNumberOfGamepads, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
+  EXPECT_EQ(0, consumer->connected_counter());
+  EXPECT_EQ(0, consumer->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, SecondConsumerGestureTest) {
+  auto* consumer1 = CreateConsumer();
+  auto* consumer2 = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer1));
+
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   // Simulate a user gesture. The gesture is received before the second
   // consumer is active.
@@ -255,235 +231,288 @@
   SetPadsConnected(true);
   SimulateUserGesture(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   // The second consumer becomes active, but should not receive connection
   // events until a new user gesture is received.
   ClearCounters();
   SimulateUserGesture(false);
-  InitializeSecondConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   // Connection events should only be sent to the second consumer.
   ClearCounters();
   SimulateUserGesture(true);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, ConnectWhileInactiveTest) {
+  auto* consumer1 = CreateConsumer();
+  auto* consumer2 = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer1));
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
+
   // Ensure the initial user gesture is received by both consumers.
-  InitializeSecondConsumer();
   SimulateUserGesture(true);
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->disconnected_counter());
 
   // Check that connecting gamepads while a consumer is inactive will notify
   // once the consumer is active.
   ClearCounters();
-  SetSecondConsumerActive(false);
+  EXPECT_TRUE(service()->ConsumerBecameInactive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
-  SetSecondConsumerActive(true);
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, ConnectAndDisconnectWhileInactiveTest) {
+  auto* consumer1 = CreateConsumer();
+  auto* consumer2 = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer1));
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
+
   // Ensure the initial user gesture is received by both consumers.
-  InitializeSecondConsumer();
   SimulateUserGesture(true);
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->disconnected_counter());
 
   // Check that a connection and then disconnection is NOT reported once the
   // consumer is active.
   ClearCounters();
-  SetSecondConsumerActive(false);
+  EXPECT_TRUE(service()->ConsumerBecameInactive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
-  SetSecondConsumerActive(true);
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, DisconnectWhileInactiveTest) {
+  auto* consumer1 = CreateConsumer();
+  auto* consumer2 = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer1));
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
+
   // Ensure the initial user gesture is received by both consumers.
-  InitializeSecondConsumer();
   SimulateUserGesture(true);
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   // Check that disconnecting gamepads while a consumer is inactive will notify
   // once the consumer is active.
   ClearCounters();
-  SetSecondConsumerActive(false);
+  EXPECT_TRUE(service()->ConsumerBecameInactive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
-  SetSecondConsumerActive(true);
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->disconnected_counter());
 
   ClearCounters();
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 }
 
 TEST_F(GamepadServiceTest, DisconnectAndConnectWhileInactiveTest) {
+  auto* consumer1 = CreateConsumer();
+  auto* consumer2 = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer1));
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
+
   // Ensure the initial user gesture is received by both consumers.
-  InitializeSecondConsumer();
   SimulateUserGesture(true);
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   // Check that a disconnection and then connection is reported as a connection
   // (and no disconnection) once the consumer is active.
   ClearCounters();
-  SetSecondConsumerActive(false);
+  EXPECT_TRUE(service()->ConsumerBecameInactive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(false);
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
   SetPadsConnected(true);
   WaitForData();
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(0, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(kNumberOfGamepads, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(0, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
 
   ClearCounters();
-  SetSecondConsumerActive(true);
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer2));
   WaitForData();
-  EXPECT_EQ(0, GetConnectedCounter());
-  EXPECT_EQ(0, GetDisconnectedCounter());
-  EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter2());
-  EXPECT_EQ(0, GetDisconnectedCounter2());
+  EXPECT_EQ(0, consumer1->connected_counter());
+  EXPECT_EQ(0, consumer1->disconnected_counter());
+  EXPECT_EQ(kNumberOfGamepads, consumer2->connected_counter());
+  EXPECT_EQ(0, consumer2->disconnected_counter());
+}
+
+TEST_F(GamepadServiceTest, ActiveConsumerBecameActive) {
+  // Mark |consumer| active.
+  auto* consumer = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer));
+
+  // Mark |consumer| active a second time. ConsumerBecameActive should fail.
+  EXPECT_FALSE(service()->ConsumerBecameActive(consumer));
+}
+
+TEST_F(GamepadServiceTest, InactiveConsumerBecameInactive) {
+  // Mark |consumer| active.
+  auto* consumer = CreateConsumer();
+  EXPECT_TRUE(service()->ConsumerBecameActive(consumer));
+
+  // Mark |consumer| inactive.
+  EXPECT_TRUE(service()->ConsumerBecameInactive(consumer));
+
+  // Mark |consumer| inactive a second time. ConsumerBecameInactive should fail.
+  EXPECT_FALSE(service()->ConsumerBecameInactive(consumer));
+}
+
+TEST_F(GamepadServiceTest, UnregisteredConsumerBecameInactive) {
+  auto* consumer = CreateConsumer();
+
+  // |consumer| has not yet been added to the gamepad service through a call to
+  // ConsumerBecameActive. ConsumerBecameInactive should fail.
+  EXPECT_FALSE(service()->ConsumerBecameInactive(consumer));
+}
+
+TEST_F(GamepadServiceTest, RemoveUnregisteredConsumer) {
+  auto* consumer = CreateConsumer();
+
+  // |consumer| has not yet been added to the gamepad service through a call to
+  // ConsumerBecameActive. RemoveConsumer should fail.
+  EXPECT_FALSE(service()->RemoveConsumer(consumer));
 }
 
 }  // namespace device
diff --git a/docs/speed/benchmark/harnesses/blink_perf.md b/docs/speed/benchmark/harnesses/blink_perf.md
index f757799..299cd5c5 100644
--- a/docs/speed/benchmark/harnesses/blink_perf.md
+++ b/docs/speed/benchmark/harnesses/blink_perf.md
@@ -5,7 +5,7 @@
 ## Overview
 
 Blink perf tests are used for micro benchmarking the surface of Blink that
-is exposed to the Web. They are the counterpart of [web_tests/](../../../docs/testing/layout_tests.md)
+is exposed to the Web. They are the counterpart of [web_tests/](../../../testing/web_tests.md)
 but for performance coverage.
 
 ## Writing Tests
diff --git a/docs/speed/perf_regression_sheriffing.md b/docs/speed/perf_regression_sheriffing.md
index d502d8c..7cd90c4d 100644
--- a/docs/speed/perf_regression_sheriffing.md
+++ b/docs/speed/perf_regression_sheriffing.md
@@ -63,6 +63,8 @@
     * If one of the alerts already has a bug id, click "existing bug" and use
       that bug id.
     * Otherwise click "new bug".
+    * Only add a description if you have additional context. Otherwise a default
+      description will be automatically added when left blank.
 5. **Look at the revision range** for the regression. You can see it in the
    tooltip on the graph. If you see any likely culprits, cc the authors on the
    bug.
diff --git a/extensions/browser/api/feedback_private/feedback_service.cc b/extensions/browser/api/feedback_private/feedback_service.cc
index 9678af8..9f5cbd3 100644
--- a/extensions/browser/api/feedback_private/feedback_service.cc
+++ b/extensions/browser/api/feedback_private/feedback_service.cc
@@ -40,21 +40,15 @@
   feedback_data->set_user_agent(ExtensionsBrowserClient::Get()->GetUserAgent());
 
   if (!feedback_data->attached_file_uuid().empty()) {
-    // Self-deleting object.
-    BlobReader* attached_file_reader =
-        new BlobReader(browser_context_, feedback_data->attached_file_uuid(),
-                       base::Bind(&FeedbackService::AttachedFileCallback,
-                                  AsWeakPtr(), feedback_data, callback));
-    attached_file_reader->Start();
+    BlobReader::Read(browser_context_, feedback_data->attached_file_uuid(),
+                     base::Bind(&FeedbackService::AttachedFileCallback,
+                                AsWeakPtr(), feedback_data, callback));
   }
 
   if (!feedback_data->screenshot_uuid().empty()) {
-    // Self-deleting object.
-    BlobReader* screenshot_reader =
-        new BlobReader(browser_context_, feedback_data->screenshot_uuid(),
-                       base::Bind(&FeedbackService::ScreenshotCallback,
-                                  AsWeakPtr(), feedback_data, callback));
-    screenshot_reader->Start();
+    BlobReader::Read(browser_context_, feedback_data->screenshot_uuid(),
+                     base::Bind(&FeedbackService::ScreenshotCallback,
+                                AsWeakPtr(), feedback_data, callback));
   }
 
   CompleteSendFeedback(feedback_data, callback);
diff --git a/extensions/browser/blob_reader.cc b/extensions/browser/blob_reader.cc
index 492c339..d311c70 100644
--- a/extensions/browser/blob_reader.cc
+++ b/extensions/browser/blob_reader.cc
@@ -11,34 +11,64 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 
-BlobReader::BlobReader(content::BrowserContext* browser_context,
-                       const std::string& blob_uuid,
-                       BlobReadCallback callback)
-    : BlobReader(
-          content::BrowserContext::GetBlobRemote(browser_context, blob_uuid),
-          std::move(callback)) {}
-
-BlobReader::BlobReader(mojo::PendingRemote<blink::mojom::Blob> blob,
-                       BlobReadCallback callback)
-    : callback_(std::move(callback)), blob_(std::move(blob)) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  blob_.set_disconnect_handler(
-      base::BindOnce(&BlobReader::Failed, base::Unretained(this)));
-}
-
-BlobReader::~BlobReader() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); }
-
-void BlobReader::SetByteRange(int64_t offset, int64_t length) {
+// static
+void BlobReader::Read(content::BrowserContext* browser_context,
+                      const std::string& blob_uuid,
+                      BlobReader::BlobReadCallback callback,
+                      int64_t offset,
+                      int64_t length) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   CHECK_GE(offset, 0);
   CHECK_GT(length, 0);
   CHECK_LE(offset, std::numeric_limits<int64_t>::max() - length);
 
-  read_range_ = Range{offset, length};
+  base::Optional<Range> range = Range{offset, length};
+  Read(browser_context, blob_uuid, std::move(callback), std::move(range));
 }
 
-void BlobReader::Start() {
+// static
+void BlobReader::Read(content::BrowserContext* browser_context,
+                      const std::string& blob_uuid,
+                      BlobReader::BlobReadCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  Read(browser_context, blob_uuid, std::move(callback), base::nullopt);
+}
+
+BlobReader::~BlobReader() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); }
+
+// static
+void BlobReader::Read(content::BrowserContext* browser_context,
+                      const std::string& blob_uuid,
+                      BlobReader::BlobReadCallback callback,
+                      base::Optional<BlobReader::Range> range) {
+  std::unique_ptr<BlobReader> reader(new BlobReader(
+      content::BrowserContext::GetBlobRemote(browser_context, blob_uuid),
+      std::move(range)));
+
+  // Move the reader to be owned by the callback, so hold onto a temporary
+  // pointer to it so we can still call Start on it.
+  BlobReader* raw_reader = reader.get();
+  base::OnceClosure wrapped = base::BindOnce(
+      [](BlobReadCallback callback, std::unique_ptr<BlobReader> reader) {
+        std::move(callback).Run(std::move(reader->blob_data_),
+                                *reader->blob_length_);
+      },
+      std::move(callback), std::move(reader));
+  raw_reader->Start(std::move(wrapped));
+}
+
+BlobReader::BlobReader(mojo::PendingRemote<blink::mojom::Blob> blob,
+                       base::Optional<Range> range)
+    : blob_(std::move(blob)), read_range_(std::move(range)) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  blob_.set_disconnect_handler(
+      base::BindOnce(&BlobReader::Failed, base::Unretained(this)));
+}
+
+void BlobReader::Start(base::OnceClosure callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  callback_ = std::move(callback);
+
   mojo::ScopedDataPipeProducerHandle producer_handle;
   mojo::ScopedDataPipeConsumerHandle consumer_handle;
   MojoResult result =
@@ -81,11 +111,11 @@
 }
 
 void BlobReader::Failed() {
-  std::move(callback_).Run(std::make_unique<std::string>(), 0);
-  delete this;
+  blob_length_ = 0;
+  blob_data_ = std::make_unique<std::string>();
+  std::move(callback_).Run();
 }
 
 void BlobReader::Succeeded() {
-  std::move(callback_).Run(std::move(blob_data_), *blob_length_);
-  delete this;
+  std::move(callback_).Run();
 }
diff --git a/extensions/browser/blob_reader.h b/extensions/browser/blob_reader.h
index fb3e6d5..1e2b06b 100644
--- a/extensions/browser/blob_reader.h
+++ b/extensions/browser/blob_reader.h
@@ -23,8 +23,7 @@
 class BrowserContext;
 }
 
-// This class may only be used from the UI thread. It self-deletes when finished
-// reading.
+// This class may only be used from the UI thread.
 class BlobReader : public blink::mojom::BlobReaderClient,
                    public mojo::DataPipeDrainer::Client {
  public:
@@ -35,18 +34,32 @@
                                   int64_t blob_total_size)>
       BlobReadCallback;
 
-  BlobReader(content::BrowserContext* browser_context,
-             const std::string& blob_uuid,
-             BlobReadCallback callback);
-  BlobReader(mojo::PendingRemote<blink::mojom::Blob> blob,
-             BlobReadCallback callback);
+  static void Read(content::BrowserContext* browser_context,
+                   const std::string& blob_uuid,
+                   BlobReadCallback callback,
+                   int64_t offset,
+                   int64_t length);
+  static void Read(content::BrowserContext* browser_context,
+                   const std::string& blob_uuid,
+                   BlobReadCallback callback);
+
   ~BlobReader() override;
 
-  void SetByteRange(int64_t offset, int64_t length);
-
-  void Start();
-
  private:
+  struct Range {
+    uint64_t offset;
+    uint64_t length;
+  };
+
+  static void Read(content::BrowserContext* browser_context,
+                   const std::string& blob_uuid,
+                   BlobReadCallback callback,
+                   base::Optional<BlobReader::Range> range);
+
+  BlobReader(mojo::PendingRemote<blink::mojom::Blob> blob,
+             base::Optional<Range> range);
+  void Start(base::OnceClosure callback);
+
   // blink::mojom::BlobReaderClient:
   void OnCalculatedSize(uint64_t total_size,
                         uint64_t expected_content_size) override;
@@ -59,12 +72,8 @@
   void Failed();
   void Succeeded();
 
-  BlobReadCallback callback_;
+  base::OnceClosure callback_;
   mojo::Remote<blink::mojom::Blob> blob_;
-  struct Range {
-    uint64_t offset;
-    uint64_t length;
-  };
   base::Optional<Range> read_range_;
 
   mojo::Receiver<blink::mojom::BlobReaderClient> receiver_{this};
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index 8f5b6f6..a992551 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -227,6 +227,10 @@
                                      gl::kGLImplementationStubName);
   }
 
+  if (enable_protected_graphics) {
+    launch_command.AppendSwitch(switches::kEnforceVulkanProtectedMemory);
+  }
+
   if (enable_widevine) {
     launch_command.AppendSwitch(switches::kEnableWidevine);
   }
diff --git a/google_apis/drive/base_requests.cc b/google_apis/drive/base_requests.cc
index ef79519c..1418377 100644
--- a/google_apis/drive/base_requests.cc
+++ b/google_apis/drive/base_requests.cc
@@ -30,6 +30,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
 #include "net/http/http_util.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace {
 
@@ -83,7 +84,7 @@
 // Returns response headers as a string. Returns a warning message if
 // |response_head| does not contain a valid response. Used only for debugging.
 std::string GetResponseHeadersAsString(
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   // Check that response code indicates response headers are valid (i.e. not
   // malformed) before we retrieve the headers.
   if (response_head.headers->response_code() == -1)
@@ -394,7 +395,7 @@
 
 void UrlFetchRequestBase::OnResponseStarted(
     const GURL& final_url,
-    const network::ResourceResponseHead& response_head) {
+    const network::mojom::URLResponseHead& response_head) {
   DVLOG(1) << "Response headers:\n"
            << GetResponseHeadersAsString(response_head);
   response_content_length_ = response_head.content_length;
@@ -480,7 +481,7 @@
 
 void UrlFetchRequestBase::OnOutputFileClosed(bool success) {
   DCHECK(download_data_);
-  const network::ResourceResponseHead* response_info;
+  const network::mojom::URLResponseHead* response_info;
   if (url_loader_) {
     response_info = url_loader_->ResponseInfo();
     if (response_info) {
@@ -600,7 +601,7 @@
 EntryActionRequest::~EntryActionRequest() {}
 
 void EntryActionRequest::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   callback_.Run(GetErrorCode());
@@ -630,7 +631,7 @@
 InitiateUploadRequestBase::~InitiateUploadRequestBase() {}
 
 void InitiateUploadRequestBase::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   std::string upload_location;
@@ -698,7 +699,7 @@
 }
 
 void UploadRangeRequestBase::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   DriveApiErrorCode code = GetErrorCode();
@@ -1012,7 +1013,7 @@
 }
 
 void DownloadFileRequestBase::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   download_action_callback_.Run(GetErrorCode(), response_file);
diff --git a/google_apis/drive/base_requests.h b/google_apis/drive/base_requests.h
index 5d056c2..3960a64 100644
--- a/google_apis/drive/base_requests.h
+++ b/google_apis/drive/base_requests.h
@@ -22,9 +22,9 @@
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "google_apis/drive/drive_api_error_codes.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -182,7 +182,7 @@
   // |response_body| may be truncated and only contain the starting portion
   // of the resource.
   virtual void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) = 0;
 
@@ -258,7 +258,7 @@
 
   // Called when the SimpleURLLoader first receives a response.
   void OnResponseStarted(const GURL& final_url,
-                         const network::ResourceResponseHead& response_head);
+                         const network::mojom::URLResponseHead& response_head);
 
   // Invokes callback with |code| and request to delete the request to
   // |sender_|.
@@ -338,7 +338,7 @@
  protected:
   // Overridden from UrlFetchRequestBase.
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
@@ -380,7 +380,7 @@
 
   // UrlFetchRequestBase overrides.
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
@@ -430,7 +430,7 @@
   GURL GetURL() const override;
   std::string GetRequestType() const override;
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
@@ -656,7 +656,7 @@
   void GetOutputFilePath(base::FilePath* local_file_path,
                          GetContentCallback* get_content_callback) override;
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
diff --git a/google_apis/drive/base_requests_unittest.cc b/google_apis/drive/base_requests_unittest.cc
index 7602b4b..98eaee2 100644
--- a/google_apis/drive/base_requests_unittest.cc
+++ b/google_apis/drive/base_requests_unittest.cc
@@ -25,6 +25,7 @@
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/test/test_network_service_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -49,7 +50,7 @@
  protected:
   GURL GetURL() const override { return url_; }
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override {
     callback_.Run(GetErrorCode());
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index c780569..bb38f8220 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -27,6 +27,7 @@
 #include "google_apis/drive/time_util.h"
 #include "net/base/url_util.h"
 #include "net/http/http_response_headers.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace google_apis {
 namespace drive {
@@ -1138,7 +1139,7 @@
 }
 
 void SingleBatchableDelegateRequest::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   delegate_->NotifyResult(
@@ -1319,7 +1320,7 @@
 }
 
 void BatchUploadRequest::ProcessURLFetchResults(
-    const network::ResourceResponseHead* response_head,
+    const network::mojom::URLResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
   if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) {
diff --git a/google_apis/drive/drive_api_requests.h b/google_apis/drive/drive_api_requests.h
index 4ec8bd9..322de91 100644
--- a/google_apis/drive/drive_api_requests.h
+++ b/google_apis/drive/drive_api_requests.h
@@ -24,6 +24,7 @@
 #include "google_apis/drive/drive_api_parser.h"
 #include "google_apis/drive/drive_api_url_generator.h"
 #include "google_apis/drive/drive_common_callbacks.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 
 namespace google_apis {
 
@@ -151,7 +152,7 @@
  protected:
   // UrlFetchRequestBase overrides.
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override {
     DriveApiErrorCode error = GetErrorCode();
@@ -1159,7 +1160,7 @@
                       std::string* upload_content) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void OnUploadProgress(int64_t current, int64_t total);
@@ -1222,7 +1223,7 @@
   bool GetContentData(std::string* upload_content_type,
                       std::string* upload_content) override;
   void ProcessURLFetchResults(
-      const network::ResourceResponseHead* response_head,
+      const network::mojom::URLResponseHead* response_head,
       base::FilePath response_file,
       std::string response_body) override;
   void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override;
diff --git a/google_apis/gaia/oauth2_api_call_flow.cc b/google_apis/gaia/oauth2_api_call_flow.cc
index 7ef2fdd..1a1fa801 100644
--- a/google_apis/gaia/oauth2_api_call_flow.cc
+++ b/google_apis/gaia/oauth2_api_call_flow.cc
@@ -17,6 +17,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace {
 static const char kAuthorizationValueFormat[] = "Bearer %s";
diff --git a/google_apis/gaia/oauth2_api_call_flow.h b/google_apis/gaia/oauth2_api_call_flow.h
index e3e214ab..a74226e 100644
--- a/google_apis/gaia/oauth2_api_call_flow.h
+++ b/google_apis/gaia/oauth2_api_call_flow.h
@@ -11,10 +11,10 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace network {
-struct ResourceResponseHead;
 class SimpleURLLoader;
 class SharedURLLoaderFactory;
 }
@@ -49,13 +49,15 @@
   // Sub-classes can expose an appropriate observer interface by implementing
   // these template methods.
   // Called when the API call finished successfully. |body| may be null.
-  virtual void ProcessApiCallSuccess(const network::ResourceResponseHead* head,
-                                     std::unique_ptr<std::string> body) = 0;
+  virtual void ProcessApiCallSuccess(
+      const network::mojom::URLResponseHead* head,
+      std::unique_ptr<std::string> body) = 0;
 
   // Called when the API call failed. |head| or |body| might be null.
-  virtual void ProcessApiCallFailure(int net_error,
-                                     const network::ResourceResponseHead* head,
-                                     std::unique_ptr<std::string> body) = 0;
+  virtual void ProcessApiCallFailure(
+      int net_error,
+      const network::mojom::URLResponseHead* head,
+      std::unique_ptr<std::string> body) = 0;
 
   virtual net::PartialNetworkTrafficAnnotationTag
   GetNetworkTrafficAnnotationTag() = 0;
diff --git a/google_apis/gaia/oauth2_api_call_flow_unittest.cc b/google_apis/gaia/oauth2_api_call_flow_unittest.cc
index 4d1c16a..8534328 100644
--- a/google_apis/gaia/oauth2_api_call_flow_unittest.cc
+++ b/google_apis/gaia/oauth2_api_call_flow_unittest.cc
@@ -22,6 +22,7 @@
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "services/network/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -54,11 +55,11 @@
   MOCK_METHOD0(CreateApiCallUrl, GURL());
   MOCK_METHOD0(CreateApiCallBody, std::string());
   MOCK_METHOD2(ProcessApiCallSuccess,
-               void(const network::ResourceResponseHead* head,
+               void(const network::mojom::URLResponseHead* head,
                     std::unique_ptr<std::string> body));
   MOCK_METHOD3(ProcessApiCallFailure,
                void(int net_error,
-                    const network::ResourceResponseHead* head,
+                    const network::mojom::URLResponseHead* head,
                     std::unique_ptr<std::string> body));
   MOCK_METHOD1(ProcessNewAccessToken, void(const std::string& access_token));
   MOCK_METHOD1(ProcessMintAccessTokenFailure,
diff --git a/google_apis/gaia/oauth2_mint_token_flow.cc b/google_apis/gaia/oauth2_mint_token_flow.cc
index 98d8da5f..b75b12b7 100644
--- a/google_apis/gaia/oauth2_mint_token_flow.cc
+++ b/google_apis/gaia/oauth2_mint_token_flow.cc
@@ -22,7 +22,7 @@
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/base/escape.h"
 #include "net/base/net_errors.h"
-#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace {
 
@@ -56,7 +56,7 @@
 
 static GoogleServiceAuthError CreateAuthError(
     int net_error,
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   if (net_error == net::ERR_ABORTED) {
     return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
@@ -186,7 +186,7 @@
 }
 
 void OAuth2MintTokenFlow::ProcessApiCallSuccess(
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   std::string response_body;
   if (body)
@@ -230,7 +230,7 @@
 
 void OAuth2MintTokenFlow::ProcessApiCallFailure(
     int net_error,
-    const network::ResourceResponseHead* head,
+    const network::mojom::URLResponseHead* head,
     std::unique_ptr<std::string> body) {
   ReportFailure(CreateAuthError(net_error, head, std::move(body)));
 }
diff --git a/google_apis/gaia/oauth2_mint_token_flow.h b/google_apis/gaia/oauth2_mint_token_flow.h
index caed408..ceec9f3d9 100644
--- a/google_apis/gaia/oauth2_mint_token_flow.h
+++ b/google_apis/gaia/oauth2_mint_token_flow.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "google_apis/gaia/oauth2_api_call_flow.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 class GoogleServiceAuthError;
@@ -103,10 +104,10 @@
   GURL CreateApiCallUrl() override;
   std::string CreateApiCallBody() override;
 
-  void ProcessApiCallSuccess(const network::ResourceResponseHead* head,
+  void ProcessApiCallSuccess(const network::mojom::URLResponseHead* head,
                              std::unique_ptr<std::string> body) override;
   void ProcessApiCallFailure(int net_error,
-                             const network::ResourceResponseHead* head,
+                             const network::mojom::URLResponseHead* head,
                              std::unique_ptr<std::string> body) override;
   net::PartialNetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag()
       override;
diff --git a/google_apis/gaia/oauth2_mint_token_flow_unittest.cc b/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
index 0ccae2d..16231457 100644
--- a/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
+++ b/google_apis/gaia/oauth2_mint_token_flow_unittest.cc
@@ -17,6 +17,7 @@
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
 #include "net/base/net_errors.h"
 #include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -297,56 +298,59 @@
 }
 
 TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess) {
-  network::ResourceResponseHead head_200 =
+  network::mojom::URLResponseHeadPtr head_200 =
       network::CreateResourceResponseHead(net::HTTP_OK);
 
   {  // No body.
     CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
     EXPECT_CALL(delegate_, OnMintTokenFailure(_));
-    flow_->ProcessApiCallSuccess(&head_200, nullptr);
+    flow_->ProcessApiCallSuccess(head_200.get(), nullptr);
   }
   {  // Bad json.
     CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
     EXPECT_CALL(delegate_, OnMintTokenFailure(_));
-    flow_->ProcessApiCallSuccess(&head_200,
+    flow_->ProcessApiCallSuccess(head_200.get(),
                                  std::make_unique<std::string>("foo"));
   }
   {  // Valid json: no access token.
     CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
     EXPECT_CALL(delegate_, OnMintTokenFailure(_));
     flow_->ProcessApiCallSuccess(
-        &head_200, std::make_unique<std::string>(kTokenResponseNoAccessToken));
+        head_200.get(),
+        std::make_unique<std::string>(kTokenResponseNoAccessToken));
   }
   {  // Valid json: good token response.
     CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE);
     EXPECT_CALL(delegate_, OnMintTokenSuccess("at1", 3600));
     flow_->ProcessApiCallSuccess(
-        &head_200, std::make_unique<std::string>(kValidTokenResponse));
+        head_200.get(), std::make_unique<std::string>(kValidTokenResponse));
   }
   {  // Valid json: no description.
     CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
     EXPECT_CALL(delegate_, OnMintTokenFailure(_));
     flow_->ProcessApiCallSuccess(
-        &head_200,
+        head_200.get(),
         std::make_unique<std::string>(kIssueAdviceResponseNoDescription));
   }
   {  // Valid json: no detail.
     CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
     EXPECT_CALL(delegate_, OnMintTokenFailure(_));
     flow_->ProcessApiCallSuccess(
-        &head_200, std::make_unique<std::string>(kIssueAdviceResponseNoDetail));
+        head_200.get(),
+        std::make_unique<std::string>(kIssueAdviceResponseNoDetail));
   }
   {  // Valid json: good issue advice response.
     CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE);
     IssueAdviceInfo ia(CreateIssueAdvice());
     EXPECT_CALL(delegate_, OnIssueAdviceSuccess(ia));
     flow_->ProcessApiCallSuccess(
-        &head_200, std::make_unique<std::string>(kValidIssueAdviceResponse));
+        head_200.get(),
+        std::make_unique<std::string>(kValidIssueAdviceResponse));
   }
 }
 
 TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallFailure) {
-  network::ResourceResponseHead head;
+  network::mojom::URLResponseHead head;
   {  // Null delegate should work fine.
     CreateFlow(nullptr, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE, "");
     flow_->ProcessApiCallFailure(net::ERR_FAILED, &head, nullptr);
diff --git a/gpu/OWNERS b/gpu/OWNERS
index 8dc8f05..8d32d1c 100644
--- a/gpu/OWNERS
+++ b/gpu/OWNERS
@@ -13,4 +13,10 @@
 # Passthrough command decoder
 per-file *passthrough*=geofflang@chromium.org
 
+# Shared Image and Media on Android
+per-file *shared_image_video*=vikassoni@chromium.org
+per-file *android*=vikassoni@chromium.org
+per-file *image_reader*=vikassoni@chromium.org
+per-file *hardwarebuffer*=vikassoni@chromium.org
+
 # COMPONENT: Internals>GPU>Internals
diff --git a/gpu/command_buffer/service/shared_image_video.cc b/gpu/command_buffer/service/shared_image_video.cc
index 18d3848..dcee3a7 100644
--- a/gpu/command_buffer/service/shared_image_video.cc
+++ b/gpu/command_buffer/service/shared_image_video.cc
@@ -180,20 +180,22 @@
   context_state_ = nullptr;
 }
 
-base::Optional<VulkanYCbCrInfo> SharedImageVideo::GetYcbcrInfo() {
+base::Optional<VulkanYCbCrInfo> SharedImageVideo::GetYcbcrInfo(
+    StreamTextureSharedImageInterface* stream_texture_sii,
+    scoped_refptr<SharedContextState> context_state) {
   // For non-vulkan context, return null.
-  if (!context_state_->GrContextIsVulkan())
+  if (!context_state->GrContextIsVulkan())
     return base::nullopt;
 
   // GetAHardwareBuffer() renders the latest image and gets AHardwareBuffer
   // from it.
-  auto scoped_hardware_buffer = stream_texture_sii_->GetAHardwareBuffer();
+  auto scoped_hardware_buffer = stream_texture_sii->GetAHardwareBuffer();
   if (!scoped_hardware_buffer) {
     return base::nullopt;
   }
 
   DCHECK(scoped_hardware_buffer->buffer());
-  auto* context_provider = context_state_->vk_context_provider();
+  auto* context_provider = context_state->vk_context_provider();
   VulkanImplementation* vk_implementation =
       context_provider->GetVulkanImplementation();
   VkDevice vk_device = context_provider->GetDeviceQueue()->GetVulkanDevice();
diff --git a/gpu/command_buffer/service/shared_image_video.h b/gpu/command_buffer/service/shared_image_video.h
index da3079d..58800e2 100644
--- a/gpu/command_buffer/service/shared_image_video.h
+++ b/gpu/command_buffer/service/shared_image_video.h
@@ -54,7 +54,9 @@
 
   // Returns ycbcr information. This is only valid in vulkan context and
   // nullopt for other context.
-  base::Optional<VulkanYCbCrInfo> GetYcbcrInfo();
+  static base::Optional<VulkanYCbCrInfo> GetYcbcrInfo(
+      StreamTextureSharedImageInterface* stream_texture_sii,
+      scoped_refptr<SharedContextState> context_state);
 
  protected:
   std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index 6e0bfaec..2c7dff7 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -43,8 +43,8 @@
 
 namespace {
 // Constants for 3D touch application static shortcuts.
-NSString* const kShortcutNewTab = @"OpenNewTab";
-NSString* const kShortcutNewIncognitoTab = @"OpenIncognitoTab";
+NSString* const kShortcutNewSearch = @"OpenNewSearch";
+NSString* const kShortcutNewIncognitoSearch = @"OpenIncognitoSearch";
 NSString* const kShortcutVoiceSearch = @"OpenVoiceSearch";
 NSString* const kShortcutQRScanner = @"OpenQRScanner";
 
@@ -337,30 +337,33 @@
       initWithExternalURL:GURL(kChromeUINewTabURL)
               completeURL:GURL(kChromeUINewTabURL)];
 
-  if ([shortcutItem.type isEqualToString:kShortcutNewTab]) {
-    base::RecordAction(UserMetricsAction("ApplicationShortcut.NewTabPressed"));
-    [startupInformation setStartupParameters:startupParams];
+  if ([shortcutItem.type isEqualToString:kShortcutNewSearch]) {
+    base::RecordAction(
+        UserMetricsAction("ApplicationShortcut.NewSearchPressed"));
+    startupParams.postOpeningAction = FOCUS_OMNIBOX;
+    startupInformation.startupParameters = startupParams;
     return YES;
 
-  } else if ([shortcutItem.type isEqualToString:kShortcutNewIncognitoTab]) {
+  } else if ([shortcutItem.type isEqualToString:kShortcutNewIncognitoSearch]) {
     base::RecordAction(
-        UserMetricsAction("ApplicationShortcut.NewIncognitoTabPressed"));
-    [startupParams setLaunchInIncognito:YES];
-    [startupInformation setStartupParameters:startupParams];
+        UserMetricsAction("ApplicationShortcut.NewIncognitoSearchPressed"));
+    startupParams.launchInIncognito = YES;
+    startupParams.postOpeningAction = FOCUS_OMNIBOX;
+    startupInformation.startupParameters = startupParams;
     return YES;
 
   } else if ([shortcutItem.type isEqualToString:kShortcutVoiceSearch]) {
     base::RecordAction(
         UserMetricsAction("ApplicationShortcut.VoiceSearchPressed"));
-    [startupParams setPostOpeningAction:START_VOICE_SEARCH];
-    [startupInformation setStartupParameters:startupParams];
+    startupParams.postOpeningAction = START_VOICE_SEARCH;
+    startupInformation.startupParameters = startupParams;
     return YES;
 
   } else if ([shortcutItem.type isEqualToString:kShortcutQRScanner]) {
     base::RecordAction(
         UserMetricsAction("ApplicationShortcut.ScanQRCodePressed"));
-    [startupParams setPostOpeningAction:START_QR_CODE_SCANNER];
-    [startupInformation setStartupParameters:startupParams];
+    startupParams.postOpeningAction = START_QR_CODE_SCANNER;
+    startupInformation.startupParameters = startupParams;
     return YES;
   }
 
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index 04f8229..d63f2293 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -587,8 +587,8 @@
   [fakeStartupInformation setIsPresentingFirstRunUI:NO];
 
   NSArray* parametersToTest = @[
-    @[ @"OpenNewTab", @NO, @(NO_ACTION) ],
-    @[ @"OpenIncognitoTab", @YES, @(NO_ACTION) ],
+    @[ @"OpenNewSearch", @NO, @(FOCUS_OMNIBOX) ],
+    @[ @"OpenIncognitoSearch", @YES, @(FOCUS_OMNIBOX) ],
     @[ @"OpenVoiceSearch", @NO, @(START_VOICE_SEARCH) ],
     @[ @"OpenQRScanner", @NO, @(START_QR_CODE_SCANNER) ]
   ];
@@ -636,7 +636,7 @@
   [[[startupInformationMock stub] andReturnValue:@YES] isPresentingFirstRunUI];
 
   UIApplicationShortcutItem* shortcut =
-      [[UIApplicationShortcutItem alloc] initWithType:@"OpenNewTab"
+      [[UIApplicationShortcutItem alloc] initWithType:@"OpenNewSearch"
                                        localizedTitle:@""];
 
   swizzleHandleStartupParameters();
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn
index f1f5c66..f55bcd2 100644
--- a/ios/chrome/app/resources/BUILD.gn
+++ b/ios/chrome/app/resources/BUILD.gn
@@ -151,19 +151,19 @@
   ]
 }
 
-imageset("quick_action_new_incognito_tab") {
+imageset("quick_action_incognito_search") {
   sources = [
-    "quick_action_new_incognito_tab.imageset/Contents.json",
-    "quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@2x.png",
-    "quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@3x.png",
+    "quick_action_incognito_search.imageset/Contents.json",
+    "quick_action_incognito_search.imageset/quick_action_incognito_search@2x.png",
+    "quick_action_incognito_search.imageset/quick_action_incognito_search@3x.png",
   ]
 }
 
-imageset("quick_action_new_tab") {
+imageset("quick_action_new_search") {
   sources = [
-    "quick_action_new_tab.imageset/Contents.json",
-    "quick_action_new_tab.imageset/quick_action_new_tab@2x.png",
-    "quick_action_new_tab.imageset/quick_action_new_tab@3x.png",
+    "quick_action_new_search.imageset/Contents.json",
+    "quick_action_new_search.imageset/quick_action_new_search@2x.png",
+    "quick_action_new_search.imageset/quick_action_new_search@3x.png",
   ]
 }
 
@@ -185,8 +185,8 @@
 
 group("quick_action_icons") {
   public_deps = [
-    ":quick_action_new_incognito_tab",
-    ":quick_action_new_tab",
+    ":quick_action_incognito_search",
+    ":quick_action_new_search",
     ":quick_action_qr_scanner",
     ":quick_action_voice_search",
   ]
diff --git a/ios/chrome/app/resources/Info.plist b/ios/chrome/app/resources/Info.plist
index 5706968..2251a77 100644
--- a/ios/chrome/app/resources/Info.plist
+++ b/ios/chrome/app/resources/Info.plist
@@ -92,19 +92,19 @@
 	<array>
 		<dict>
 			<key>UIApplicationShortcutItemIconFile</key>
-			<string>quick_action_new_tab</string>
+			<string>quick_action_new_search</string>
 			<key>UIApplicationShortcutItemTitle</key>
-			<string>IDS_IOS_APPLICATION_SHORTCUT_NEWTAB_TITLE</string>
+			<string>IDS_IOS_APPLICATION_SHORTCUT_NEWSEARCH_TITLE</string>
 			<key>UIApplicationShortcutItemType</key>
-			<string>OpenNewTab</string>
+			<string>OpenNewSearch</string>
 		</dict>
 		<dict>
 			<key>UIApplicationShortcutItemIconFile</key>
-			<string>quick_action_new_incognito_tab</string>
+			<string>quick_action_incognito_search</string>
 			<key>UIApplicationShortcutItemTitle</key>
-			<string>IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_TITLE</string>
+			<string>IDS_IOS_APPLICATION_SHORTCUT_INCOGNITOSEARCH_TITLE</string>
 			<key>UIApplicationShortcutItemType</key>
-			<string>OpenIncognitoTab</string>
+			<string>OpenIncognitoSearch</string>
 		</dict>
 		<dict>
 			<key>UIApplicationShortcutItemIconFile</key>
diff --git a/ios/chrome/app/resources/chrome_localize_strings_config.plist b/ios/chrome/app/resources/chrome_localize_strings_config.plist
index c0f2373..3b391a5 100644
--- a/ios/chrome/app/resources/chrome_localize_strings_config.plist
+++ b/ios/chrome/app/resources/chrome_localize_strings_config.plist
@@ -95,8 +95,8 @@
 					<key>output</key>
 					<string>NSFaceIDUsageDescription</string>
 				</dict>
-				<string>IDS_IOS_APPLICATION_SHORTCUT_NEWTAB_TITLE</string>
-				<string>IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_TITLE</string>
+				<string>IDS_IOS_APPLICATION_SHORTCUT_NEWSEARCH_TITLE</string>
+				<string>IDS_IOS_APPLICATION_SHORTCUT_INCOGNITOSEARCH_TITLE</string>
 				<string>IDS_IOS_APPLICATION_SHORTCUT_VOICE_SEARCH_TITLE</string>
 				<string>IDS_IOS_APPLICATION_SHORTCUT_QR_SCANNER_TITLE</string>
 			</array>
diff --git a/ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json b/ios/chrome/app/resources/quick_action_incognito_search.imageset/Contents.json
similarity index 67%
copy from ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json
copy to ios/chrome/app/resources/quick_action_incognito_search.imageset/Contents.json
index 284873ef..2035055 100644
--- a/ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json
+++ b/ios/chrome/app/resources/quick_action_incognito_search.imageset/Contents.json
@@ -3,12 +3,12 @@
         {
             "idiom": "universal",
             "scale": "2x",
-            "filename": "quick_action_new_tab@2x.png"
+            "filename": "quick_action_incognito_search@2x.png"
         },
         {
             "idiom": "universal",
             "scale": "3x",
-            "filename": "quick_action_new_tab@3x.png"
+            "filename": "quick_action_incognito_search@3x.png"
         }
     ],
     "info": {
diff --git a/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@2x.png b/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@2x.png
new file mode 100644
index 0000000..83f4a4958
--- /dev/null
+++ b/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@2x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@3x.png b/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@3x.png
new file mode 100644
index 0000000..0ec88884
--- /dev/null
+++ b/ios/chrome/app/resources/quick_action_incognito_search.imageset/quick_action_incognito_search@3x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/Contents.json b/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/Contents.json
deleted file mode 100644
index 37661b4..0000000
--- a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/Contents.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "images": [
-        {
-            "idiom": "universal",
-            "scale": "2x",
-            "filename": "quick_action_new_incognito_tab@2x.png"
-        },
-        {
-            "idiom": "universal",
-            "scale": "3x",
-            "filename": "quick_action_new_incognito_tab@3x.png"
-        }
-    ],
-    "info": {
-        "version": 1,
-        "author": "xcode"
-    }
-}
diff --git a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@2x.png b/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@2x.png
deleted file mode 100644
index 636b00b..0000000
--- a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@2x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@3x.png b/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@3x.png
deleted file mode 100644
index b683c15a..0000000
--- a/ios/chrome/app/resources/quick_action_new_incognito_tab.imageset/quick_action_new_incognito_tab@3x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json b/ios/chrome/app/resources/quick_action_new_search.imageset/Contents.json
similarity index 69%
rename from ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json
rename to ios/chrome/app/resources/quick_action_new_search.imageset/Contents.json
index 284873ef..55b3d62 100644
--- a/ios/chrome/app/resources/quick_action_new_tab.imageset/Contents.json
+++ b/ios/chrome/app/resources/quick_action_new_search.imageset/Contents.json
@@ -3,12 +3,12 @@
         {
             "idiom": "universal",
             "scale": "2x",
-            "filename": "quick_action_new_tab@2x.png"
+            "filename": "quick_action_new_search@2x.png"
         },
         {
             "idiom": "universal",
             "scale": "3x",
-            "filename": "quick_action_new_tab@3x.png"
+            "filename": "quick_action_new_search@3x.png"
         }
     ],
     "info": {
diff --git a/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@2x.png b/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@2x.png
new file mode 100644
index 0000000..9fad48d
--- /dev/null
+++ b/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@2x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@3x.png b/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@3x.png
new file mode 100644
index 0000000..525af72
--- /dev/null
+++ b/ios/chrome/app/resources/quick_action_new_search.imageset/quick_action_new_search@3x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@2x.png b/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@2x.png
deleted file mode 100644
index 45c4614..0000000
--- a/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@2x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@3x.png b/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@3x.png
deleted file mode 100644
index df4d68e..0000000
--- a/ios/chrome/app/resources/quick_action_new_tab.imageset/quick_action_new_tab@3x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@2x.png b/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@2x.png
index a8321d9..5c41bd5 100644
--- a/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@2x.png
+++ b/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@2x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@3x.png b/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@3x.png
index 81402caa..170c669e 100644
--- a/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@3x.png
+++ b/ios/chrome/app/resources/quick_action_qr_scanner.imageset/quick_action_qr_scanner@3x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@2x.png b/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@2x.png
index db711a6..3ea943c9 100644
--- a/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@2x.png
+++ b/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@2x.png
Binary files differ
diff --git a/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@3x.png b/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@3x.png
index cbb9647..80c1d444 100644
--- a/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@3x.png
+++ b/ios/chrome/app/resources/quick_action_voice_search.imageset/quick_action_voice_search@3x.png
Binary files differ
diff --git a/ios/chrome/app/spotlight/actions_spotlight_manager.mm b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
index 5c1844b..0fe8b55 100644
--- a/ios/chrome/app/spotlight/actions_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
@@ -147,13 +147,13 @@
           NSString* voiceSearchAction =
               base::SysUTF8ToNSString(spotlight::kSpotlightActionVoiceSearch);
 
-          NSString* newTabTitle =
-              l10n_util::GetNSString(IDS_IOS_APPLICATION_SHORTCUT_NEWTAB_TITLE);
+          NSString* newTabTitle = l10n_util::GetNSString(
+              IDS_IOS_APPLICATION_SHORTCUT_NEWSEARCH_TITLE);
           NSString* newTabAction =
               base::SysUTF8ToNSString(spotlight::kSpotlightActionNewTab);
 
           NSString* incognitoTitle = l10n_util::GetNSString(
-              IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_TITLE);
+              IDS_IOS_APPLICATION_SHORTCUT_INCOGNITOSEARCH_TITLE);
           NSString* incognitoAction = base::SysUTF8ToNSString(
               spotlight::kSpotlightActionNewIncognitoTab);
 
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 8e8db6e..cb5bbe8 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -212,11 +212,11 @@
       <message name="IDS_IOS_USE_SUGGESTED_PASSWORD" desc="Button title in a suggested password popup asking user if they want to use the suggested password. [Length: 20em] [iOS only]">
         Use Suggested Password
       </message>
-      <message name="IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_TITLE" desc="Message when opening a New Incognito Tab from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to create a new Incognito tab.">
-        New Incognito Tab
+      <message name="IDS_IOS_APPLICATION_SHORTCUT_INCOGNITOSEARCH_TITLE" desc="Message when opening a New Incognito Search from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to create a new Incognito tab.">
+       Incognito Search
       </message>
-      <message name="IDS_IOS_APPLICATION_SHORTCUT_NEWTAB_TITLE" desc="Message when opening a New Tab from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to create a new tab.">
-        New Tab
+      <message name="IDS_IOS_APPLICATION_SHORTCUT_NEWSEARCH_TITLE" desc="Message when opening a New Search from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to create a new tab.">
+        New Search
       </message>
       <message name="IDS_IOS_APPLICATION_SHORTCUT_QR_SCANNER_TITLE" desc="Message when opening a QR Scanner from springboard force touch static shortcuts. [Length: unlimited] [iOS only].">
         Scan QR Code
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 65dfa89..b7a4c5d 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -326,11 +326,9 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillRichMetadataQueries)},
     {"fullscreen-viewport-adjustment-experiment",
-     flag_descriptions::kFullscreenViewportAdjustmentExperimentName,
-     flag_descriptions::kFullscreenViewportAdjustmentExperimentDescription,
-     flags_ui::kOsIos,
-     MULTI_VALUE_TYPE(
-         fullscreen::features::kViewportAdjustmentExperimentChoices)},
+     flag_descriptions::kFullscreenSmoothScrollingName,
+     flag_descriptions::kFullscreenSmoothScrollingDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(fullscreen::features::kSmoothScrollingDefault)},
     {"autofill-enforce-min-required-fields-for-heuristics",
      flag_descriptions::kAutofillEnforceMinRequiredFieldsForHeuristicsName,
      flag_descriptions::
@@ -509,9 +507,6 @@
     {"language-settings", flag_descriptions::kLanguageSettingsName,
      flag_descriptions::kLanguageSettingsDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kLanguageSettings)},
-    {"lock-bottom-toolbar", flag_descriptions::kLockBottomToolbarName,
-     flag_descriptions::kLockBottomToolbarDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(fullscreen::features::kLockBottomToolbar)},
     {"toolbar-new-tab-button", flag_descriptions::kToolbarNewTabButtonName,
      flag_descriptions::kToolbarNewTabButtonDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kToolbarNewTabButton)},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 31568f1..9ffe795 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -204,11 +204,11 @@
 const char kFindInPageiFrameDescription[] =
     "When enabled, Find In Page will search in iFrames.";
 
-const char kFullscreenViewportAdjustmentExperimentName[] =
-    "Fullscreen Viewport Adjustment Mode";
-const char kFullscreenViewportAdjustmentExperimentDescription[] =
-    "The different ways in which the web view's viewport is updated for scroll "
-    "events.  The default option updates the web view's frame.";
+const char kFullscreenSmoothScrollingName[] = "Fullscreen Smooth Scrolling";
+const char kFullscreenSmoothScrollingDescription[] =
+    "When enabled, the web view's insets are updated for scoll events. If "
+    "disabled, the "
+    "the web view's frame are updated.";
 
 const char kIgnoresViewportScaleLimitsName[] = "Ignore Viewport Scale Limits";
 const char kIgnoresViewportScaleLimitsDescription[] =
@@ -230,11 +230,6 @@
     "Enables the Language Settings page allowing modifications to user "
     "preferred languages and translate preferences.";
 
-const char kLockBottomToolbarName[] = "Lock bottom toolbar";
-const char kLockBottomToolbarDescription[] =
-    "When enabled, the bottom toolbar will not get collapsed when scrolling "
-    "into fullscreen mode.";
-
 const char kMarkHttpAsName[] = "Mark non-secure origins as non-secure";
 const char kMarkHttpAsDescription[] = "Change the UI treatment for HTTP pages";
 
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index b6f2e24..7e0b7e40 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -167,10 +167,10 @@
 extern const char kFindInPageiFrameName[];
 extern const char kFindInPageiFrameDescription[];
 
-// Title and description for the command line switch used to determine the
-// active fullscreen viewport adjustment mode.
-extern const char kFullscreenViewportAdjustmentExperimentName[];
-extern const char kFullscreenViewportAdjustmentExperimentDescription[];
+// Title and description for the flag to update the web view's insets for scroll
+// events.
+extern const char kFullscreenSmoothScrollingName[];
+extern const char kFullscreenSmoothScrollingDescription[];
 
 // Title and description for the flag to ignore viewport scale limits.
 extern const char kIgnoresViewportScaleLimitsName[];
@@ -189,10 +189,6 @@
 extern const char kLanguageSettingsName[];
 extern const char kLanguageSettingsDescription[];
 
-// Title and description for the flag to lock the bottom toolbar into place.
-extern const char kLockBottomToolbarName[];
-extern const char kLockBottomToolbarDescription[];
-
 // Title, description, and options for the MarkHttpAs setting that controls
 // display of omnibox warnings about non-secure pages.
 extern const char kMarkHttpAsName[];
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 9efe2f2e..32d67dd1 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -597,9 +597,6 @@
 // The webState of the active tab.
 @property(nonatomic, readonly) web::WebState* currentWebState;
 
-// Whether the safe area insets should be used to adjust the viewport.
-@property(nonatomic, readonly) BOOL usesSafeInsetsForViewportAdjustments;
-
 // Whether the keyboard observer helper is viewed
 @property(nonatomic, strong) KeyboardObserverHelper* observer;
 
@@ -1072,15 +1069,6 @@
              : nullptr;
 }
 
-- (BOOL)usesSafeInsetsForViewportAdjustments {
-  fullscreen::features::ViewportAdjustmentExperiment viewportExperiment =
-      fullscreen::features::GetActiveViewportExperiment();
-  return viewportExperiment ==
-             fullscreen::features::ViewportAdjustmentExperiment::SAFE_AREA ||
-         viewportExperiment ==
-             fullscreen::features::ViewportAdjustmentExperiment::HYBRID;
-}
-
 - (BubblePresenter*)bubblePresenter {
   if (!_bubblePresenter && self.browserState) {
     self.bubblePresenter =
@@ -1686,7 +1674,7 @@
   self.secondaryToolbarNoFullscreenHeightConstraint.constant =
       [self secondaryToolbarHeightWithInset];
   [self updateFootersForFullscreenProgress:self.footerFullscreenProgress];
-  if (!self.usesSafeInsetsForViewportAdjustments && self.currentWebState) {
+  if (self.currentWebState) {
     UIEdgeInsets contentPadding =
         self.currentWebState->GetWebViewProxy().contentInset;
     contentPadding.bottom = AlignValueToPixel(
@@ -3828,9 +3816,6 @@
 // Translates the footer view up and down according to |progress|, where a
 // progress of 1.0 fully shows the footer and a progress of 0.0 fully hides it.
 - (void)updateFootersForFullscreenProgress:(CGFloat)progress {
-  // If the bottom toolbar is locked into place, reset |progress| to 1.0.
-  if (base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar))
-    progress = 1.0;
 
   self.footerFullscreenProgress = progress;
 
@@ -3873,26 +3858,10 @@
   // safe area, so the unsafe top height must be added.
   CGFloat top = AlignValueToPixel(
       self.headerHeight + (progress - 1.0) * [self primaryToolbarHeightDelta]);
-  // If the bottom toolbar is locked into place, use 1.0 instead of |progress|.
-  CGFloat bottomProgress =
-      base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar)
-          ? 1.0
-          : progress;
-  CGFloat bottom = AlignValueToPixel(bottomProgress *
-                                     [self secondaryToolbarHeightWithInset]);
+  CGFloat bottom =
+      AlignValueToPixel(progress * [self secondaryToolbarHeightWithInset]);
 
-  if (self.usesSafeInsetsForViewportAdjustments) {
-    if (fullscreen::features::GetActiveViewportExperiment() ==
-        fullscreen::features::ViewportAdjustmentExperiment::HYBRID) {
-      [self updateWebViewFrameForBottomOffset:bottom];
-    }
-
-    [self updateBrowserSafeAreaForTopToolbarHeight:top
-                               bottomToolbarHeight:bottom];
-  } else {
-    [self updateContentPaddingForTopToolbarHeight:top
-                              bottomToolbarHeight:bottom];
-  }
+  [self updateContentPaddingForTopToolbarHeight:top bottomToolbarHeight:bottom];
 }
 
 // Updates the frame of the web view so that it's |offset| from the bottom of
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.h b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
index 916a651..3826990 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.h
@@ -11,35 +11,25 @@
 namespace fullscreen {
 namespace features {
 
-// The name of the command line switch used to control the method by which the
-// viewport of the content area is updated by scrolling events.
-extern const char kViewportAdjustmentExperimentCommandLineSwitch[];
-
-// The available viewport adjustment experiments.  The choices in this array
-// correspond with the ViewportAdjustmentExperiment values.
-extern const flags_ui::FeatureEntry::Choice
-    kViewportAdjustmentExperimentChoices[6];
+// Feature used by finch config to enable smooth scrolling when the default
+// viewport adjustment experiment is selected via command line switches.
+extern const base::Feature kSmoothScrollingDefault;
 
 // Enum type describing viewport adjustment experiments.
 enum class ViewportAdjustmentExperiment : short {
   FRAME = 0,      // Adjust the viewport by resizing the entire WKWebView.
-  CONTENT_INSET,  // Adjust the viewport by updating the WKWebView's scroll view
-                  // contentInset.
-  SAFE_AREA,  // Adjust the viewport by updating the safe area of the browser
-              // container view.
-  HYBRID,  // Translates the web view up and down and updates the viewport using
-           // safe area insets.
   SMOOTH_SCROLLING,  // Adjusts the viewport using the smooth scrolling
                      // workaround.
 };
 
 // Convenience method for retrieving the active viewport adjustment experiment
-// from the command line.
+// from the command line. TODO(crbug.com/914042): Remove once the internal
+// references are moved to ShouldUseSmoothScrolling().
 ViewportAdjustmentExperiment GetActiveViewportExperiment();
 
-// Used to control whether the bottom toolbar should be locked into the extended
-// position (i.e. fullscreen progress == 1.0).
-extern const base::Feature kLockBottomToolbar;
+// Convenience method for determining when to adjust the viewport by resizing
+// WKWebView or using smooth scrolling.
+bool ShouldUseSmoothScrolling();
 
 }  // namespace features
 }  // namespace fullscreen
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
index 0d4f0b9d..af1a6d51 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_features.mm
@@ -11,63 +11,21 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// The command line values for the content inset and safe area experiment
-// choices.
-const char kFrameChoiceValue[] = "frame";
-const char kContentInsetChoiceValue[] = "content-inset";
-const char kSafeAreaChoiceValue[] = "safe-area";
-const char kHybridChoiceValue[] = "hybrid";
-const char kSmoothScrollingChoiceValue[] = "smooth";
-
-// Feature used by finch config to enable smooth scrolling when the default
-// viewport adjustment experiment is selected via command line switches.
-const base::Feature kSmoothScrollingDefault{"FullscreenSmoothScrollingDefault",
-                                            base::FEATURE_ENABLED_BY_DEFAULT};
-}
-
 namespace fullscreen {
 namespace features {
 
-const char kViewportAdjustmentExperimentCommandLineSwitch[] =
-    "fullscreen-viewport-adjustment-experiment";
-
-const flags_ui::FeatureEntry::Choice kViewportAdjustmentExperimentChoices[] = {
-    {flags_ui::kGenericExperimentChoiceDefault, "", ""},
-    {"Update Content Inset", kViewportAdjustmentExperimentCommandLineSwitch,
-     "content-inset"},
-    {"Update Safe Area", kViewportAdjustmentExperimentCommandLineSwitch,
-     "safe-area"},
-    {"Use Hybrid Implementation",
-     kViewportAdjustmentExperimentCommandLineSwitch, "hybrid"},
-    {"Use Smooth Scrolling", kViewportAdjustmentExperimentCommandLineSwitch,
-     "smooth"},
-    {"Update Frame", kViewportAdjustmentExperimentCommandLineSwitch, "frame"}};
+const base::Feature kSmoothScrollingDefault{"FullscreenSmoothScrollingDefault",
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 ViewportAdjustmentExperiment GetActiveViewportExperiment() {
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(kViewportAdjustmentExperimentCommandLineSwitch)) {
-    std::string viewport_experiment = command_line->GetSwitchValueASCII(
-        kViewportAdjustmentExperimentCommandLineSwitch);
-    if (viewport_experiment == std::string(kContentInsetChoiceValue))
-      return ViewportAdjustmentExperiment::CONTENT_INSET;
-    if (viewport_experiment == std::string(kSafeAreaChoiceValue))
-      return ViewportAdjustmentExperiment::SAFE_AREA;
-    if (viewport_experiment == std::string(kHybridChoiceValue))
-      return ViewportAdjustmentExperiment::HYBRID;
-    if (viewport_experiment == std::string(kSmoothScrollingChoiceValue))
-      return ViewportAdjustmentExperiment::SMOOTH_SCROLLING;
-    if (viewport_experiment == std::string(kFrameChoiceValue))
-      return ViewportAdjustmentExperiment::FRAME;
-  }
-  return base::FeatureList::IsEnabled(kSmoothScrollingDefault)
+  return ShouldUseSmoothScrolling()
              ? ViewportAdjustmentExperiment::SMOOTH_SCROLLING
              : ViewportAdjustmentExperiment::FRAME;
 }
 
-const base::Feature kLockBottomToolbar{"LockBottomToolbar",
-                                       base::FEATURE_DISABLED_BY_DEFAULT};
+bool ShouldUseSmoothScrolling() {
+  return base::FeatureList::IsEnabled(kSmoothScrollingDefault);
+}
 
 }  // namespace features
 }  // namespace fullscreen
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
index f750501..8d6306e2 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_model.h
@@ -73,14 +73,10 @@
 
   // Returns the toolbar insets at |progress|.
   UIEdgeInsets GetToolbarInsetsAtProgress(CGFloat progress) const {
-    const CGFloat kBottomToolbarProgress =
-        base::FeatureList::IsEnabled(fullscreen::features::kLockBottomToolbar)
-            ? 1.0
-            : progress;
     return UIEdgeInsetsMake(
         collapsed_toolbar_height_ +
             progress * (expanded_toolbar_height_ - collapsed_toolbar_height_),
-        0, kBottomToolbarProgress * bottom_toolbar_height_, 0);
+        0, progress * bottom_toolbar_height_, 0);
   }
 
   // Increments and decrements |disabled_counter_| for features that require the
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
index 80cb935..81f5e6f 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
@@ -28,8 +28,6 @@
 #error "This file requires ARC support."
 #endif
 
-using fullscreen::features::ViewportAdjustmentExperiment;
-
 FullscreenWebStateObserver::FullscreenWebStateObserver(
     FullscreenController* controller,
     FullscreenModel* model,
@@ -83,18 +81,13 @@
   // - For normal pages, using |contentInset| breaks the layout of fixed-
   //   position DOM elements, so top padding must be accomplished by updating
   //   the WKWebView's frame.
-  bool force_content_inset =
-      fullscreen::features::GetActiveViewportExperiment() ==
-      ViewportAdjustmentExperiment::CONTENT_INSET;
   bool is_pdf = web_state->GetContentsMimeType() == "application/pdf";
-  bool use_content_inset = force_content_inset || is_pdf;
   id<CRWWebViewProxy> web_view_proxy = web_state->GetWebViewProxy();
-  web_view_proxy.shouldUseViewContentInset = use_content_inset;
+  web_view_proxy.shouldUseViewContentInset = is_pdf;
 
-  model_->SetResizesScrollView(!use_content_inset &&
-                               !ios::GetChromeBrowserProvider()
-                                    ->GetFullscreenProvider()
-                                    ->IsInitialized());
+  model_->SetResizesScrollView(!is_pdf && !ios::GetChromeBrowserProvider()
+                                               ->GetFullscreenProvider()
+                                               ->IsInitialized());
 
   // Only reset the model for document-changing navigations or same-document
   // navigations that update the visible URL.
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
index 5829e04..0ea5d9d8 100644
--- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
+++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -32,8 +32,6 @@
 #error "This file requires ARC support."
 #endif
 
-using fullscreen::features::ViewportAdjustmentExperiment;
-
 namespace {
 // This enum is used to record the overscroll actions performed by the user on
 // the histogram named |OverscrollActions|.
@@ -571,12 +569,9 @@
 - (BOOL)viewportAdjustsContentInset {
   if (_webViewProxy.shouldUseViewContentInset)
     return YES;
-  ViewportAdjustmentExperiment experiment =
-      fullscreen::features::GetActiveViewportExperiment();
-  return experiment == ViewportAdjustmentExperiment::SMOOTH_SCROLLING &&
-         ios::GetChromeBrowserProvider()
-             ->GetFullscreenProvider()
-             ->IsInitialized();
+  return ios::GetChromeBrowserProvider()
+      ->GetFullscreenProvider()
+      ->IsInitialized();
 }
 
 - (void)recordMetricForTriggeredAction:(OverscrollAction)action {
diff --git a/ios/web/net/cookie_notification_bridge.h b/ios/web/net/cookie_notification_bridge.h
index 3f7be7a..72216420 100644
--- a/ios/web/net/cookie_notification_bridge.h
+++ b/ios/web/net/cookie_notification_bridge.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 
+@protocol NSObject;
 @class NSNotification;
 
 namespace web {
@@ -21,7 +22,10 @@
 
  private:
   static void OnNotificationReceived(NSNotification* notification);
-  id observer_;
+
+  // Token returned by NSNotificationCenter upon registration. Owned by the
+  // bridge and used to unregister from NSNotificationCenter in destructor.
+  __strong id<NSObject> registration_;
 
   DISALLOW_COPY_AND_ASSIGN(CookieNotificationBridge);
 };
diff --git a/ios/web/net/cookie_notification_bridge.mm b/ios/web/net/cookie_notification_bridge.mm
index 1004380f..79b85a11 100644
--- a/ios/web/net/cookie_notification_bridge.mm
+++ b/ios/web/net/cookie_notification_bridge.mm
@@ -20,18 +20,18 @@
 namespace web {
 
 CookieNotificationBridge::CookieNotificationBridge() {
-  id<NSObject> observer = [[NSNotificationCenter defaultCenter]
+  id<NSObject> registration = [[NSNotificationCenter defaultCenter]
       addObserverForName:NSHTTPCookieManagerCookiesChangedNotification
                   object:[NSHTTPCookieStorage sharedHTTPCookieStorage]
                    queue:nil
               usingBlock:^(NSNotification* notification) {
                 OnNotificationReceived(notification);
               }];
-  observer_ = observer;
+  registration_ = registration;
 }
 
 CookieNotificationBridge::~CookieNotificationBridge() {
-  [[NSNotificationCenter defaultCenter] removeObserver:observer_];
+  [[NSNotificationCenter defaultCenter] removeObserver:registration_];
 }
 
 void CookieNotificationBridge::OnNotificationReceived(
diff --git a/media/base/android/test_destruction_observable.h b/media/base/android/test_destruction_observable.h
index c2c0e3f..90dddfe 100644
--- a/media/base/android/test_destruction_observable.h
+++ b/media/base/android/test_destruction_observable.h
@@ -44,6 +44,9 @@
   // expectation.
   void DoNotAllowDestruction();
 
+  // Return if the object has been destroyed.
+  bool destructed() const { return destructed_; }
+
  private:
   void VerifyExpectations();
   void OnObservableDestructed();
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc
index e5be008..819a00b 100644
--- a/media/filters/fuchsia/fuchsia_video_decoder.cc
+++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -276,9 +276,6 @@
   int num_used_output_buffers_ = 0;
   int max_used_output_buffers_ = 0;
 
-  // Non-null when flush is pending.
-  VideoDecoder::DecodeCB pending_flush_cb_;
-
   base::WeakPtr<FuchsiaVideoDecoder> weak_this_;
   base::WeakPtrFactory<FuchsiaVideoDecoder> weak_factory_;
 
@@ -591,13 +588,6 @@
   active_stream_ = true;
   codec_->QueueInputEndOfStream(stream_lifetime_ordinal_);
   codec_->FlushEndOfStreamAndCloseStream(stream_lifetime_ordinal_);
-
-  DCHECK(!decode_callbacks_.empty());
-  pending_flush_cb_ = std::move(decode_callbacks_.front());
-  decode_callbacks_.pop_front();
-
-  // Decode() is not supposed to be called after EOF.
-  DCHECK(decode_callbacks_.empty());
 }
 
 void FuchsiaVideoDecoder::OnFreeInputPacket(
@@ -865,7 +855,12 @@
   stream_lifetime_ordinal_ += 2;
   active_stream_ = false;
 
-  std::move(pending_flush_cb_).Run(DecodeStatus::OK);
+  // Decode() is not supposed to be called after EOF.
+  DCHECK_EQ(decode_callbacks_.size(), 1U);
+  auto flush_cb = std::move(decode_callbacks_.front());
+  decode_callbacks_.pop_front();
+
+  std::move(flush_cb).Run(DecodeStatus::OK);
 }
 
 void FuchsiaVideoDecoder::OnError() {
diff --git a/media/filters/fuchsia/fuchsia_video_decoder_unittest.cc b/media/filters/fuchsia/fuchsia_video_decoder_unittest.cc
index 8219207e..22d6640 100644
--- a/media/filters/fuchsia/fuchsia_video_decoder_unittest.cc
+++ b/media/filters/fuchsia/fuchsia_video_decoder_unittest.cc
@@ -215,29 +215,39 @@
     while (output_frames_.size() > frames_to_keep_) {
       output_frames_.pop_front();
     }
-    if (on_frame_)
-      on_frame_.Run();
+    if (run_loop_)
+      run_loop_->Quit();
   }
 
-  DecodeStatus DecodeBuffer(scoped_refptr<DecoderBuffer> buffer) {
-    base::RunLoop run_loop;
-    DecodeStatus status;
-    decoder_->Decode(buffer,
-                     base::BindRepeating(
-                         [](DecodeStatus* status, base::RunLoop* run_loop,
-                            DecodeStatus result) {
-                           *status = result;
-                           run_loop->Quit();
-                         },
-                         &status, &run_loop));
-
-    run_loop.Run();
-
-    return status;
+  void DecodeBuffer(scoped_refptr<DecoderBuffer> buffer) {
+    decoder_->Decode(buffer, base::BindRepeating(
+                                 &FuchsiaVideoDecoderTest::OnFrameDecoded,
+                                 base::Unretained(this), num_input_buffers_));
+    num_input_buffers_ += 1;
   }
 
-  DecodeStatus ReadAndDecodeFrame(const std::string& name) {
-    return DecodeBuffer(ReadTestDataFile(name));
+  void ReadAndDecodeFrame(const std::string& name) {
+    DecodeBuffer(ReadTestDataFile(name));
+  }
+
+  void OnFrameDecoded(size_t frame_pos, DecodeStatus status) {
+    EXPECT_EQ(frame_pos, num_decoded_buffers_);
+    num_decoded_buffers_ += 1;
+    last_decode_status_ = status;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  // Waits until all pending decode requests are finished.
+  void WaitDecodeDone() {
+    size_t target_pos = num_input_buffers_;
+    while (num_decoded_buffers_ < target_pos) {
+      base::RunLoop run_loop;
+      run_loop_ = &run_loop;
+      run_loop.Run();
+      run_loop_ = nullptr;
+      ASSERT_EQ(last_decode_status_, DecodeStatus::OK);
+    }
   }
 
  protected:
@@ -249,13 +259,20 @@
 
   std::unique_ptr<VideoDecoder> decoder_;
 
+  size_t num_input_buffers_ = 0;
+
+  // Number of frames for which DecodeCB has been called. That doesn't mean
+  // we've received corresponding output frames.
+  size_t num_decoded_buffers_ = 0;
+
   std::list<scoped_refptr<VideoFrame>> output_frames_;
-  int num_output_frames_ = 0;
+  size_t num_output_frames_ = 0;
+
+  DecodeStatus last_decode_status_ = DecodeStatus::OK;
+  base::RunLoop* run_loop_ = nullptr;
 
   // Number of frames that OnVideoFrame() should keep in |output_frames_|.
   size_t frames_to_keep_ = 2;
-
-  base::RepeatingClosure on_frame_;
 };
 
 TEST_F(FuchsiaVideoDecoderTest, CreateAndDestroy) {}
@@ -267,24 +284,26 @@
 TEST_F(FuchsiaVideoDecoderTest, DISABLED_VP9) {
   ASSERT_TRUE(Initialize(TestVideoConfig::Normal(kCodecVP9)));
 
-  ASSERT_TRUE(ReadAndDecodeFrame("vp9-I-frame-320x240") == DecodeStatus::OK);
-  ASSERT_TRUE(DecodeBuffer(DecoderBuffer::CreateEOSBuffer()) ==
-              DecodeStatus::OK);
+  ReadAndDecodeFrame("vp9-I-frame-320x240");
+  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
+  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());
 
-  EXPECT_EQ(num_output_frames_, 1);
+  EXPECT_EQ(num_output_frames_, 1U);
 }
 
 TEST_F(FuchsiaVideoDecoderTest, H264) {
   ASSERT_TRUE(Initialize(TestVideoConfig::NormalH264()));
 
-  ASSERT_TRUE(ReadAndDecodeFrame("h264-320x180-frame-0") == DecodeStatus::OK);
-  ASSERT_TRUE(ReadAndDecodeFrame("h264-320x180-frame-1") == DecodeStatus::OK);
-  ASSERT_TRUE(ReadAndDecodeFrame("h264-320x180-frame-2") == DecodeStatus::OK);
-  ASSERT_TRUE(ReadAndDecodeFrame("h264-320x180-frame-3") == DecodeStatus::OK);
-  ASSERT_TRUE(DecodeBuffer(DecoderBuffer::CreateEOSBuffer()) ==
-              DecodeStatus::OK);
+  ReadAndDecodeFrame("h264-320x180-frame-0");
+  ReadAndDecodeFrame("h264-320x180-frame-1");
+  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());
 
-  EXPECT_EQ(num_output_frames_, 4);
+  ReadAndDecodeFrame("h264-320x180-frame-2");
+  ReadAndDecodeFrame("h264-320x180-frame-3");
+  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
+  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());
+
+  EXPECT_EQ(num_output_frames_, 4U);
 }
 
 }  // namespace media
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index da2e0b11..1c0e1659 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -133,6 +133,8 @@
       "android/video_frame_factory.h",
       "android/video_frame_factory_impl.cc",
       "android/video_frame_factory_impl.h",
+      "android/ycbcr_helper.cc",
+      "android/ycbcr_helper.h",
     ]
     libs += [ "android" ]
     deps += [
diff --git a/media/gpu/android/direct_shared_image_video_provider.cc b/media/gpu/android/direct_shared_image_video_provider.cc
index 5620d53..9ef9242f 100644
--- a/media/gpu/android/direct_shared_image_video_provider.cc
+++ b/media/gpu/android/direct_shared_image_video_provider.cc
@@ -122,6 +122,8 @@
     return;
   }
 
+  is_vulkan_ = shared_context->GrContextIsVulkan();
+
   // Make the shared context current.
   auto scoped_current = std::make_unique<ui::ScopedMakeCurrent>(
       shared_context->context(), shared_context->surface());
@@ -172,7 +174,8 @@
   SharedImageVideoProvider::ImageRecord record;
   record.mailbox = mailbox;
   record.release_cb = std::move(release_cb);
-  record.ycbcr_info = ycbcr_info_;
+  record.is_vulkan = is_vulkan_;
+
   // Since |codec_image|'s ref holders can be destroyed by stub destruction, we
   // create a ref to it for the MaybeRenderEarlyManager.  This is a hack; we
   // should not be sending the CodecImage at all.  The MaybeRenderEarlyManager
@@ -243,9 +246,6 @@
       std::move(texture), std::move(shared_context),
       false /* is_thread_safe */);
 
-  if (!ycbcr_info_)
-    ycbcr_info_ = shared_image->GetYcbcrInfo();
-
   // Register it with shared image mailbox as well as legacy mailbox. This
   // keeps |shared_image| around until its destruction cb is called.
   // NOTE: Currently none of the video mailbox consumer uses shared image
diff --git a/media/gpu/android/direct_shared_image_video_provider.h b/media/gpu/android/direct_shared_image_video_provider.h
index b860ad1..e140b6cad 100644
--- a/media/gpu/android/direct_shared_image_video_provider.h
+++ b/media/gpu/android/direct_shared_image_video_provider.h
@@ -96,9 +96,7 @@
   // A helper for creating textures. Only valid while |stub_| is valid.
   std::unique_ptr<GLES2DecoderHelper> decoder_helper_;
 
-  // Sampler conversion information which is used in vulkan context. This is
-  // constant for all the frames in a video and hence we cache it.
-  base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info_;
+  bool is_vulkan_ = false;
 
   THREAD_CHECKER(thread_checker_);
 
diff --git a/media/gpu/android/shared_image_video_provider.h b/media/gpu/android/shared_image_video_provider.h
index 269fe0d..4e1ea50db 100644
--- a/media/gpu/android/shared_image_video_provider.h
+++ b/media/gpu/android/shared_image_video_provider.h
@@ -53,9 +53,6 @@
     // Mailbox to which this shared image is bound.
     gpu::Mailbox mailbox;
 
-    // Sampler conversion information which is used in vulkan context.
-    base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;
-
     // Release callback.  When this is called (or dropped), the image will be
     // considered to be unused.
     ReleaseCB release_cb;
@@ -63,6 +60,10 @@
     // CodecImage that one can use for MaybeRenderEarly.
     scoped_refptr<CodecImageHolder> codec_image_holder;
 
+    // Is the underlying context Vulkan?  If so, then one must provide YCbCrInfo
+    // with the VideoFrame.
+    bool is_vulkan = false;
+
    private:
     DISALLOW_COPY_AND_ASSIGN(ImageRecord);
   };
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index 6571f2c..cced87f 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -81,12 +81,14 @@
     scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
     const gpu::GpuPreferences& gpu_preferences,
     std::unique_ptr<SharedImageVideoProvider> image_provider,
-    std::unique_ptr<MaybeRenderEarlyManager> mre_manager)
+    std::unique_ptr<MaybeRenderEarlyManager> mre_manager,
+    base::SequenceBound<YCbCrHelper> ycbcr_helper)
     : image_provider_(std::move(image_provider)),
       gpu_task_runner_(std::move(gpu_task_runner)),
       enable_threaded_texture_mailboxes_(
           gpu_preferences.enable_threaded_texture_mailboxes),
-      mre_manager_(std::move(mre_manager)) {}
+      mre_manager_(std::move(mre_manager)),
+      ycbcr_helper_(std::move(ycbcr_helper)) {}
 
 VideoFrameFactoryImpl::~VideoFrameFactoryImpl() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -155,9 +157,9 @@
   SharedImageVideoProvider::ImageSpec spec(coded_size);
 
   auto image_ready_cb = base::BindOnce(
-      &VideoFrameFactoryImpl::OnImageReady, weak_factory_.GetWeakPtr(),
-      std::move(output_cb), timestamp, coded_size, natural_size,
-      std::move(output_buffer), codec_buffer_wait_coordinator_,
+      &VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady,
+      weak_factory_.GetWeakPtr(), std::move(output_cb), timestamp, coded_size,
+      natural_size, std::move(output_buffer), codec_buffer_wait_coordinator_,
       std::move(promotion_hint_cb), pixel_format, overlay_mode_,
       enable_threaded_texture_mailboxes_, gpu_task_runner_);
 
@@ -169,7 +171,7 @@
 }
 
 // static
-void VideoFrameFactoryImpl::OnImageReady(
+void VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady(
     base::WeakPtr<VideoFrameFactoryImpl> thiz,
     OnceOutputCb output_cb,
     base::TimeDelta timestamp,
@@ -198,8 +200,63 @@
 
   // Send the CodecImage (via holder, since we can't touch the refcount here) to
   // the MaybeRenderEarlyManager.
-  thiz->mre_manager()->AddCodecImage(std::move(record.codec_image_holder));
+  thiz->mre_manager()->AddCodecImage(record.codec_image_holder);
 
+  // In case we need to get the YCbCr info, take the image holder out of the
+  // record before we move it into |completion_cb|.
+  auto codec_image_holder = std::move(record.codec_image_holder);
+
+  // Doesn't need to be weak-ptr'd, since we're either calling it inline, or
+  // calling it from the YCbCr callback which is, itself weak-ptr'd.
+  auto completion_cb = base::BindOnce(
+      &VideoFrameFactoryImpl::CreateVideoFrame_Finish, thiz,
+      std::move(output_cb), timestamp, coded_size, natural_size,
+      std::move(codec_buffer_wait_coordinator), pixel_format, overlay_mode,
+      enable_threaded_texture_mailboxes, std::move(record));
+
+  // TODO(liberato): Use |ycbcr_helper_| as a signal about whether we're
+  // supposed to get YCbCr info or not, rather than requiring the provider to
+  // tell us.  Note that right now, we do have the helper even if we don't
+  // need it.  See GpuMojoMediaClient.
+  if (!thiz->ycbcr_info_ && record.is_vulkan) {
+    // We need YCbCr info to create the frame.  Post back to the gpu thread to
+    // do it.  Note that we might post multiple times before succeeding once,
+    // both because of failures and because we might get multiple requests to
+    // create frames on the mcvd thread, before the gpu thread returns one ycbcr
+    // info to us.  Either way, it's fine, since the helper also caches the
+    // info locally.  It won't render more frames than needed.
+    auto ycbcr_cb = BindToCurrentLoop(base::BindOnce(
+        &VideoFrameFactoryImpl::CreateVideoFrame_OnYCbCrInfo,
+        thiz->weak_factory_.GetWeakPtr(), std::move(completion_cb)));
+    thiz->ycbcr_helper_.Post(FROM_HERE, &YCbCrHelper::GetYCbCrInfo,
+                             std::move(codec_image_holder),
+                             std::move(ycbcr_cb));
+    return;
+  }
+
+  std::move(completion_cb).Run();
+}
+
+void VideoFrameFactoryImpl::CreateVideoFrame_OnYCbCrInfo(
+    base::OnceClosure completion_cb,
+    YCbCrHelper::OptionalInfo ycbcr_info) {
+  ycbcr_info_ = std::move(ycbcr_info);
+  // Clear the helper just to free it up, though we might continue to get
+  // callbacks from it if we've posted multiple requests.
+  ycbcr_helper_.Reset();
+  std::move(completion_cb).Run();
+}
+
+void VideoFrameFactoryImpl::CreateVideoFrame_Finish(
+    OnceOutputCb output_cb,
+    base::TimeDelta timestamp,
+    gfx::Size coded_size,
+    gfx::Size natural_size,
+    scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+    VideoPixelFormat pixel_format,
+    OverlayMode overlay_mode,
+    bool enable_threaded_texture_mailboxes,
+    SharedImageVideoProvider::ImageRecord record) {
   gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
   mailbox_holders[0] = gpu::MailboxHolder(record.mailbox, gpu::SyncToken(),
                                           GL_TEXTURE_EXTERNAL_OES);
@@ -222,7 +279,9 @@
       pixel_format, mailbox_holders, VideoFrame::ReleaseMailboxCB(), coded_size,
       visible_rect, natural_size, timestamp);
 
-  frame->set_ycbcr_info(record.ycbcr_info);
+  // For Vulkan.
+  frame->set_ycbcr_info(ycbcr_info_);
+
   // If, for some reason, we failed to create a frame, then fail.  Note that we
   // don't need to call |release_cb|; dropping it is okay since the api says so.
   if (!frame) {
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index bef5d83..8352166 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
+#include "base/threading/sequence_bound.h"
 #include "gpu/config/gpu_preferences.h"
 #include "media/base/video_frame.h"
 #include "media/gpu/android/codec_buffer_wait_coordinator.h"
@@ -18,6 +19,7 @@
 #include "media/gpu/android/maybe_render_early_manager.h"
 #include "media/gpu/android/shared_image_video_provider.h"
 #include "media/gpu/android/video_frame_factory.h"
+#include "media/gpu/android/ycbcr_helper.h"
 #include "media/gpu/media_gpu_export.h"
 #include "ui/gl/gl_bindings.h"
 
@@ -44,7 +46,8 @@
       scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
       const gpu::GpuPreferences& gpu_preferences,
       std::unique_ptr<SharedImageVideoProvider> image_provider,
-      std::unique_ptr<MaybeRenderEarlyManager> mre_manager);
+      std::unique_ptr<MaybeRenderEarlyManager> mre_manager,
+      base::SequenceBound<YCbCrHelper> ycbcr_helper);
   ~VideoFrameFactoryImpl() override;
 
   void Initialize(OverlayMode overlay_mode, InitCb init_cb) override;
@@ -76,7 +79,7 @@
   //
   // Second, this way we don't care about the lifetime of |this|; |output_cb|
   // can worry about it.
-  static void OnImageReady(
+  static void CreateVideoFrame_OnImageReady(
       base::WeakPtr<VideoFrameFactoryImpl> thiz,
       OnceOutputCb output_cb,
       base::TimeDelta timestamp,
@@ -91,6 +94,23 @@
       scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
       SharedImageVideoProvider::ImageRecord record);
 
+  // Callback to receive YCbCrInfo from |provider_| while creating a VideoFrame.
+  void CreateVideoFrame_OnYCbCrInfo(base::OnceClosure completion_cb,
+                                    YCbCrHelper::OptionalInfo ycbcr_info);
+
+  // Really create the VideoFrame, once we've tried to get the YCbCrInfo if it's
+  // needed for it.
+  void CreateVideoFrame_Finish(
+      OnceOutputCb output_cb,
+      base::TimeDelta timestamp,
+      gfx::Size coded_size,
+      gfx::Size natural_size,
+      scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+      VideoPixelFormat pixel_format,
+      OverlayMode overlay_mode,
+      bool enable_threaded_texture_mailboxes,
+      SharedImageVideoProvider::ImageRecord record);
+
   MaybeRenderEarlyManager* mre_manager() const { return mre_manager_.get(); }
 
   std::unique_ptr<SharedImageVideoProvider> image_provider_;
@@ -111,6 +131,12 @@
 
   std::unique_ptr<MaybeRenderEarlyManager> mre_manager_;
 
+  // Sampler conversion information which is used in vulkan context.
+  YCbCrHelper::OptionalInfo ycbcr_info_;
+
+  // Optional helper to get the Vulkan YCbCrInfo.
+  base::SequenceBound<YCbCrHelper> ycbcr_helper_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<VideoFrameFactoryImpl> weak_factory_{this};
diff --git a/media/gpu/android/video_frame_factory_impl_unittest.cc b/media/gpu/android/video_frame_factory_impl_unittest.cc
index a4129ae..f33c6ab 100644
--- a/media/gpu/android/video_frame_factory_impl_unittest.cc
+++ b/media/gpu/android/video_frame_factory_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "gpu/command_buffer/service/mock_texture_owner.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/config/gpu_preferences.h"
+#include "media/base/android/test_destruction_observable.h"
 #include "media/base/limits.h"
 #include "media/gpu/android/codec_buffer_wait_coordinator.h"
 #include "media/gpu/android/maybe_render_early_manager.h"
@@ -64,22 +65,42 @@
   scoped_refptr<gpu::TextureOwner> texture_owner_;
 };
 
+class MockYCbCrHelper : public YCbCrHelper, public DestructionObservable {
+ public:
+  MockYCbCrHelper(MockYCbCrHelper** thiz) { *thiz = this; }
+
+  void GetYCbCrInfo(
+      scoped_refptr<CodecImageHolder> codec_image_holder,
+      base::OnceCallback<void(OptionalInfo ycbcr_info)> cb) override {
+    MockGetYCbCrInfo(codec_image_holder);
+    cb_ = std::move(cb);
+  }
+
+  MOCK_METHOD1(MockGetYCbCrInfo,
+               void(scoped_refptr<CodecImageHolder> codec_image_holder));
+
+  base::OnceCallback<void(OptionalInfo ycbcr_info)> cb_;
+};
+
 class VideoFrameFactoryImplTest : public testing::Test {
  public:
   VideoFrameFactoryImplTest()
       : task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-    auto get_stub_cb = base::BindRepeating(
-        []() -> gpu::CommandBufferStub* { return nullptr; });
-
     auto image_provider = std::make_unique<MockSharedImageVideoProvider>();
     image_provider_raw_ = image_provider.get();
 
     auto mre_manager = std::make_unique<MockMaybeRenderEarlyManager>();
     mre_manager_raw_ = mre_manager.get();
 
+    auto ycbcr_helper =
+        base::SequenceBound<MockYCbCrHelper>(task_runner_, &ycbcr_helper_raw_);
+    base::RunLoop().RunUntilIdle();  // Init |ycbcr_helper_raw_|.
+    ycbcr_destruction_observer_ =
+        ycbcr_helper_raw_->CreateDestructionObserver();
+
     impl_ = std::make_unique<VideoFrameFactoryImpl>(
         task_runner_, gpu_preferences_, std::move(image_provider),
-        std::move(mre_manager));
+        std::move(mre_manager), std::move(ycbcr_helper));
     auto texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
         0, nullptr, nullptr, true);
     auto codec_buffer_wait_coordinator =
@@ -90,6 +111,7 @@
     impl_->SetCodecBufferWaitCorrdinatorForTesting(
         std::move(codec_buffer_wait_coordinator));
   }
+
   ~VideoFrameFactoryImplTest() override = default;
 
   void RequestVideoFrame() {
@@ -114,6 +136,25 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  // |release_cb_called_flag| will be set when the record's |release_cb| runs.
+  SharedImageVideoProvider::ImageRecord MakeImageRecord(
+      bool* release_cb_called_flag = nullptr) {
+    SharedImageVideoProvider::ImageRecord record;
+    record.mailbox = gpu::Mailbox::Generate();
+    if (release_cb_called_flag)
+      *release_cb_called_flag = false;
+    record.release_cb = base::BindOnce(
+        [](bool* flag, const gpu::SyncToken&) {
+          if (flag)
+            *flag = true;
+        },
+        base::Unretained(release_cb_called_flag));
+    auto codec_image = base::MakeRefCounted<MockCodecImage>();
+    record.codec_image_holder =
+        base::MakeRefCounted<CodecImageHolder>(task_runner_, codec_image);
+    return record;
+  }
+
   base::test::TaskEnvironment task_environment_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
@@ -128,6 +169,9 @@
   // Sent to |impl_| by RequestVideoFrame..
   base::MockCallback<VideoFrameFactory::OnceOutputCb> output_cb_;
 
+  MockYCbCrHelper* ycbcr_helper_raw_ = nullptr;
+  std::unique_ptr<DestructionObserver> ycbcr_destruction_observer_;
+
   gpu::GpuPreferences gpu_preferences_;
 };
 
@@ -193,15 +237,10 @@
   // Call the ImageReadyCB.
   scoped_refptr<VideoFrame> frame;
   EXPECT_CALL(output_cb_, Run(_)).WillOnce(SaveArg<0>(&frame));
-  SharedImageVideoProvider::ImageRecord record;
-  record.mailbox = gpu::Mailbox::Generate();
   bool release_cb_called_flag = false;
-  record.release_cb =
-      base::BindOnce([](bool* flag, const gpu::SyncToken&) { *flag = true; },
-                     base::Unretained(&release_cb_called_flag));
-  auto codec_image = base::MakeRefCounted<MockCodecImage>();
-  record.codec_image_holder =
-      base::MakeRefCounted<CodecImageHolder>(task_runner_, codec_image);
+  auto record = MakeImageRecord(&release_cb_called_flag);
+  scoped_refptr<CodecImage> codec_image(
+      record.codec_image_holder->codec_image_raw());
   std::move(image_provider_raw_->cb_).Run(std::move(record));
   base::RunLoop().RunUntilIdle();
   EXPECT_NE(frame, nullptr);
@@ -227,4 +266,49 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(VideoFrameFactoryImplTest, DoesNotCallYCbCrHelperIfNotVulkan) {
+  EXPECT_CALL(*ycbcr_helper_raw_, MockGetYCbCrInfo(_)).Times(0);
+  RequestVideoFrame();
+  auto image_record = MakeImageRecord();
+  image_record.is_vulkan = false;
+  std::move(image_provider_raw_->cb_).Run(std::move(image_record));
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(VideoFrameFactoryImplTest, DoesCallYCbCrHelperIfVulkan) {
+  RequestVideoFrame();
+  auto image_record = MakeImageRecord();
+  base::OnceCallback<void(YCbCrHelper::OptionalInfo)> cb;
+  EXPECT_CALL(*ycbcr_helper_raw_,
+              MockGetYCbCrInfo(image_record.codec_image_holder))
+      .Times(1);
+  image_record.is_vulkan = true;
+  std::move(image_provider_raw_->cb_).Run(std::move(image_record));
+  base::RunLoop().RunUntilIdle();
+
+  // Provide YCbCrInfo.  It should provide the VideoFrame too.
+  EXPECT_CALL(output_cb_, Run(_)).Times(1);
+  gpu::VulkanYCbCrInfo ycbcr;
+  std::move(ycbcr_helper_raw_->cb_).Run(ycbcr);
+  base::RunLoop().RunUntilIdle();
+  // It's okay if the ycbcr helper is destroyed.  If not, then verify
+  // expectations explicitly now.
+  if (ycbcr_destruction_observer_->destructed())
+    ycbcr_helper_raw_ = nullptr;
+  else
+    testing::Mock::VerifyAndClearExpectations(ycbcr_helper_raw_);
+
+  // Verify that no more calls happen, since we don't want thread hops on every
+  // frame.  Note that multiple could be dispatched before now.  It should still
+  // send along a VideoFrame, though.
+  RequestVideoFrame();
+  auto other_image_record = MakeImageRecord();
+  // If the helper hasn't been destroyed, then we don't expect it to be called.
+  if (ycbcr_helper_raw_)
+    EXPECT_CALL(*ycbcr_helper_raw_, MockGetYCbCrInfo(_)).Times(0);
+  EXPECT_CALL(output_cb_, Run(_)).Times(1);
+  std::move(image_provider_raw_->cb_).Run(std::move(other_image_record));
+  base::RunLoop().RunUntilIdle();
+}
+
 }  // namespace media
diff --git a/media/gpu/android/ycbcr_helper.cc b/media/gpu/android/ycbcr_helper.cc
new file mode 100644
index 0000000..bee89a68
--- /dev/null
+++ b/media/gpu/android/ycbcr_helper.cc
@@ -0,0 +1,82 @@
+// 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 "media/gpu/android/ycbcr_helper.h"
+
+#include "gpu/command_buffer/service/shared_image_video.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
+
+namespace media {
+
+// Concrete implementation of YCbCrHelper that renders output buffers and gets
+// the YCbCrInfo they need.
+class YCbCrHelperImpl : public YCbCrHelper,
+                        public gpu::CommandBufferStub::DestructionObserver {
+ public:
+  YCbCrHelperImpl(SharedImageVideoProvider::GetStubCB get_stub_cb) {
+    stub_ = get_stub_cb.Run();
+    if (stub_)
+      stub_->AddDestructionObserver(this);
+  }
+
+  ~YCbCrHelperImpl() override {
+    if (stub_)
+      stub_->RemoveDestructionObserver(this);
+  }
+
+  // YCbCrHelper
+  void GetYCbCrInfo(
+      scoped_refptr<CodecImageHolder> codec_image_holder,
+      base::OnceCallback<void(OptionalInfo ycbcr_info)> cb) override {
+    // If we don't have the info cached, then try to get it.  If we have gotten
+    // it, then don't try again.  Assume that our caller asked for it before it
+    // got the results back.  We don't want to render more frames to the front
+    // buffer if we don't need to.
+    if (!ycbcr_info_)
+      ycbcr_info_ = RenderImageAndGetYCbCrInfo(std::move(codec_image_holder));
+
+    // Whether we got it or not, send it along.
+    std::move(cb).Run(ycbcr_info_);
+  }
+
+  void OnWillDestroyStub(bool have_context) override {
+    DCHECK(stub_);
+    stub_ = nullptr;
+  }
+
+ private:
+  // Render the codec output buffer, and use it to get the YCbCrInfo.
+  OptionalInfo RenderImageAndGetYCbCrInfo(
+      scoped_refptr<CodecImageHolder> codec_image_holder) {
+    gpu::ContextResult result;
+    if (!stub_)
+      return base::nullopt;
+
+    auto shared_context =
+        stub_->channel()->gpu_channel_manager()->GetSharedContextState(&result);
+    auto context_provider =
+        (result == gpu::ContextResult::kSuccess) ? shared_context : nullptr;
+    if (!context_provider)
+      return base::nullopt;
+
+    return gpu::SharedImageVideo::GetYcbcrInfo(
+        codec_image_holder->codec_image_raw(), context_provider);
+  }
+
+  gpu::CommandBufferStub* stub_ = nullptr;
+
+  OptionalInfo ycbcr_info_;
+};
+
+// static
+base::SequenceBound<YCbCrHelper> YCbCrHelper::Create(
+    scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
+    SharedImageVideoProvider::GetStubCB get_stub_cb) {
+  return base::SequenceBound<YCbCrHelperImpl>(std::move(gpu_task_runner),
+                                              std::move(get_stub_cb));
+}
+
+}  // namespace media
diff --git a/media/gpu/android/ycbcr_helper.h b/media/gpu/android/ycbcr_helper.h
new file mode 100644
index 0000000..4576ece
--- /dev/null
+++ b/media/gpu/android/ycbcr_helper.h
@@ -0,0 +1,48 @@
+// 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 MEDIA_GPU_ANDROID_YCBCR_HELPER_H_
+#define MEDIA_GPU_ANDROID_YCBCR_HELPER_H_
+
+#include "base/optional.h"
+#include "base/threading/sequence_bound.h"
+#include "media/gpu/android/codec_image.h"
+#include "media/gpu/android/shared_image_video_provider.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace media {
+
+// Helper class to fetch YCbCrInfo for Vulkan from a CodecImage.
+class MEDIA_GPU_EXPORT YCbCrHelper {
+ public:
+  using OptionalInfo = base::Optional<gpu::VulkanYCbCrInfo>;
+
+  static base::SequenceBound<YCbCrHelper> Create(
+      scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
+      SharedImageVideoProvider::GetStubCB get_stub_cb);
+
+  virtual ~YCbCrHelper() = default;
+
+  // Call |cb| with the YCbCrInfo (or nullopt, if we can't get it).  Will render
+  // |codec_image_holder| to the front buffer if it hasn't successfully gotten
+  // the YCbCrInfo on a previous call.  Otherwise, will return the cached
+  // YCbCrInfo and leave |codec_image_holder| unmodified.  Once we call |cb|
+  // with a non-nullopt YCbCrInfo, we will always return that same value; there
+  // is no need to call us afterwards.
+  //
+  // While this API might seem to be out of its Vulkan mind, it's this
+  // complicated to (a) prevent rendering frames out of order to the front
+  // buffer, and (b) make it easy to handle the fact that sometimes, we just
+  // can't get a YCbCrInfo from a CodecImage due to timeouts.
+  virtual void GetYCbCrInfo(
+      scoped_refptr<CodecImageHolder> codec_image_holder,
+      base::OnceCallback<void(OptionalInfo ycbcr_info)> cb) = 0;
+
+ protected:
+  YCbCrHelper() = default;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_YCBCR_HELPER_H_
diff --git a/media/gpu/windows/dxva_picture_buffer_win.cc b/media/gpu/windows/dxva_picture_buffer_win.cc
index 5ffc851..1b78e84e 100644
--- a/media/gpu/windows/dxva_picture_buffer_win.cc
+++ b/media/gpu/windows/dxva_picture_buffer_win.cc
@@ -21,7 +21,7 @@
 namespace {
 
 void LogDXVAError(int line) {
-  LOG(ERROR) << "Error in dxva_picture_buffer_win.cc on line " << line;
+  PLOG(ERROR) << "Error in dxva_picture_buffer_win.cc on line " << line;
   base::UmaHistogramSparse("Media.DXVAVDA.PictureBufferErrorLine", line);
 }
 
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
index 7cd0cb19..a54e5d6 100644
--- a/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
@@ -12,8 +12,9 @@
 namespace learning {
 
 MojoLearningTaskController::MojoLearningTaskController(
+    const LearningTask& task,
     mojom::LearningTaskControllerPtr controller_ptr)
-    : controller_ptr_(std::move(controller_ptr)) {}
+    : task_(task), controller_ptr_(std::move(controller_ptr)) {}
 
 MojoLearningTaskController::~MojoLearningTaskController() = default;
 
@@ -36,7 +37,7 @@
 }
 
 const LearningTask& MojoLearningTaskController::GetLearningTask() {
-  return LearningTask::Empty();
+  return task_;
 }
 
 }  // namespace learning
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.h b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
index d6c9bed..d76ede6 100644
--- a/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
@@ -19,8 +19,10 @@
 class COMPONENT_EXPORT(MEDIA_LEARNING_MOJO) MojoLearningTaskController
     : public LearningTaskController {
  public:
-  explicit MojoLearningTaskController(
-      mojom::LearningTaskControllerPtr controller_ptr);
+  // |task| will be provided by GetLearningTask().  Hopefully, it matches
+  // whatever |controller_ptr| uses.
+  MojoLearningTaskController(const LearningTask& task,
+                             mojom::LearningTaskControllerPtr controller_ptr);
   ~MojoLearningTaskController() override;
 
   // LearningTaskController
@@ -32,6 +34,7 @@
   const LearningTask& GetLearningTask() override;
 
  private:
+  LearningTask task_;
   mojom::LearningTaskControllerPtr controller_ptr_;
 
   DISALLOW_COPY_AND_ASSIGN(MojoLearningTaskController);
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
index b7af774d..716e8261 100644
--- a/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
+++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
@@ -59,6 +59,9 @@
   ~MojoLearningTaskControllerTest() override = default;
 
   void SetUp() override {
+    // Create a LearningTask.
+    task_.name = "MyLearningTask";
+
     // Create a fake learner provider mojo impl.
     mojom::LearningTaskControllerPtr learning_controller_ptr;
     learning_controller_binding_.Bind(
@@ -66,12 +69,13 @@
 
     // Tell |learning_controller_| to forward to the fake learner impl.
     learning_controller_ = std::make_unique<MojoLearningTaskController>(
-        std::move(learning_controller_ptr));
+        task_, std::move(learning_controller_ptr));
   }
 
   // Mojo stuff.
   base::test::TaskEnvironment task_environment_;
 
+  LearningTask task_;
   FakeMojoLearningTaskController fake_learning_controller_;
   mojo::Binding<mojom::LearningTaskController> learning_controller_binding_;
 
@@ -79,6 +83,10 @@
   std::unique_ptr<MojoLearningTaskController> learning_controller_;
 };
 
+TEST_F(MojoLearningTaskControllerTest, GetLearningTask) {
+  EXPECT_EQ(learning_controller_->GetLearningTask().name, task_.name);
+}
+
 TEST_F(MojoLearningTaskControllerTest, Begin) {
   base::UnguessableToken id = base::UnguessableToken::Create();
   FeatureVector features = {FeatureValue(123), FeatureValue(456)};
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 1d61efd..53763bb 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -209,7 +209,13 @@
           &GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_,
           command_buffer_id->channel_token, command_buffer_id->route_id);
       auto image_provider = std::make_unique<DirectSharedImageVideoProvider>(
-          gpu_task_runner_, std::move(get_stub_cb));
+          gpu_task_runner_, get_stub_cb);
+      // TODO(liberato): Create this only if we're using Vulkan, else it's
+      // ignored.  If we can tell that here, then VideoFrameFactory can use it
+      // as a signal about whether it's supposed to get YCbCrInfo rather than
+      // requiring the provider to set |is_vulkan| in the ImageRecord.
+      auto ycbcr_helper =
+          YCbCrHelper::Create(gpu_task_runner_, std::move(get_stub_cb));
       video_decoder = std::make_unique<MediaCodecVideoDecoder>(
           gpu_preferences_, gpu_feature_info_, DeviceInfo::GetInstance(),
           CodecAllocator::GetInstance(gpu_task_runner_),
@@ -218,7 +224,8 @@
           android_overlay_factory_cb_, std::move(request_overlay_info_cb),
           std::make_unique<VideoFrameFactoryImpl>(
               gpu_task_runner_, gpu_preferences_, std::move(image_provider),
-              MaybeRenderEarlyManager::Create(gpu_task_runner_)));
+              MaybeRenderEarlyManager::Create(gpu_task_runner_),
+              std::move(ycbcr_helper)));
 
 #elif defined(OS_CHROMEOS)
       if (base::FeatureList::IsEnabled(kChromeosVideoDecoder)) {
diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc
index 94ae386..ae2ad5a 100644
--- a/net/proxy_resolution/proxy_config.cc
+++ b/net/proxy_resolution/proxy_config.cc
@@ -234,7 +234,7 @@
         AddProxyListToValue("https", proxy_rules_.proxies_for_https, &dict2);
         AddProxyListToValue("ftp", proxy_rules_.proxies_for_ftp, &dict2);
         AddProxyListToValue("fallback", proxy_rules_.fallback_proxies, &dict2);
-        dict2.SetKey("proxy_per_scheme", std::move(dict2));
+        dict.SetKey("proxy_per_scheme", std::move(dict2));
         break;
       }
       default:
diff --git a/net/proxy_resolution/proxy_config_unittest.cc b/net/proxy_resolution/proxy_config_unittest.cc
index eeaacce..29813ac 100644
--- a/net/proxy_resolution/proxy_config_unittest.cc
+++ b/net/proxy_resolution/proxy_config_unittest.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "net/proxy_resolution/proxy_config.h"
+#include "base/json/json_writer.h"
 #include "base/stl_util.h"
+#include "base/values.h"
 #include "net/proxy_resolution/proxy_config_service_common_unittest.h"
 #include "net/proxy_resolution/proxy_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -96,6 +98,128 @@
   EXPECT_TRUE(config2.Equals(config1));
 }
 
+struct ProxyConfigToValueTestCase {
+  ProxyConfig config;
+  const char* expected_value_json;
+};
+
+class ProxyConfigToValueTest
+    : public ::testing::TestWithParam<ProxyConfigToValueTestCase> {};
+
+TEST_P(ProxyConfigToValueTest, ToValueJSON) {
+  const ProxyConfigToValueTestCase& test_case = GetParam();
+
+  base::Value value = test_case.config.ToValue();
+
+  std::string json_string;
+  ASSERT_TRUE(base::JSONWriter::Write(value, &json_string));
+
+  EXPECT_EQ(std::string(test_case.expected_value_json), json_string);
+}
+
+ProxyConfigToValueTestCase GetTestCaseDirect() {
+  return {ProxyConfig::CreateDirect(), "{}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseAutoDetect() {
+  return {ProxyConfig::CreateAutoDetect(), "{\"auto_detect\":true}"};
+}
+
+ProxyConfigToValueTestCase GetTestCasePacUrl() {
+  ProxyConfig config;
+  config.set_pac_url(GURL("http://www.example.com/test.pac"));
+
+  return {std::move(config),
+          "{\"pac_url\":\"http://www.example.com/test.pac\"}"};
+}
+
+ProxyConfigToValueTestCase GetTestCasePacUrlMandatory() {
+  ProxyConfig config;
+  config.set_pac_url(GURL("http://www.example.com/test.pac"));
+  config.set_pac_mandatory(true);
+
+  return {std::move(config),
+          "{\"pac_mandatory\":true,\"pac_url\":\"http://www.example.com/"
+          "test.pac\"}"};
+}
+
+ProxyConfigToValueTestCase GetTestCasePacUrlAndAutoDetect() {
+  ProxyConfig config = ProxyConfig::CreateAutoDetect();
+  config.set_pac_url(GURL("http://www.example.com/test.pac"));
+
+  return {
+      std::move(config),
+      "{\"auto_detect\":true,\"pac_url\":\"http://www.example.com/test.pac\"}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseSingleProxy() {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString("https://proxy1:8080");
+
+  return {std::move(config), "{\"single_proxy\":[\"https://proxy1:8080\"]}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseSingleProxyWithBypass() {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString("https://proxy1:8080");
+  config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
+  config.proxy_rules().bypass_rules.AddRuleFromString("192.168.0.1/16");
+
+  return {std::move(config),
+          "{\"bypass_list\":[\"*.google.com\",\"192.168.0.1/"
+          "16\"],\"single_proxy\":[\"https://proxy1:8080\"]}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseSingleProxyWithReversedBypass() {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString("https://proxy1:8080");
+  config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
+  config.proxy_rules().reverse_bypass = true;
+
+  return {std::move(config),
+          "{\"bypass_list\":[\"*.google.com\"],\"reverse_bypass\":true,"
+          "\"single_proxy\":[\"https://proxy1:8080\"]}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseProxyPerScheme() {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString(
+      "http=https://proxy1:8080;https=socks5://proxy2");
+  config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
+  config.set_pac_url(GURL("http://wpad/wpad.dat"));
+  config.set_auto_detect(true);
+
+  return {
+      std::move(config),
+      "{\"auto_detect\":true,\"bypass_list\":[\"*.google.com\"],\"pac_url\":"
+      "\"http://wpad/wpad.dat\",\"proxy_per_scheme\":{\"http\":[\"https://"
+      "proxy1:8080\"],\"https\":[\"socks5://proxy2:1080\"]}}"};
+}
+
+ProxyConfigToValueTestCase GetTestCaseSingleProxyList() {
+  ProxyConfig config;
+  config.proxy_rules().ParseFromString(
+      "https://proxy1:8080,http://proxy2,direct://");
+
+  return {std::move(config),
+          "{\"single_proxy\":[\"https://proxy1:8080\",\"proxy2:80\",\"direct://"
+          "\"]}"};
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    ProxyConfigToValueTest,
+    testing::Values(GetTestCaseDirect(),
+                    GetTestCaseAutoDetect(),
+                    GetTestCasePacUrl(),
+                    GetTestCasePacUrlMandatory(),
+                    GetTestCasePacUrlAndAutoDetect(),
+                    GetTestCaseSingleProxy(),
+                    GetTestCaseSingleProxyWithBypass(),
+                    GetTestCaseSingleProxyWithReversedBypass(),
+                    GetTestCaseProxyPerScheme(),
+                    GetTestCaseSingleProxyList()));
+
 TEST(ProxyConfigTest, ParseProxyRules) {
   const struct {
     const char* proxy_rules;
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
index cff5dec3..dec819a 100644
--- a/net/socket/socket_posix.cc
+++ b/net/socket/socket_posix.cc
@@ -130,7 +130,10 @@
 }
 
 SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
-  StopWatchingAndCleanUp();
+  // It's not safe to release a socket with a pending write.
+  DCHECK(!write_buf_);
+
+  StopWatchingAndCleanUp(false /* close_socket */);
   SocketDescriptor socket_fd = socket_fd_;
   socket_fd_ = kInvalidSocket;
   return socket_fd;
@@ -400,13 +403,7 @@
 void SocketPosix::Close() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  StopWatchingAndCleanUp();
-
-  if (socket_fd_ != kInvalidSocket) {
-    if (IGNORE_EINTR(close(socket_fd_)) < 0)
-      PLOG(ERROR) << "close() failed";
-    socket_fd_ = kInvalidSocket;
-  }
+  StopWatchingAndCleanUp(true /* close_socket */);
 }
 
 void SocketPosix::DetachFromThread() {
@@ -544,7 +541,7 @@
   std::move(write_callback_).Run(rv);
 }
 
-void SocketPosix::StopWatchingAndCleanUp() {
+void SocketPosix::StopWatchingAndCleanUp(bool close_socket) {
   bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
   DCHECK(ok);
   ok = read_socket_watcher_.StopWatchingFileDescriptor();
@@ -552,6 +549,16 @@
   ok = write_socket_watcher_.StopWatchingFileDescriptor();
   DCHECK(ok);
 
+  // These needs to be done after the StopWatchingFileDescriptor() calls, but
+  // before deleting the write buffer.
+  if (close_socket) {
+    if (socket_fd_ != kInvalidSocket) {
+      if (IGNORE_EINTR(close(socket_fd_)) < 0)
+        DPLOG(ERROR) << "close() failed";
+      socket_fd_ = kInvalidSocket;
+    }
+  }
+
   if (!accept_callback_.is_null()) {
     accept_socket_ = NULL;
     accept_callback_.Reset();
diff --git a/net/socket/socket_posix.h b/net/socket/socket_posix.h
index ff7cbb6..dc3f210 100644
--- a/net/socket/socket_posix.h
+++ b/net/socket/socket_posix.h
@@ -44,7 +44,8 @@
   // to be accepted, but must not be actually connected.
   int AdoptUnconnectedSocket(SocketDescriptor socket);
 
-  // Releases ownership of |socket_fd_| to caller.
+  // Releases ownership of |socket_fd_| to caller. There must be no pending
+  // write.
   SocketDescriptor ReleaseConnectedSocket();
 
   int Bind(const SockaddrStorage& address);
@@ -119,7 +120,8 @@
   int DoWrite(IOBuffer* buf, int buf_len);
   void WriteCompleted();
 
-  void StopWatchingAndCleanUp();
+  // |close_socket| indicates whether the socket should also be closed.
+  void StopWatchingAndCleanUp(bool close_socket);
 
   SocketDescriptor socket_fd_;
 
diff --git a/services/image_annotation/annotator.cc b/services/image_annotation/annotator.cc
index 4b3f87a..32c8a7a 100644
--- a/services/image_annotation/annotator.cc
+++ b/services/image_annotation/annotator.cc
@@ -22,6 +22,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/image_annotation/image_annotation_metrics.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "url/gurl.h"
 
@@ -624,7 +625,7 @@
     const std::unique_ptr<std::string> json_response) {
   ReportServerNetError(server_request_it->get()->NetError());
 
-  if (const network::ResourceResponseInfo* const response_info =
+  if (const network::mojom::URLResponseHead* const response_info =
           server_request_it->get()->ResponseInfo()) {
     ReportServerResponseCode(response_info->headers->response_code());
     ReportServerLatency(response_info->response_time -
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc
index b6b6730..c713aa83 100644
--- a/services/network/cors/preflight_controller.cc
+++ b/services/network/cors/preflight_controller.cc
@@ -19,6 +19,7 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "url/gurl.h"
 
 namespace network {
@@ -125,7 +126,7 @@
 
 std::unique_ptr<PreflightResult> CreatePreflightResult(
     const GURL& final_url,
-    const ResourceResponseHead& head,
+    const mojom::URLResponseHead& head,
     const ResourceRequest& original_request,
     bool tainted,
     base::Optional<CorsErrorStatus>* detected_error_status) {
@@ -218,7 +219,7 @@
 
  private:
   void HandleRedirect(const net::RedirectInfo& redirect_info,
-                      const network::ResourceResponseHead& response_head,
+                      const network::mojom::URLResponseHead& response_head,
                       std::vector<std::string>* to_be_removed_headers) {
     // Preflight should not allow any redirect.
     FinalizeLoader();
@@ -232,7 +233,7 @@
   }
 
   void HandleResponseHeader(const GURL& final_url,
-                            const ResourceResponseHead& head) {
+                            const mojom::URLResponseHead& head) {
     FinalizeLoader();
 
     base::Optional<CorsErrorStatus> detected_error_status;
@@ -310,7 +311,7 @@
 std::unique_ptr<PreflightResult>
 PreflightController::CreatePreflightResultForTesting(
     const GURL& final_url,
-    const ResourceResponseHead& head,
+    const mojom::URLResponseHead& head,
     const ResourceRequest& original_request,
     bool tainted,
     base::Optional<CorsErrorStatus>* detected_error_status) {
diff --git a/services/network/cors/preflight_controller.h b/services/network/cors/preflight_controller.h
index 1f374a78..596de37 100644
--- a/services/network/cors/preflight_controller.h
+++ b/services/network/cors/preflight_controller.h
@@ -21,12 +21,11 @@
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace network {
 
-struct ResourceResponseHead;
-
 namespace cors {
 
 // A class to manage CORS-preflight, making a CORS-preflight request, checking
@@ -43,7 +42,7 @@
   // Creates a PreflightResult for a specified response parameters for testing.
   static std::unique_ptr<PreflightResult> CreatePreflightResultForTesting(
       const GURL& final_url,
-      const ResourceResponseHead& head,
+      const mojom::URLResponseHead& head,
       const ResourceRequest& original_request,
       bool tainted,
       base::Optional<CorsErrorStatus>* detected_error_status);
diff --git a/services/network/cors/preflight_controller_unittest.cc b/services/network/cors/preflight_controller_unittest.cc
index 3daf074..fe326619 100644
--- a/services/network/cors/preflight_controller_unittest.cc
+++ b/services/network/cors/preflight_controller_unittest.cc
@@ -390,7 +390,7 @@
 
 TEST_F(PreflightControllerTest, CheckResponseWithNullHeaders) {
   GURL url = GURL("https://google.com/finullurl");
-  const ResourceResponseHead response_head;
+  const mojom::URLResponseHead response_head;
   ResourceRequest request;
   request.url = url;
   request.request_initiator = url::Origin::Create(request.url);
diff --git a/services/network/origin_policy/origin_policy_fetcher.cc b/services/network/origin_policy/origin_policy_fetcher.cc
index 209c47c..09160a0 100644
--- a/services/network/origin_policy/origin_policy_fetcher.cc
+++ b/services/network/origin_policy/origin_policy_fetcher.cc
@@ -10,8 +10,8 @@
 #include "net/http/http_util.h"
 #include "services/network/origin_policy/origin_policy_manager.h"
 #include "services/network/origin_policy/origin_policy_parser.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace network {
 
@@ -82,7 +82,7 @@
 
 void OriginPolicyFetcher::OnPolicyRedirect(
     const net::RedirectInfo& redirect_info,
-    const network::ResourceResponseHead& response_head,
+    const mojom::URLResponseHead& response_head,
     std::vector<std::string>* to_be_removed_headers) {
   if (IsValidRedirect(redirect_info)) {
     must_redirect_ = false;
diff --git a/services/network/origin_policy/origin_policy_fetcher.h b/services/network/origin_policy/origin_policy_fetcher.h
index 35fb686c..3810412 100644
--- a/services/network/origin_policy/origin_policy_fetcher.h
+++ b/services/network/origin_policy/origin_policy_fetcher.h
@@ -14,12 +14,12 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/origin_policy_manager.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/origin.h"
 
 namespace network {
 
 class OriginPolicyManager;
-struct ResourceResponseHead;
 
 class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyFetcher {
  public:
@@ -54,12 +54,12 @@
   using FetchCallback = base::OnceCallback<void(std::unique_ptr<std::string>)>;
   using RedirectCallback =
       base::RepeatingCallback<void(const net::RedirectInfo&,
-                                   const ResourceResponseHead&,
+                                   const mojom::URLResponseHead&,
                                    std::vector<std::string>*)>;
 
   void OnPolicyHasArrived(std::unique_ptr<std::string> policy_content);
   void OnPolicyRedirect(const net::RedirectInfo& redirect_info,
-                        const network::ResourceResponseHead& response_head,
+                        const mojom::URLResponseHead& response_head,
                         std::vector<std::string>* to_be_removed_headers);
   void FetchPolicy(mojom::URLLoaderFactory* factory);
 
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc
index 2c4e2b0..5efac8f 100644
--- a/services/network/public/cpp/simple_url_loader.cc
+++ b/services/network/public/cpp/simple_url_loader.cc
@@ -37,11 +37,11 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/data_element.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/mojom/data_pipe_getter.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace network {
 
@@ -230,7 +230,7 @@
   void SetTimeoutDuration(base::TimeDelta timeout_duration) override;
 
   int NetError() const override;
-  const ResourceResponseHead* ResponseInfo() const override;
+  const mojom::URLResponseHead* ResponseInfo() const override;
   const GURL& GetFinalURL() const override;
   bool LoadedFromCache() const override;
   int64_t GetContentSize() const override;
@@ -281,7 +281,7 @@
 
     bool loaded_from_cache = false;
 
-    std::unique_ptr<ResourceResponseHead> response_info;
+    mojom::URLResponseHeadPtr response_info;
   };
 
   // Prepares internal state to start a request, and then calls StartRequest().
@@ -1389,7 +1389,7 @@
   return request_state_->received_body_size;
 }
 
-const ResourceResponseHead* SimpleURLLoaderImpl::ResponseInfo() const {
+const mojom::URLResponseHead* SimpleURLLoaderImpl::ResponseInfo() const {
   // Should only be called once the request is compelete.
   DCHECK(request_state_->finished);
   return request_state_->response_info.get();
@@ -1576,14 +1576,13 @@
     // Copy |final_url_| to a stack allocated GURL so it remains valid even if
     // the callback deletes |this|.
     GURL final_url = final_url_;
-    std::move(on_response_started_callback_).Run(final_url, response_head);
+    std::move(on_response_started_callback_).Run(final_url, *response_head);
     // If deleted by the callback, bail now.
     if (!weak_this)
       return;
   }
 
-  request_state_->response_info =
-      std::make_unique<ResourceResponseHead>(response_head);
+  request_state_->response_info = std::move(response_head);
   if (!allow_http_error_results_ && response_code / 100 != 2)
     FinishWithResult(net::ERR_HTTP_RESPONSE_CODE_FAILURE);
 }
@@ -1604,7 +1603,7 @@
     if (callback) {
       base::WeakPtr<SimpleURLLoaderImpl> weak_this =
           weak_ptr_factory_.GetWeakPtr();
-      callback.Run(redirect_info, response_head, &removed_headers);
+      callback.Run(redirect_info, *response_head, &removed_headers);
       // If deleted by the callback, bail now.
       if (!weak_this)
         return;
diff --git a/services/network/public/cpp/simple_url_loader.h b/services/network/public/cpp/simple_url_loader.h
index 255cb183..918b70a 100644
--- a/services/network/public/cpp/simple_url_loader.h
+++ b/services/network/public/cpp/simple_url_loader.h
@@ -15,7 +15,7 @@
 #include "base/callback_forward.h"
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 
 class GURL;
 
@@ -115,14 +115,14 @@
   // removed for requests when a redirect to a non-Google URL occurs.
   using OnRedirectCallback =
       base::RepeatingCallback<void(const net::RedirectInfo& redirect_info,
-                                   const ResourceResponseHead& response_head,
+                                   const mojom::URLResponseHead& response_head,
                                    std::vector<std::string>* removed_headers)>;
 
   // Callback used when a response is received. It is safe to delete the
   // SimpleURLLoader during the callback.
   using OnResponseStartedCallback =
       base::OnceCallback<void(const GURL& final_url,
-                              const ResourceResponseHead& response_head)>;
+                              const mojom::URLResponseHead& response_head)>;
 
   // Callback used when an upload progress is reported. It is safe to
   // delete the SimpleURLLoader during the callback.
@@ -331,10 +331,10 @@
   // only be called once the loader has informed the caller of completion.
   virtual int NetError() const = 0;
 
-  // The ResourceResponseHead for the request. Will be nullptr if ResponseInfo
+  // The URLResponseHead for the request. Will be nullptr if ResponseInfo
   // was never received. May only be called once the loader has informed the
   // caller of completion.
-  virtual const ResourceResponseHead* ResponseInfo() const = 0;
+  virtual const mojom::URLResponseHead* ResponseInfo() const = 0;
 
   // Returns the URL that this loader is processing. May only be called once the
   // loader has informed the caller of completion.
diff --git a/services/network/public/cpp/simple_url_loader_unittest.cc b/services/network/public/cpp/simple_url_loader_unittest.cc
index ec596df..bae914b 100644
--- a/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -47,11 +47,11 @@
 #include "net/url_request/redirect_info.h"
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
 #include "services/network/test/test_network_context_client.h"
 #include "services/network/test/test_network_service_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -767,16 +767,16 @@
 
   int num_redirects = 0;
   net::RedirectInfo redirect_info;
-  network::ResourceResponseHead response_head;
+  network::mojom::URLResponseHeadPtr response_head;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, net::RedirectInfo* redirect_info_ptr,
-         network::ResourceResponseHead* response_head_ptr,
+         network::mojom::URLResponseHeadPtr* response_head_ptr,
          const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) {
         ++*num_redirects;
         *redirect_info_ptr = redirect_info;
-        *response_head_ptr = response_head;
+        *response_head_ptr = response_head.Clone();
       },
       base::Unretained(&num_redirects), base::Unretained(&redirect_info),
       base::Unretained(&response_head)));
@@ -790,8 +790,8 @@
 
   EXPECT_EQ(1, num_redirects);
   EXPECT_EQ(test_server_.GetURL("/echo"), redirect_info.new_url);
-  ASSERT_TRUE(response_head.headers);
-  EXPECT_EQ(301, response_head.headers->response_code());
+  ASSERT_TRUE(response_head->headers);
+  EXPECT_EQ(301, response_head->headers->response_code());
 }
 
 // Make sure OnRedirectCallback is invoked on each redirect.
@@ -805,7 +805,7 @@
   int num_redirects = 0;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) { ++*num_redirects; },
       base::Unretained(&num_redirects)));
 
@@ -830,7 +830,7 @@
       base::BindRepeating(
           [](std::unique_ptr<SimpleLoaderTestHelper> test_helper,
              base::RunLoop* run_loop, const net::RedirectInfo& redirect_info,
-             const network::ResourceResponseHead& response_head,
+             const network::mojom::URLResponseHead& response_head,
              std::vector<std::string>* to_be_removed_headers) {
             test_helper.reset();
             // Access the parameters to trigger a memory error if they have been
@@ -860,7 +860,7 @@
   int num_redirects = 0;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) { ++*num_redirects; },
       base::Unretained(&num_redirects)));
 
@@ -888,7 +888,7 @@
   int num_redirects = 0;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) { ++*num_redirects; },
       base::Unretained(&num_redirects)));
 
@@ -920,7 +920,7 @@
   int num_redirects = 0;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) {
         ++*num_redirects;
         to_be_removed_headers->push_back("foo");
@@ -954,7 +954,7 @@
   int num_redirects = 0;
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) {
         ++*num_redirects;
         to_be_removed_headers->push_back("bar");
@@ -989,7 +989,7 @@
   test_helper->simple_url_loader()->SetOnResponseStartedCallback(base::BindOnce(
       [](GURL* out_final_url, std::string* foo_header_value,
          base::OnceClosure quit_closure, const GURL& final_url,
-         const ResourceResponseHead& response_head) {
+         const mojom::URLResponseHead& response_head) {
         *out_final_url = final_url;
         if (response_head.headers) {
           response_head.headers->EnumerateHeader(/*iter=*/nullptr, "foo",
@@ -1015,7 +1015,7 @@
       base::BindOnce(
           [](std::unique_ptr<SimpleLoaderTestHelper> test_helper,
              base::OnceClosure quit_closure, const GURL& final_url,
-             const ResourceResponseHead& response_head) {
+             const mojom::URLResponseHead& response_head) {
             // Delete the SimpleURLLoader.
             test_helper.reset();
             // Access the parameters to trigger a memory error if they have been
@@ -1827,41 +1827,41 @@
           redirect_info.new_url = GURL("bar://foo/");
           redirect_info.status_code = 301;
 
-          network::ResourceResponseHead response_info;
+          auto response_info = network::mojom::URLResponseHead::New();
           std::string headers(
               "HTTP/1.0 301 The Response Has Moved to Another Server\n"
               "Location: bar://foo/");
-          response_info.headers =
+          response_info->headers =
               base::MakeRefCounted<net::HttpResponseHeaders>(
                   net::HttpUtil::AssembleRawHeaders(headers));
-          client_->OnReceiveRedirect(redirect_info, response_info);
+          client_->OnReceiveRedirect(redirect_info, std::move(response_info));
           break;
         }
         case TestLoaderEvent::kReceivedResponse: {
-          network::ResourceResponseHead response_info;
+          auto response_info = network::mojom::URLResponseHead::New();
           std::string headers("HTTP/1.0 200 OK");
-          response_info.headers =
+          response_info->headers =
               base::MakeRefCounted<net::HttpResponseHeaders>(
                   net::HttpUtil::AssembleRawHeaders(headers));
-          client_->OnReceiveResponse(response_info);
+          client_->OnReceiveResponse(std::move(response_info));
           break;
         }
         case TestLoaderEvent::kReceived401Response: {
-          network::ResourceResponseHead response_info;
+          auto response_info = network::mojom::URLResponseHead::New();
           std::string headers("HTTP/1.0 401 Client Borkage");
-          response_info.headers =
+          response_info->headers =
               base::MakeRefCounted<net::HttpResponseHeaders>(
                   net::HttpUtil::AssembleRawHeaders(headers));
-          client_->OnReceiveResponse(response_info);
+          client_->OnReceiveResponse(std::move(response_info));
           break;
         }
         case TestLoaderEvent::kReceived501Response: {
-          network::ResourceResponseHead response_info;
+          auto response_info = network::mojom::URLResponseHead::New();
           std::string headers("HTTP/1.0 501 Server Borkage");
-          response_info.headers =
+          response_info->headers =
               base::MakeRefCounted<net::HttpResponseHeaders>(
                   net::HttpUtil::AssembleRawHeaders(headers));
-          client_->OnReceiveResponse(response_info);
+          client_->OnReceiveResponse(std::move(response_info));
           break;
         }
         case TestLoaderEvent::kBodyBufferReceived: {
@@ -2540,7 +2540,7 @@
       1, SimpleURLLoader::RETRY_ON_5XX);
   test_helper->simple_url_loader()->SetOnRedirectCallback(base::BindRepeating(
       [](int* num_redirects, const net::RedirectInfo& redirect_info,
-         const network::ResourceResponseHead& response_head,
+         const network::mojom::URLResponseHead& response_head,
          std::vector<std::string>* to_be_removed_headers) { ++*num_redirects; },
       base::Unretained(&num_redirects)));
   loader_factory.RunTest(test_helper.get());
diff --git a/services/network/public/mojom/websocket.mojom b/services/network/public/mojom/websocket.mojom
index 0b943144..db0385d 100644
--- a/services/network/public/mojom/websocket.mojom
+++ b/services/network/public/mojom/websocket.mojom
@@ -131,7 +131,9 @@
   //   the first message. If |type| is WebSocketMessageType.TEXT, then the
   //   concatenation of the |data| from every frame in the message must be valid
   //   UTF-8. If |fin| is not set, |data| must be non-empty.
-  SendFrame(bool fin, WebSocketMessageType type, array<uint8> data);
+  SendFrame(bool fin,
+            WebSocketMessageType type,
+            mojo_base.mojom.ReadOnlyBuffer data);
 
   // Let browser to start receiving WebSocket data frames from network stream.
   // TODO(yoichio): Remove this by move Connect() after checking throttle at
diff --git a/services/network/websocket.cc b/services/network/websocket.cc
index 133f42d3..8c010d97 100644
--- a/services/network/websocket.cc
+++ b/services/network/websocket.cc
@@ -5,6 +5,7 @@
 #include "services/network/websocket.h"
 
 #include <inttypes.h>
+#include <string.h>
 
 #include <utility>
 
@@ -419,7 +420,7 @@
 
 void WebSocket::SendFrame(bool fin,
                           mojom::WebSocketMessageType type,
-                          const std::vector<uint8_t>& data) {
+                          base::span<const uint8_t> data) {
   DVLOG(3) << "WebSocket::SendFrame @" << reinterpret_cast<void*>(this)
            << " fin=" << fin << " type=" << type << " data is " << data.size()
            << " bytes";
@@ -435,7 +436,7 @@
 
   // TODO(darin): Avoid this copy.
   auto data_to_pass = base::MakeRefCounted<net::IOBuffer>(data.size());
-  std::copy(data.begin(), data.end(), data_to_pass->data());
+  memcpy(data_to_pass->data(), data.data(), data.size());
 
   channel_->SendFrame(fin, MessageTypeToOpCode(type), std::move(data_to_pass),
                       data.size());
diff --git a/services/network/websocket.h b/services/network/websocket.h
index bf0fa54..a31430f 100644
--- a/services/network/websocket.h
+++ b/services/network/websocket.h
@@ -13,6 +13,7 @@
 
 #include "base/component_export.h"
 #include "base/containers/queue.h"
+#include "base/containers/span.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -67,7 +68,7 @@
   // mojom::WebSocket methods:
   void SendFrame(bool fin,
                  mojom::WebSocketMessageType type,
-                 const std::vector<uint8_t>& data) override;
+                 base::span<const uint8_t> data) override;
   void StartReceiving() override;
   void StartClosingHandshake(uint16_t code, const std::string& reason) override;
 
diff --git a/services/resource_coordinator/BUILD.gn b/services/resource_coordinator/BUILD.gn
index ccaa4f7..cc38677 100644
--- a/services/resource_coordinator/BUILD.gn
+++ b/services/resource_coordinator/BUILD.gn
@@ -15,8 +15,6 @@
     "memory_instrumentation/graph.h",
     "memory_instrumentation/graph_processor.cc",
     "memory_instrumentation/graph_processor.h",
-    "memory_instrumentation/process_map.cc",
-    "memory_instrumentation/process_map.h",
     "memory_instrumentation/queued_request.cc",
     "memory_instrumentation/queued_request.h",
     "memory_instrumentation/queued_request_dispatcher.cc",
@@ -46,7 +44,6 @@
     "memory_instrumentation/coordinator_impl_unittest.cc",
     "memory_instrumentation/graph_processor_unittest.cc",
     "memory_instrumentation/graph_unittest.cc",
-    "memory_instrumentation/process_map_unittest.cc",
     "public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits_unittest.cc",
     "public/cpp/memory_instrumentation/os_metrics_unittest.cc",
     "public/cpp/memory_instrumentation/tracing_integration_unittest.cc",
@@ -60,9 +57,6 @@
     "//mojo/public/cpp/bindings",
     "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//services/resource_coordinator/public/cpp/memory_instrumentation:memory_instrumentation",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/cpp/test:test_support",
-    "//services/service_manager/public/mojom",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/services/resource_coordinator/DEPS b/services/resource_coordinator/DEPS
index f3a0e682..9765ce49 100644
--- a/services/resource_coordinator/DEPS
+++ b/services/resource_coordinator/DEPS
@@ -2,5 +2,4 @@
   "+components/ukm/test_ukm_recorder.h",
   "+third_party/smhasher",
   "+services/metrics/public",
-  "+services/service_manager/public"
 ]
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
index fea9f790..0659a2d 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_request_args.h"
@@ -27,7 +28,6 @@
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/identity.h"
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 #include "base/mac/mac_util.h"
@@ -59,16 +59,9 @@
 
 }  // namespace
 
-
-// static
-CoordinatorImpl* CoordinatorImpl::GetInstance() {
-  return g_coordinator_impl;
-}
-
-CoordinatorImpl::CoordinatorImpl(service_manager::Connector* connector)
+CoordinatorImpl::CoordinatorImpl()
     : next_dump_id_(0),
       client_process_timeout_(base::TimeDelta::FromSeconds(15)) {
-  process_map_ = std::make_unique<ProcessMap>(connector);
   DCHECK(!g_coordinator_impl);
   g_coordinator_impl = this;
   base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id(
@@ -82,35 +75,44 @@
   g_coordinator_impl = nullptr;
 }
 
-base::ProcessId CoordinatorImpl::GetProcessIdForClientIdentity(
-    service_manager::Identity identity) const {
-  DCHECK(identity.IsValid());
-  return process_map_->GetProcessId(identity);
+// static
+CoordinatorImpl* CoordinatorImpl::GetInstance() {
+  return g_coordinator_impl;
 }
 
-std::map<base::ProcessId, std::vector<std::string>>
-CoordinatorImpl::ComputePidToServiceNamesMap() const {
-  return process_map_->ComputePidToServiceNamesMap();
+void CoordinatorImpl::BindController(
+    mojo::PendingReceiver<mojom::CoordinatorController> receiver) {
+  controller_receiver_.Bind(std::move(receiver));
 }
 
-service_manager::Identity CoordinatorImpl::GetClientIdentityForCurrentRequest()
-    const {
-  return receivers_.current_context();
+void CoordinatorImpl::RegisterHeapProfiler(
+    mojo::PendingRemote<mojom::HeapProfiler> profiler,
+    mojo::PendingReceiver<mojom::HeapProfilerHelper> helper_receiver) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  heap_profiler_.Bind(std::move(profiler));
+  heap_profiler_helper_receiver_.Bind(std::move(helper_receiver));
 }
 
-void CoordinatorImpl::BindCoordinatorReceiver(
+void CoordinatorImpl::RegisterClientProcess(
     mojo::PendingReceiver<mojom::Coordinator> receiver,
-    const service_manager::BindSourceInfo& source_info) {
+    mojo::PendingRemote<mojom::ClientProcess> client_process,
+    mojom::ProcessType process_type,
+    base::ProcessId process_id,
+    const base::Optional<std::string>& service_name) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  receivers_.Add(this, std::move(receiver), source_info.identity);
-}
-
-void CoordinatorImpl::BindHeapProfilerHelperRequest(
-    mojom::HeapProfilerHelperRequest request,
-    const service_manager::BindSourceInfo& source_info) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  bindings_heap_profiler_helper_.AddBinding(this, std::move(request),
-                                            source_info.identity);
+  mojo::Remote<mojom::ClientProcess> process(std::move(client_process));
+  coordinator_receivers_.Add(this, std::move(receiver), process_id);
+  process.set_disconnect_handler(
+      base::BindOnce(&CoordinatorImpl::UnregisterClientProcess,
+                     base::Unretained(this), process_id));
+  auto result = clients_.emplace(
+      process_id, std::make_unique<ClientInfo>(std::move(process), process_type,
+                                               service_name));
+  DCHECK(result.second) << "Cannot register process " << process_id
+                        << " with type " << static_cast<int>(process_type)
+                        << ". Already registered for "
+                        << static_cast<int>(
+                               clients_.find(process_id)->second->process_type);
 }
 
 void CoordinatorImpl::RequestGlobalMemoryDump(
@@ -196,12 +198,6 @@
                                   base::BindOnce(adapter, std::move(callback)));
 }
 
-void CoordinatorImpl::RegisterHeapProfiler(
-    mojom::HeapProfilerPtr heap_profiler) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  heap_profiler_ = std::move(heap_profiler);
-}
-
 void CoordinatorImpl::GetVmRegionsForHeapProfiler(
     const std::vector<base::ProcessId>& pids,
     GetVmRegionsForHeapProfilerCallback callback) {
@@ -211,13 +207,12 @@
       std::make_unique<QueuedVmRegionRequest>(dump_guid, std::move(callback));
   in_progress_vm_region_requests_[dump_guid] = std::move(request);
 
-  auto names_for_pid = ComputePidToServiceNamesMap();
   std::vector<QueuedRequestDispatcher::ClientInfo> clients;
-  for (const auto& kv : clients_) {
-    auto client_identity = kv.second->identity;
-    const base::ProcessId pid = GetProcessIdForClientIdentity(client_identity);
-    clients.emplace_back(kv.second->client.get(), pid, kv.second->process_type,
-                         std::move(names_for_pid[pid]));
+  for (const auto& entry : clients_) {
+    const base::ProcessId pid = entry.first;
+    clients.emplace_back(entry.second->client.get(), pid,
+                         entry.second->process_type,
+                         entry.second->service_name);
   }
 
   QueuedVmRegionRequest* request_ptr =
@@ -230,24 +225,7 @@
   FinalizeVmRegionDumpIfAllManagersReplied(dump_guid);
 }
 
-void CoordinatorImpl::RegisterClientProcess(
-    mojom::ClientProcessPtr client_process_ptr,
-    mojom::ProcessType process_type) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  mojom::ClientProcess* client_process = client_process_ptr.get();
-  client_process_ptr.set_connection_error_handler(
-      base::BindOnce(&CoordinatorImpl::UnregisterClientProcess,
-                     weak_ptr_factory_.GetWeakPtr(), client_process));
-  auto identity = GetClientIdentityForCurrentRequest();
-  auto client_info = std::make_unique<ClientInfo>(
-      std::move(identity), std::move(client_process_ptr), process_type);
-  auto iterator_and_inserted =
-      clients_.emplace(client_process, std::move(client_info));
-  DCHECK(iterator_and_inserted.second);
-}
-
-void CoordinatorImpl::UnregisterClientProcess(
-    mojom::ClientProcess* client_process) {
+void CoordinatorImpl::UnregisterClientProcess(base::ProcessId process_id) {
   QueuedRequest* request = GetCurrentRequest();
   if (request != nullptr) {
     // Check if we are waiting for an ack from this client process.
@@ -258,9 +236,9 @@
       // increment the iterator in advance while keeping a reference to the
       // current element.
       std::set<QueuedRequest::PendingResponse>::iterator current = it++;
-      if (current->client != client_process)
+      if (current->process_id != process_id)
         continue;
-      RemovePendingResponse(client_process, current->type);
+      RemovePendingResponse(process_id, current->type);
       request->failed_memory_dump_count++;
     }
     FinalizeGlobalMemoryDumpIfAllManagersReplied();
@@ -271,7 +249,7 @@
     auto it = request->pending_responses.begin();
     while (it != request->pending_responses.end()) {
       auto current = it++;
-      if (*current == client_process) {
+      if (*current == process_id) {
         request->pending_responses.erase(current);
       }
     }
@@ -288,7 +266,7 @@
             weak_ptr_factory_.GetWeakPtr(), pair.second->dump_guid));
   }
 
-  size_t num_deleted = clients_.erase(client_process);
+  size_t num_deleted = clients_.erase(process_id);
   DCHECK(num_deleted == 1);
 }
 
@@ -379,19 +357,12 @@
   if (request == nullptr)
     return;
 
-  auto names_for_pid = ComputePidToServiceNamesMap();
   std::vector<QueuedRequestDispatcher::ClientInfo> clients;
-  for (const auto& kv : clients_) {
-    auto client_identity = kv.second->identity;
-    const base::ProcessId pid = GetProcessIdForClientIdentity(client_identity);
-    if (pid == base::kNullProcessId) {
-      VLOG(1) << "Couldn't find a PID for client "
-              << client_identity.ToString();
-      continue;
-    }
-
-    clients.emplace_back(kv.second->client.get(), pid, kv.second->process_type,
-                         std::move(names_for_pid[pid]));
+  for (const auto& entry : clients_) {
+    const base::ProcessId pid = entry.first;
+    clients.emplace_back(entry.second->client.get(), pid,
+                         entry.second->process_type,
+                         entry.second->service_name);
   }
 
   auto chrome_callback =
@@ -444,7 +415,7 @@
 }
 
 void CoordinatorImpl::OnChromeMemoryDumpResponse(
-    mojom::ClientProcess* client,
+    base::ProcessId process_id,
     bool success,
     uint64_t dump_guid,
     std::unique_ptr<base::trace_event::ProcessMemoryDump> chrome_memory_dump) {
@@ -455,13 +426,14 @@
     return;
   }
 
-  RemovePendingResponse(client, ResponseType::kChromeDump);
+  RemovePendingResponse(process_id, ResponseType::kChromeDump);
 
-  if (!clients_.count(client)) {
+  if (!base::Contains(clients_, process_id)) {
     VLOG(1) << "Received a memory dump response from an unregistered client";
     return;
   }
-  auto* response = &request->responses[client];
+
+  auto* response = &request->responses[process_id];
   response->chrome_dump = std::move(chrome_memory_dump);
 
   if (!success) {
@@ -473,7 +445,7 @@
 }
 
 void CoordinatorImpl::OnOSMemoryDumpResponse(uint64_t dump_guid,
-                                             mojom::ClientProcess* client,
+                                             base::ProcessId process_id,
                                              bool success,
                                              OSMemDumpMap os_dumps) {
   using ResponseType = QueuedRequest::PendingResponse::Type;
@@ -483,14 +455,14 @@
     return;
   }
 
-  RemovePendingResponse(client, ResponseType::kOSDump);
+  RemovePendingResponse(process_id, ResponseType::kOSDump);
 
-  if (!clients_.count(client)) {
+  if (!base::Contains(clients_, process_id)) {
     VLOG(1) << "Received a memory dump response from an unregistered client";
     return;
   }
 
-  request->responses[client].os_dumps = std::move(os_dumps);
+  request->responses[process_id].os_dumps = std::move(os_dumps);
 
   if (!success) {
     request->failed_memory_dump_count++;
@@ -501,7 +473,7 @@
 }
 
 void CoordinatorImpl::OnOSMemoryDumpForVMRegions(uint64_t dump_guid,
-                                                 mojom::ClientProcess* client,
+                                                 base::ProcessId process_id,
                                                  bool success,
                                                  OSMemDumpMap os_dumps) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -509,10 +481,10 @@
   DCHECK(request_it != in_progress_vm_region_requests_.end());
 
   QueuedVmRegionRequest* request = request_it->second.get();
-  auto it = request->pending_responses.find(client);
+  auto it = request->pending_responses.find(process_id);
   DCHECK(it != request->pending_responses.end());
   request->pending_responses.erase(it);
-  request->responses[client].os_dumps = std::move(os_dumps);
+  request->responses[process_id].os_dumps = std::move(os_dumps);
 
   FinalizeVmRegionDumpIfAllManagersReplied(request->dump_guid);
 }
@@ -563,14 +535,14 @@
 }
 
 void CoordinatorImpl::RemovePendingResponse(
-    mojom::ClientProcess* client,
+    base::ProcessId process_id,
     QueuedRequest::PendingResponse::Type type) {
   QueuedRequest* request = GetCurrentRequest();
   if (request == nullptr) {
     NOTREACHED() << "No current dump request.";
     return;
   }
-  auto it = request->pending_responses.find({client, type});
+  auto it = request->pending_responses.find({process_id, type});
   if (it == request->pending_responses.end()) {
     VLOG(1) << "Unexpected memory dump response";
     return;
@@ -604,12 +576,13 @@
 }
 
 CoordinatorImpl::ClientInfo::ClientInfo(
-    const service_manager::Identity& identity,
-    mojom::ClientProcessPtr client,
-    mojom::ProcessType process_type)
-    : identity(identity),
-      client(std::move(client)),
-      process_type(process_type) {}
-CoordinatorImpl::ClientInfo::~ClientInfo() {}
+    mojo::Remote<mojom::ClientProcess> client,
+    mojom::ProcessType process_type,
+    base::Optional<std::string> service_name)
+    : client(std::move(client)),
+      process_type(process_type),
+      service_name(std::move(service_name)) {}
+
+CoordinatorImpl::ClientInfo::~ClientInfo() = default;
 
 }  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.h b/services/resource_coordinator/memory_instrumentation/coordinator_impl.h
index 4b017e4..8b18b2c 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.h
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.h
@@ -8,26 +8,19 @@
 #include <list>
 #include <map>
 #include <set>
-#include <unordered_map>
+#include <string>
 
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "base/trace_event/memory_dump_request_args.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/resource_coordinator/memory_instrumentation/process_map.h"
 #include "services/resource_coordinator/memory_instrumentation/queued_request.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/identity.h"
-
-namespace service_manager {
-struct BindSourceInfo;
-class Connector;
-}
 
 namespace memory_instrumentation {
 
@@ -37,28 +30,32 @@
 // - Provides global (i.e. for all processes) memory snapshots on demand.
 //   Global snapshots are obtained by requesting in-process snapshots from each
 //   registered client and aggregating them.
-class CoordinatorImpl : public Coordinator,
+class CoordinatorImpl : public mojom::CoordinatorController,
                         public mojom::Coordinator,
                         public mojom::HeapProfilerHelper {
  public:
+  CoordinatorImpl();
+  ~CoordinatorImpl() override;
+
   // The getter of the unique instance.
   static CoordinatorImpl* GetInstance();
 
-  CoordinatorImpl(service_manager::Connector* connector);
+  void BindController(
+      mojo::PendingReceiver<mojom::CoordinatorController> receiver);
 
-  // Binds a client library to this coordinator instance.
-  void BindCoordinatorReceiver(
-      mojo::PendingReceiver<mojom::Coordinator>,
-      const service_manager::BindSourceInfo& source_info) override;
+  void RegisterHeapProfiler(
+      mojo::PendingRemote<mojom::HeapProfiler> profiler,
+      mojo::PendingReceiver<mojom::HeapProfilerHelper> helper_receiver);
 
-  void BindHeapProfilerHelperRequest(
-      mojom::HeapProfilerHelperRequest request,
-      const service_manager::BindSourceInfo& source_info);
+  // mojom::CoordinatorController implementation.
+  void RegisterClientProcess(
+      mojo::PendingReceiver<mojom::Coordinator> receiver,
+      mojo::PendingRemote<mojom::ClientProcess> client_process,
+      mojom::ProcessType process_type,
+      base::ProcessId process_id,
+      const base::Optional<std::string>& service_name) override;
 
   // mojom::Coordinator implementation.
-  void RegisterClientProcess(mojom::ClientProcessPtr,
-                             mojom::ProcessType) override;
-  void UnregisterClientProcess(mojom::ClientProcess*);
   void RequestGlobalMemoryDump(
       base::trace_event::MemoryDumpType,
       base::trace_event::MemoryDumpLevelOfDetail,
@@ -75,63 +72,53 @@
       base::trace_event::MemoryDumpType,
       base::trace_event::MemoryDumpLevelOfDetail,
       RequestGlobalMemoryDumpAndAppendToTraceCallback) override;
-  void RegisterHeapProfiler(mojom::HeapProfilerPtr heap_profiler) override;
 
   // mojom::HeapProfilerHelper implementation.
   void GetVmRegionsForHeapProfiler(
       const std::vector<base::ProcessId>& pids,
       GetVmRegionsForHeapProfilerCallback) override;
 
- protected:
-  // virtual for testing.
-  virtual service_manager::Identity GetClientIdentityForCurrentRequest() const;
-  // virtual for testing.
-  virtual base::ProcessId GetProcessIdForClientIdentity(
-      service_manager::Identity identity) const;
-  // virtual for testing.
-  virtual std::map<base::ProcessId, std::vector<std::string>>
-  ComputePidToServiceNamesMap() const;
-  ~CoordinatorImpl() override;
 
  private:
   using OSMemDumpMap = base::flat_map<base::ProcessId, mojom::RawOSMemDumpPtr>;
   using RequestGlobalMemoryDumpInternalCallback =
       base::OnceCallback<void(bool, uint64_t, mojom::GlobalMemoryDumpPtr)>;
-  friend std::default_delete<CoordinatorImpl>;  // For testing
   friend class CoordinatorImplTest;             // For testing
 
-  // Holds the identity and remote reference of registered clients.
+  // Holds metadata and a client pipe connected to every client process.
   struct ClientInfo {
-    ClientInfo(const service_manager::Identity&,
-               mojom::ClientProcessPtr,
-               mojom::ProcessType);
+    ClientInfo(mojo::Remote<mojom::ClientProcess> client,
+               mojom::ProcessType,
+               base::Optional<std::string> service_name);
     ~ClientInfo();
 
-    const service_manager::Identity identity;
-    const mojom::ClientProcessPtr client;
+    const mojo::Remote<mojom::ClientProcess> client;
     const mojom::ProcessType process_type;
+    const base::Optional<std::string> service_name;
   };
 
+  void UnregisterClientProcess(base::ProcessId);
+
   void RequestGlobalMemoryDumpInternal(
       const QueuedRequest::Args& args,
       RequestGlobalMemoryDumpInternalCallback callback);
 
   // Callback of RequestChromeMemoryDump.
   void OnChromeMemoryDumpResponse(
-      mojom::ClientProcess*,
+      base::ProcessId process_id,
       bool success,
       uint64_t dump_guid,
       std::unique_ptr<base::trace_event::ProcessMemoryDump> chrome_memory_dump);
 
   // Callback of RequestOSMemoryDump.
   void OnOSMemoryDumpResponse(uint64_t dump_guid,
-                              mojom::ClientProcess*,
+                              base::ProcessId process_id,
                               bool success,
                               OSMemDumpMap);
 
   // Callback of RequestOSMemoryDumpForVmRegions.
   void OnOSMemoryDumpForVMRegions(uint64_t dump_guid,
-                                  mojom::ClientProcess* client,
+                                  base::ProcessId process_id,
                                   bool success,
                                   OSMemDumpMap);
 
@@ -142,7 +129,7 @@
       uint64_t dump_guid,
       std::vector<mojom::HeapProfileResultPtr> heap_profile_results);
 
-  void RemovePendingResponse(mojom::ClientProcess*,
+  void RemovePendingResponse(base::ProcessId process_id,
                              QueuedRequest::PendingResponse::Type);
 
   void OnQueuedRequestTimedOut(uint64_t dump_guid);
@@ -157,7 +144,7 @@
   }
 
   // Map of registered client processes.
-  std::map<mojom::ClientProcess*, std::unique_ptr<ClientInfo>> clients_;
+  std::map<base::ProcessId, std::unique_ptr<ClientInfo>> clients_;
 
   // Outstanding dump requests, enqueued via RequestGlobalMemoryDump().
   std::list<QueuedRequest> queued_memory_dump_requests_;
@@ -182,17 +169,12 @@
   std::map<uint64_t, std::unique_ptr<QueuedVmRegionRequest>>
       in_progress_vm_region_requests_;
 
-  // There may be extant callbacks in |queued_memory_dump_requests_|. The
-  // receivers_ must be closed before destroying the un-run callbacks.
-  mojo::ReceiverSet<mojom::Coordinator, service_manager::Identity> receivers_;
+  // Receives control messages from the single privileged client of this object.
+  mojo::Receiver<mojom::CoordinatorController> controller_receiver_{this};
 
-  // There may be extant callbacks in |queued_memory_dump_requests_|. The
-  // bindings_ must be closed before destroying the un-run callbacks.
-  mojo::BindingSet<mojom::HeapProfilerHelper, service_manager::Identity>
-      bindings_heap_profiler_helper_;
-
-  // Maintains a map of service_manager::Identity -> pid for registered clients.
-  std::unique_ptr<ProcessMap> process_map_;
+  // There may be extant callbacks in |queued_memory_dump_requests_|. These
+  // receivers must be closed before destroying the un-run callbacks.
+  mojo::ReceiverSet<mojom::Coordinator, base::ProcessId> coordinator_receivers_;
 
   // Dump IDs are unique across both heap dump and memory dump requests.
   uint64_t next_dump_id_;
@@ -202,10 +184,13 @@
   base::TimeDelta client_process_timeout_;
 
   // When not null, can be queried for heap dumps.
-  mojom::HeapProfilerPtr heap_profiler_;
+  mojo::Remote<mojom::HeapProfiler> heap_profiler_;
+  mojo::Receiver<mojom::HeapProfilerHelper> heap_profiler_helper_receiver_{
+      this};
 
   THREAD_CHECKER(thread_checker_);
   base::WeakPtrFactory<CoordinatorImpl> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(CoordinatorImpl);
 };
 
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
index f24e6d4..09d740e 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
@@ -15,7 +15,6 @@
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/resource_coordinator/memory_instrumentation/process_map.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -62,48 +61,31 @@
 
 class FakeCoordinatorImpl : public CoordinatorImpl {
  public:
-  FakeCoordinatorImpl() : CoordinatorImpl(nullptr) {}
-  ~FakeCoordinatorImpl() override {}
+  FakeCoordinatorImpl() = default;
+  ~FakeCoordinatorImpl() override = default;
 
-  MOCK_CONST_METHOD0(GetClientIdentityForCurrentRequest,
-                     service_manager::Identity());
-  MOCK_CONST_METHOD1(GetProcessIdForClientIdentity,
-                     base::ProcessId(service_manager::Identity));
   MOCK_CONST_METHOD0(ComputePidToServiceNamesMap,
                      std::map<base::ProcessId, std::vector<std::string>>());
 };
 
 class CoordinatorImplTest : public testing::Test {
  public:
-  CoordinatorImplTest() {}
+  CoordinatorImplTest() = default;
+
   void SetUp() override {
     coordinator_.reset(new NiceMock<FakeCoordinatorImpl>);
   }
 
   void TearDown() override { coordinator_.reset(); }
 
-  void RegisterClientProcess(mojom::ClientProcessPtr client_process,
-                             base::ProcessId pid,
-                             mojom::ProcessType process_type) {
-    service_manager::Identity identity(base::NumberToString(pid),
-                                       base::Token{1, 1}, base::Token{},
-                                       base::Token{1, 1});
-
-    ON_CALL(*coordinator_, GetClientIdentityForCurrentRequest())
-        .WillByDefault(Return(identity));
-
-    ON_CALL(*coordinator_, GetProcessIdForClientIdentity(identity))
-        .WillByDefault(Return(pid));
-
-    ON_CALL(*coordinator_, ComputePidToServiceNamesMap())
-        .WillByDefault(
-            Return(std::map<base::ProcessId, std::vector<std::string>>(
-                {{1, {"bootup_helper", "1"}},
-                 {2, {"bootup_helper", "2"}},
-                 {3, {"bootup_helper", "3"}}})));
-
-    coordinator_->RegisterClientProcess(std::move(client_process),
-                                        process_type);
+  void RegisterClientProcess(
+      mojo::PendingReceiver<mojom::Coordinator> receiver,
+      mojo::PendingRemote<mojom::ClientProcess> client_process,
+      mojom::ProcessType process_type,
+      base::ProcessId pid) {
+    coordinator_->RegisterClientProcess(
+        std::move(receiver), std::move(client_process), process_type, pid,
+        /*service_name=*/base::nullopt);
   }
 
   void RequestGlobalMemoryDump(RequestGlobalMemoryDumpCallback callback) {
@@ -163,13 +145,14 @@
 
   MockClientProcess(CoordinatorImplTest* test_coordinator,
                     base::ProcessId pid,
-                    mojom::ProcessType process_type)
-      : binding_(this) {
+                    mojom::ProcessType process_type) {
     // Register to the coordinator.
-    mojom::ClientProcessPtr client_process;
-    binding_.Bind(mojo::MakeRequest(&client_process));
-    test_coordinator->RegisterClientProcess(std::move(client_process), pid,
-                                            process_type);
+    mojo::Remote<mojom::Coordinator> remote_coordinator;
+    mojo::PendingRemote<mojom::ClientProcess> client_process;
+    receiver_.Bind(client_process.InitWithNewPipeAndPassReceiver());
+    test_coordinator->RegisterClientProcess(
+        remote_coordinator.BindNewPipeAndPassReceiver(),
+        std::move(client_process), process_type, pid);
 
     ON_CALL(*this, RequestChromeMemoryDumpMock(_, _))
         .WillByDefault(Invoke([pid](const MemoryDumpRequestArgs& args,
@@ -193,7 +176,7 @@
         }));
   }
 
-  ~MockClientProcess() override {}
+  ~MockClientProcess() override = default;
 
   // TODO(crbug.com/729950): Remove non const reference here once GMock is
   // updated to support move-only types.
@@ -217,7 +200,7 @@
   }
 
  private:
-  mojo::Binding<mojom::ClientProcess> binding_;
+  mojo::Receiver<mojom::ClientProcess> receiver_{this};
 };
 
 class MockGlobalMemoryDumpCallback {
@@ -691,11 +674,6 @@
         mojom::ProcessMemoryDumpPtr browser_dump = nullptr;
         mojom::ProcessMemoryDumpPtr renderer_dump = nullptr;
         for (mojom::ProcessMemoryDumpPtr& dump : global_dump->process_dumps) {
-          // Service names should match what ComputePidToServiceNamesMap
-          // provides.
-          EXPECT_THAT(dump->service_names,
-                      UnorderedElementsAre("bootup_helper",
-                                           base::NumberToString(dump->pid)));
           if (dump->process_type == mojom::ProcessType::BROWSER) {
             browser_dump = std::move(dump);
           } else if (dump->process_type == mojom::ProcessType::RENDERER) {
@@ -948,24 +926,15 @@
       .WillOnce(Invoke([](bool success, GlobalMemoryDump* global_dump) {
         EXPECT_EQ(1U, global_dump->process_dumps.size());
         EXPECT_EQ(global_dump->process_dumps[0]->pid, kBrowserPid);
-        EXPECT_THAT(global_dump->process_dumps[0]->service_names,
-                    UnorderedElementsAre("bootup_helper",
-                                         base::NumberToString(kBrowserPid)));
       }))
       .WillOnce(Invoke([](bool success, GlobalMemoryDump* global_dump) {
         EXPECT_EQ(1U, global_dump->process_dumps.size());
         EXPECT_EQ(global_dump->process_dumps[0]->pid, kRendererPid);
-        EXPECT_THAT(global_dump->process_dumps[0]->service_names,
-                    UnorderedElementsAre("bootup_helper",
-                                         base::NumberToString(kRendererPid)));
       }))
       .WillOnce(
           Invoke([&run_loop](bool success, GlobalMemoryDump* global_dump) {
             EXPECT_EQ(1U, global_dump->process_dumps.size());
             EXPECT_EQ(global_dump->process_dumps[0]->pid, kGpuPid);
-            EXPECT_THAT(global_dump->process_dumps[0]->service_names,
-                        UnorderedElementsAre("bootup_helper",
-                                             base::NumberToString(kGpuPid)));
             run_loop.Quit();
           }));
 
diff --git a/services/resource_coordinator/memory_instrumentation/process_map.cc b/services/resource_coordinator/memory_instrumentation/process_map.cc
deleted file mode 100644
index f6af663..0000000
--- a/services/resource_coordinator/memory_instrumentation/process_map.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/resource_coordinator/memory_instrumentation/process_map.h"
-
-#include "base/process/process_handle.h"
-#include "base/stl_util.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/identity.h"
-#include "services/service_manager/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/mojom/service_manager.mojom.h"
-
-namespace memory_instrumentation {
-
-ProcessMap::ProcessMap(service_manager::Connector* connector) : binding_(this) {
-  if (!connector)
-    return;  // Happens in unittests.
-  service_manager::mojom::ServiceManagerPtr service_manager;
-  connector->BindInterface(service_manager::mojom::kServiceName,
-                           &service_manager);
-  service_manager::mojom::ServiceManagerListenerPtr listener;
-  service_manager::mojom::ServiceManagerListenerRequest request(
-      mojo::MakeRequest(&listener));
-  service_manager->AddListener(std::move(listener));
-  binding_.Bind(std::move(request));
-}
-
-ProcessMap::~ProcessMap() = default;
-
-void ProcessMap::OnInit(std::vector<RunningServiceInfoPtr> instances) {
-  for (const RunningServiceInfoPtr& instance : instances) {
-    if (instance->pid == base::kNullProcessId)
-      continue;
-
-    // This must succeed. Every instance has a globally unique Identity.
-    auto it_and_inserted =
-        instances_.emplace(instance->identity, instance->pid);
-    DCHECK(it_and_inserted.second);
-  }
-}
-
-void ProcessMap::OnServiceCreated(RunningServiceInfoPtr instance) {
-}
-
-void ProcessMap::OnServiceStarted(const service_manager::Identity& identity,
-                                  uint32_t pid) {
-}
-
-void ProcessMap::OnServiceFailedToStart(const service_manager::Identity&) {}
-
-void ProcessMap::OnServiceStopped(const service_manager::Identity& identity) {
-  instances_.erase(identity);
-}
-
-void ProcessMap::OnServicePIDReceived(const service_manager::Identity& identity,
-                                      uint32_t pid) {
-  auto it_and_inserted = instances_.emplace(identity, pid);
-
-  // Either we didn't have the PID before and emplacement succeeded above, or
-  // we already had a valid PID for this Identity from |OnInit()|. In the latter
-  // case, the PID received here must match that one.
-  DCHECK(it_and_inserted.second ||
-         it_and_inserted.first->second == base::ProcessId(pid));
-}
-
-base::ProcessId ProcessMap::GetProcessId(
-    const service_manager::Identity& identity) const {
-  auto it = instances_.find(identity);
-  return it != instances_.end() ? it->second : base::kNullProcessId;
-}
-
-std::map<base::ProcessId, std::vector<std::string>>
-ProcessMap::ComputePidToServiceNamesMap() const {
-  std::map<base::ProcessId, std::vector<std::string>> result;
-  for (const auto& identity_and_pid : instances_) {
-    result[identity_and_pid.second].push_back(identity_and_pid.first.name());
-  }
-  return result;
-}
-
-}  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/memory_instrumentation/process_map.h b/services/resource_coordinator/memory_instrumentation/process_map.h
deleted file mode 100644
index 4e79a43..0000000
--- a/services/resource_coordinator/memory_instrumentation/process_map.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_PROCESS_MAP_H_
-#define SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_PROCESS_MAP_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/process/process_handle.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/identity.h"
-#include "services/service_manager/public/mojom/service_manager.mojom.h"
-
-namespace service_manager {
-class Connector;
-}  // namespace service_manager
-
-namespace memory_instrumentation {
-
-// Maintains a map from service_manager::Identity to base::ProcessId by
-// listening for connections. This allows |pid| lookup by
-// service_manager::Identity. The assumption is that all the processes that will
-// register, via their client libraries, to the memory instrumentation service
-// will also necessarily connect to the service manager.
-class ProcessMap : public service_manager::mojom::ServiceManagerListener {
- public:
-  explicit ProcessMap(service_manager::Connector* connector);
-  ~ProcessMap() override;
-
-  // Returns the pid for a client given its identity.
-  base::ProcessId GetProcessId(const service_manager::Identity&) const;
-
-  // Computes a map of all service names each known PID is associated with. Note
-  // that this walks over all of |instances_|, so it should not be needlessly
-  // called repeatedly.
-  std::map<base::ProcessId, std::vector<std::string>>
-  ComputePidToServiceNamesMap() const;
-
- protected:
- private:
-  FRIEND_TEST_ALL_PREFIXES(ProcessMapTest, TypicalCase);
-  FRIEND_TEST_ALL_PREFIXES(ProcessMapTest, PresentInInit);
-  FRIEND_TEST_ALL_PREFIXES(ProcessMapTest, NullsInInitIgnored);
-
-  using Identity = service_manager::Identity;
-  using RunningServiceInfoPtr = service_manager::mojom::RunningServiceInfoPtr;
-
-  // Overridden from service_manager::mojom::ServiceManagerListener.
-  void OnInit(std::vector<RunningServiceInfoPtr> instances) override;
-  void OnServiceCreated(RunningServiceInfoPtr instance) override;
-  void OnServiceStarted(const Identity&, uint32_t pid) override;
-  void OnServiceFailedToStart(const Identity&) override;
-  void OnServiceStopped(const Identity&) override;
-  void OnServicePIDReceived(const service_manager::Identity& identity,
-                            uint32_t pid) override;
-
-  mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
-  std::map<Identity, base::ProcessId> instances_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProcessMap);
-};
-
-}  // namespace memory_instrumentation
-#endif  // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_PROCESS_MAP_H_
diff --git a/services/resource_coordinator/memory_instrumentation/process_map_unittest.cc b/services/resource_coordinator/memory_instrumentation/process_map_unittest.cc
deleted file mode 100644
index 1d9d743b..0000000
--- a/services/resource_coordinator/memory_instrumentation/process_map_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <utility>
-
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "services/resource_coordinator/memory_instrumentation/process_map.h"
-#include "services/service_manager/public/cpp/identity.h"
-#include "services/service_manager/public/mojom/service_manager.mojom.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace memory_instrumentation {
-
-using RunningServiceInfoPtr = service_manager::mojom::RunningServiceInfoPtr;
-using ServiceManagerListenerRequest =
-    service_manager::mojom::ServiceManagerListenerRequest;
-using testing::ElementsAre;
-
-service_manager::Identity MakeFakeId(const std::string& service_name) {
-  // The details of this Identity don't really matter. Name is used for test
-  // expectations, and in general the last token should be unique, hence the
-  // randomization.
-  return service_manager::Identity{service_name, base::Token{1, 1},
-                                   base::Token{}, base::Token::CreateRandom()};
-}
-
-RunningServiceInfoPtr MakeTestServiceInfo(
-    const service_manager::Identity& identity,
-    uint32_t pid) {
-  RunningServiceInfoPtr info(service_manager::mojom::RunningServiceInfo::New());
-  info->identity = identity;
-  info->pid = pid;
-  return info;
-}
-
-TEST(ProcessMapTest, PresentInInit) {
-  // Add a dummy entry so that the actual |ids| indexes are 1-based.
-  std::vector<service_manager::Identity> ids{MakeFakeId("id0")};
-  std::vector<RunningServiceInfoPtr> instances;
-  ProcessMap process_map(nullptr);
-  for (uint32_t i = 1; i <= 3; i++) {
-    ids.push_back(MakeFakeId(base::StringPrintf("id%d", i)));
-    instances.push_back(MakeTestServiceInfo(ids.back(), i /* pid */));
-  }
-  process_map.OnInit(std::move(instances));
-  EXPECT_EQ(static_cast<base::ProcessId>(1), process_map.GetProcessId(ids[1]));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(ids[2]));
-  EXPECT_EQ(static_cast<base::ProcessId>(3), process_map.GetProcessId(ids[3]));
-
-  process_map.OnServiceStopped(ids[1]);
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(ids[1]));
-  EXPECT_EQ(static_cast<base::ProcessId>(3), process_map.GetProcessId(ids[3]));
-}
-
-TEST(ProcessMapTest, NullsInInitIgnored) {
-  ProcessMap process_map(nullptr);
-  service_manager::Identity id1 = MakeFakeId("id1");
-  service_manager::Identity id2 = MakeFakeId("id2");
-
-  std::vector<RunningServiceInfoPtr> instances;
-  instances.push_back(MakeTestServiceInfo(id1, base::kNullProcessId));
-  instances.push_back(MakeTestServiceInfo(id2, 2));
-
-  process_map.OnInit(std::move(instances));
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id1));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id2));
-
-  process_map.OnServicePIDReceived(id1, 1 /* pid */);
-  EXPECT_EQ(static_cast<base::ProcessId>(1), process_map.GetProcessId(id1));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id2));
-}
-
-TEST(ProcessMapTest, TypicalCase) {
-  ProcessMap process_map(nullptr);
-  service_manager::Identity id1 = MakeFakeId("id1");
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id1));
-  process_map.OnInit(std::vector<RunningServiceInfoPtr>());
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id1));
-
-  process_map.OnServiceCreated(MakeTestServiceInfo(id1, 1 /* pid */));
-  process_map.OnServiceStarted(id1, 1 /* pid */);
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id1));
-
-  process_map.OnServicePIDReceived(id1, 1 /* pid */);
-  EXPECT_EQ(static_cast<base::ProcessId>(1), process_map.GetProcessId(id1));
-
-  // Adding a separate service with a different identity should have no effect
-  // on the first identity registered.
-  service_manager::Identity id2 = MakeFakeId("id2");
-  process_map.OnServiceCreated(MakeTestServiceInfo(id2, 2 /* pid */));
-  process_map.OnServicePIDReceived(id2, 2 /* pid */);
-  EXPECT_EQ(static_cast<base::ProcessId>(1), process_map.GetProcessId(id1));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id2));
-  std::map<base::ProcessId, std::vector<std::string>> pid_to_names =
-      process_map.ComputePidToServiceNamesMap();
-  EXPECT_EQ(2u, pid_to_names.size());
-  EXPECT_THAT(pid_to_names[static_cast<base::ProcessId>(1)],
-              ElementsAre("id1"));
-  EXPECT_THAT(pid_to_names[static_cast<base::ProcessId>(2)],
-              ElementsAre("id2"));
-
-  // Once the service is stopped, searching for its id should return a null pid.
-  process_map.OnServiceStopped(id1);
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id1));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id2));
-
-  // Unknown identities return a null pid.
-  service_manager::Identity id3 = MakeFakeId("id3");
-  EXPECT_EQ(base::kNullProcessId, process_map.GetProcessId(id3));
-
-  // Can have multiple identities under same pid.
-  service_manager::Identity id4 = MakeFakeId("id4");
-  process_map.OnServiceCreated(MakeTestServiceInfo(id4, 2 /* pid */));
-  process_map.OnServicePIDReceived(id4, 2 /* pid */);
-
-  // Can get the pid for both, and the computed service map should have both.
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id2));
-  EXPECT_EQ(static_cast<base::ProcessId>(2), process_map.GetProcessId(id4));
-
-  std::map<base::ProcessId, std::vector<std::string>> pid_to_names2 =
-      process_map.ComputePidToServiceNamesMap();
-  EXPECT_EQ(1u, pid_to_names2.size());
-  EXPECT_THAT(pid_to_names2[static_cast<base::ProcessId>(2)],
-              ElementsAre("id2", "id4"));
-}
-
-}  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request.cc b/services/resource_coordinator/memory_instrumentation/queued_request.cc
index c27a835..40e97d44 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request.cc
+++ b/services/resource_coordinator/memory_instrumentation/queued_request.cc
@@ -21,14 +21,13 @@
 QueuedRequest::Args::Args(const Args& args) = default;
 QueuedRequest::Args::~Args() = default;
 
-QueuedRequest::PendingResponse::PendingResponse(
-    const mojom::ClientProcess* client,
-    Type type)
-    : client(client), type(type) {}
+QueuedRequest::PendingResponse::PendingResponse(base::ProcessId process_id,
+                                                Type type)
+    : process_id(process_id), type(type) {}
 
 bool QueuedRequest::PendingResponse::operator<(
     const PendingResponse& other) const {
-  return std::tie(client, type) < std::tie(other.client, other.type);
+  return std::tie(process_id, type) < std::tie(other.process_id, other.type);
 }
 
 QueuedRequest::Response::Response() {}
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request.h b/services/resource_coordinator/memory_instrumentation/queued_request.h
index 1da9567d..a0df132 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request.h
+++ b/services/resource_coordinator/memory_instrumentation/queued_request.h
@@ -8,10 +8,11 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <string>
 
 #include "base/containers/flat_map.h"
+#include "base/optional.h"
 #include "base/trace_event/memory_dump_request_args.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 
 using base::trace_event::MemoryDumpLevelOfDetail;
@@ -54,11 +55,11 @@
       kChromeDump,
       kOSDump,
     };
-    PendingResponse(const mojom::ClientProcess* client, const Type type);
+    PendingResponse(base::ProcessId, const Type type);
 
     bool operator<(const PendingResponse& other) const;
 
-    const mojom::ClientProcess* client;
+    const base::ProcessId process_id;
     const Type type;
   };
 
@@ -69,7 +70,7 @@
 
     base::ProcessId process_id = base::kNullProcessId;
     mojom::ProcessType process_type = mojom::ProcessType::OTHER;
-    std::vector<std::string> service_names;
+    base::Optional<std::string> service_name;
     std::unique_ptr<base::trace_event::ProcessMemoryDump> chrome_dump;
     OSMemDumpMap os_dumps;
   };
@@ -101,7 +102,7 @@
   // |RequestOSMemoryDump| call that has not yet replied or been canceled (due
   // to the client disconnecting).
   std::set<PendingResponse> pending_responses;
-  std::map<mojom::ClientProcess*, Response> responses;
+  std::map<base::ProcessId, Response> responses;
   int failed_memory_dump_count = 0;
   bool dump_in_progress = false;
 
@@ -129,10 +130,11 @@
 
     base::ProcessId process_id = base::kNullProcessId;
     OSMemDumpMap os_dumps;
+    base::Optional<std::string> service_name;
   };
 
-  std::set<mojom::ClientProcess*> pending_responses;
-  std::map<mojom::ClientProcess*, Response> responses;
+  std::set<base::ProcessId> pending_responses;
+  std::map<base::ProcessId, Response> responses;
 };
 
 }  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
index 044ffda0..cd963db1 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
+++ b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
@@ -221,9 +221,9 @@
       continue;
     }
 
-    request->responses[client].process_id = client_info.pid;
-    request->responses[client].process_type = client_info.process_type;
-    request->responses[client].service_names = client_info.service_names;
+    request->responses[client_info.pid].process_id = client_info.pid;
+    request->responses[client_info.pid].process_type = client_info.process_type;
+    request->responses[client_info.pid].service_name = client_info.service_name;
 
     // Don't request a chrome memory dump at all if the client only wants the
     // a memory footprint.
@@ -234,19 +234,20 @@
     // https://bugs.chromium.org/p/chromium/issues/detail?id=812346#c16 for more
     // details.
     if (!request->args.memory_footprint_only) {
-      request->pending_responses.insert({client, ResponseType::kChromeDump});
+      request->pending_responses.insert(
+          {client_info.pid, ResponseType::kChromeDump});
       client->RequestChromeMemoryDump(
           request->GetRequestArgs(),
-          base::BindOnce(std::move(chrome_callback), client));
+          base::BindOnce(std::move(chrome_callback), client_info.pid));
     }
 
 // On most platforms each process can dump data about their own process
 // so ask each process to do so Linux is special see below.
 #if !defined(OS_LINUX)
-    request->pending_responses.insert({client, ResponseType::kOSDump});
+    request->pending_responses.insert({client_info.pid, ResponseType::kOSDump});
     client->RequestOSMemoryDump(request->memory_map_option(),
                                 {base::kNullProcessId},
-                                base::BindOnce(os_callback, client));
+                                base::BindOnce(os_callback, client_info.pid));
 #endif  // !defined(OS_LINUX)
 
     // If we are in the single pid case, then we've already found the only
@@ -260,6 +261,7 @@
 #if defined(OS_LINUX)
   std::vector<base::ProcessId> pids;
   mojom::ClientProcess* browser_client = nullptr;
+  base::ProcessId browser_client_pid = base::kNullProcessId;
   pids.reserve(request->args.pid == base::kNullProcessId ? clients.size() : 1);
   for (const auto& client_info : clients) {
     if (request->args.pid == base::kNullProcessId ||
@@ -268,14 +270,16 @@
     }
     if (client_info.process_type == mojom::ProcessType::BROWSER) {
       browser_client = client_info.client;
+      browser_client_pid = client_info.pid;
     }
   }
   if (clients.size() > 0) {
     DCHECK(browser_client);
   }
   if (browser_client && pids.size() > 0) {
-    request->pending_responses.insert({browser_client, ResponseType::kOSDump});
-    auto callback = base::BindOnce(os_callback, browser_client);
+    request->pending_responses.insert(
+        {browser_client_pid, ResponseType::kOSDump});
+    auto callback = base::BindOnce(os_callback, browser_client_pid);
     browser_client->RequestOSMemoryDump(request->memory_map_option(), pids,
                                         std::move(callback));
   }
@@ -314,9 +318,9 @@
     return;
   }
 
-  request->pending_responses.insert(browser_client);
-  request->responses[browser_client].process_id = browser_client_pid;
-  auto callback = base::BindOnce(os_callback, browser_client);
+  request->pending_responses.insert(browser_client_pid);
+  request->responses[browser_client_pid].process_id = browser_client_pid;
+  auto callback = base::BindOnce(os_callback, browser_client_pid);
   browser_client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
                                       desired_pids, std::move(callback));
 #else
@@ -324,11 +328,13 @@
     if (std::find(desired_pids.begin(), desired_pids.end(), client_info.pid) !=
         desired_pids.end()) {
       mojom::ClientProcess* client = client_info.client;
-      request->pending_responses.insert(client);
-      request->responses[client].process_id = client_info.pid;
+      request->pending_responses.insert(client_info.pid);
+      request->responses[client_info.pid].process_id = client_info.pid;
+      request->responses[client_info.pid].service_name =
+          client_info.service_name;
       client->RequestOSMemoryDump(mojom::MemoryMapOption::MODULES,
                                   {base::kNullProcessId},
-                                  base::BindOnce(os_callback, client));
+                                  base::BindOnce(os_callback, client_info.pid));
     }
   }
 #endif  // defined(OS_LINUX)
@@ -388,7 +394,6 @@
   // All the pointers in the maps will continue to be owned by |request|
   // which outlives these containers.
   std::map<base::ProcessId, mojom::ProcessType> pid_to_process_type;
-  std::map<base::ProcessId, std::vector<std::string>> pid_to_service_names;
   std::map<base::ProcessId, const base::trace_event::ProcessMemoryDump*>
       pid_to_pmd;
   std::map<base::ProcessId, mojom::RawOSMemDump*> pid_to_os_dump;
@@ -396,12 +401,6 @@
     const base::ProcessId& original_pid = response.second.process_id;
     pid_to_process_type[original_pid] = response.second.process_type;
 
-    std::vector<std::string>& service_names_for_pid =
-        pid_to_service_names[original_pid];
-    service_names_for_pid.insert(service_names_for_pid.begin(),
-                                 response.second.service_names.begin(),
-                                 response.second.service_names.end());
-
     // |chrome_dump| can be nullptr if this was a OS-counters only response.
     pid_to_pmd[original_pid] = response.second.chrome_dump.get();
 
@@ -534,8 +533,8 @@
     mojom::ProcessMemoryDumpPtr pmd = mojom::ProcessMemoryDump::New();
     pmd->pid = pid;
     pmd->process_type = pid_to_process_type[pid];
-    pmd->service_names = pid_to_service_names[pid];
     pmd->os_dump = std::move(os_dump);
+    pmd->service_name = response.second.service_name;
 
     // If we have to return a summary, add all entries for the requested
     // allocator dumps.
@@ -623,12 +622,14 @@
     mojom::ClientProcess* client,
     base::ProcessId pid,
     mojom::ProcessType process_type,
-    std::vector<std::string> service_names)
+    base::Optional<std::string> service_name)
     : client(client),
       pid(pid),
       process_type(process_type),
-      service_names(std::move(service_names)) {}
+      service_name(std::move(service_name)) {}
+
 QueuedRequestDispatcher::ClientInfo::ClientInfo(ClientInfo&& other) = default;
-QueuedRequestDispatcher::ClientInfo::~ClientInfo() {}
+
+QueuedRequestDispatcher::ClientInfo::~ClientInfo() = default;
 
 }  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
index d38309f..16254ae1 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
+++ b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/containers/flat_map.h"
+#include "base/optional.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "services/resource_coordinator/memory_instrumentation/coordinator_impl.h"
 #include "services/resource_coordinator/memory_instrumentation/graph.h"
@@ -26,12 +27,12 @@
   using RequestGlobalMemoryDumpInternalCallback = base::OnceCallback<
       void(bool, uint64_t, memory_instrumentation::mojom::GlobalMemoryDumpPtr)>;
   using ChromeCallback = base::RepeatingCallback<void(
-      mojom::ClientProcess*,
+      base::ProcessId,
       bool,
       uint64_t,
       std::unique_ptr<base::trace_event::ProcessMemoryDump>)>;
   using OsCallback =
-      base::RepeatingCallback<void(mojom::ClientProcess*, bool, OSMemDumpMap)>;
+      base::RepeatingCallback<void(base::ProcessId, bool, OSMemDumpMap)>;
   using VmRegions =
       base::flat_map<base::ProcessId,
                      std::vector<memory_instrumentation::mojom::VmRegionPtr>>;
@@ -40,14 +41,14 @@
     ClientInfo(mojom::ClientProcess* client,
                base::ProcessId pid,
                mojom::ProcessType process_type,
-               std::vector<std::string> service_names);
+               base::Optional<std::string> service_name);
     ClientInfo(ClientInfo&& other);
     ~ClientInfo();
 
-    mojom::ClientProcess* client;
+    mojom::ClientProcess* const client;
     const base::ProcessId pid;
     const mojom::ProcessType process_type;
-    std::vector<std::string> service_names;
+    const base::Optional<std::string> service_name;
   };
 
   // Sets up the parameters of the queued |request| using |clients| and then
diff --git a/services/resource_coordinator/public/cpp/BUILD.gn b/services/resource_coordinator/public/cpp/BUILD.gn
index a0ce7be..b4577df 100644
--- a/services/resource_coordinator/public/cpp/BUILD.gn
+++ b/services/resource_coordinator/public/cpp/BUILD.gn
@@ -9,21 +9,5 @@
     "//mojo/public/cpp/bindings",
     "//services/resource_coordinator/public/cpp/memory_instrumentation",
     "//services/resource_coordinator/public/mojom",
-    "//services/service_manager/public/cpp",
-  ]
-}
-
-source_set("manifest") {
-  sources = [
-    "manifest.cc",
-    "manifest.h",
-  ]
-
-  deps = [
-    "//base",
-    "//services/metrics/public/mojom",
-    "//services/resource_coordinator/public/mojom",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/mojom",
   ]
 }
diff --git a/services/resource_coordinator/public/cpp/OWNERS b/services/resource_coordinator/public/cpp/OWNERS
index 5e4bf1e..a605b825 100644
--- a/services/resource_coordinator/public/cpp/OWNERS
+++ b/services/resource_coordinator/public/cpp/OWNERS
@@ -5,7 +5,3 @@
 
 per-file *_mojom_traits*.*=set noparent
 per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/services/resource_coordinator/public/cpp/manifest.cc b/services/resource_coordinator/public/cpp/manifest.cc
deleted file mode 100644
index 073bd38..0000000
--- a/services/resource_coordinator/public/cpp/manifest.cc
+++ /dev/null
@@ -1,44 +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 "services/resource_coordinator/public/cpp/manifest.h"
-
-#include <set>
-
-#include "base/no_destructor.h"
-#include "services/metrics/public/mojom/constants.mojom.h"
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
-#include "services/service_manager/public/cpp/manifest_builder.h"
-#include "services/service_manager/public/mojom/constants.mojom.h"
-
-namespace resource_coordinator {
-
-const service_manager::Manifest& GetManifest() {
-  static base::NoDestructor<service_manager::Manifest> manifest{
-      service_manager::ManifestBuilder()
-          .WithServiceName(mojom::kServiceName)
-          .WithDisplayName("Global Resource Coordinator")
-          .WithOptions(service_manager::ManifestOptionsBuilder()
-                           .WithInstanceSharingPolicy(
-                               service_manager::Manifest::
-                                   InstanceSharingPolicy::kSharedAcrossGroups)
-                           .Build())
-          .ExposeCapability("app",
-                            service_manager::Manifest::InterfaceList<
-                                memory_instrumentation::mojom::Coordinator>())
-          .ExposeCapability(
-              "heap_profiler_helper",
-              service_manager::Manifest::InterfaceList<
-                  memory_instrumentation::mojom::HeapProfilerHelper>())
-          .ExposeCapability("tests", std::set<const char*>{"*"})
-          .RequireCapability(metrics::mojom::kMetricsServiceName,
-                             "url_keyed_metrics")
-          .RequireCapability(service_manager::mojom::kServiceName,
-                             "service_manager:service_manager")
-          .Build()};
-  return *manifest;
-}
-
-}  // namespace resource_coordinator
diff --git a/services/resource_coordinator/public/cpp/manifest.h b/services/resource_coordinator/public/cpp/manifest.h
deleted file mode 100644
index fdf1346..0000000
--- a/services/resource_coordinator/public/cpp/manifest.h
+++ /dev/null
@@ -1,16 +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 SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MANIFEST_H_
-#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MANIFEST_H_
-
-#include "services/service_manager/public/cpp/manifest.h"
-
-namespace resource_coordinator {
-
-const service_manager::Manifest& GetManifest();
-
-}  // namespace resource_coordinator
-
-#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MANIFEST_H_
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn b/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
index 813ea0e..7775874 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/BUILD.gn
@@ -6,7 +6,6 @@
   sources = [
     "client_process_impl.cc",
     "client_process_impl.h",
-    "coordinator.h",
     "global_memory_dump.cc",
     "global_memory_dump.h",
     "memory_instrumentation.cc",
@@ -42,7 +41,6 @@
     "//base",
     "//mojo/public/cpp/bindings",
     "//services/resource_coordinator/public/mojom",
-    "//services/service_manager/public/cpp",
   ]
 }
 
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
index 440ae0b..0d9ca71 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
@@ -13,43 +13,39 @@
 #include "base/trace_event/memory_dump_request_args.h"
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/bind_source_info.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace memory_instrumentation {
 
 // static
-void ClientProcessImpl::CreateInstance(const Config& config) {
+void ClientProcessImpl::CreateInstance(
+    mojo::PendingReceiver<mojom::ClientProcess> receiver,
+    mojo::PendingRemote<mojom::Coordinator> coordinator,
+    bool is_browser_process) {
   static ClientProcessImpl* instance = nullptr;
   if (!instance) {
-    instance = new ClientProcessImpl(config);
+    instance = new ClientProcessImpl(
+        std::move(receiver), std::move(coordinator), is_browser_process,
+        /*initialize_memory_instrumentation=*/true);
   } else {
     NOTREACHED();
   }
 }
 
-ClientProcessImpl::ClientProcessImpl(const Config& config)
-    : binding_(this), process_type_(config.process_type), task_runner_() {
-  // |config.connector| can be null in tests.
-  if (config.connector) {
-    config.connector->BindInterface(config.service_name,
-                                    mojo::MakeRequest(&coordinator_));
-    mojom::ClientProcessPtr process;
-    binding_.Bind(mojo::MakeRequest(&process));
-    coordinator_->RegisterClientProcess(std::move(process),
-                                        config.process_type);
-
+ClientProcessImpl::ClientProcessImpl(
+    mojo::PendingReceiver<mojom::ClientProcess> receiver,
+    mojo::PendingRemote<mojom::Coordinator> coordinator,
+    bool is_browser_process,
+    bool initialize_memory_instrumentation)
+    : receiver_(this, std::move(receiver)) {
+  if (initialize_memory_instrumentation) {
     // Initialize the public-facing MemoryInstrumentation helper.
-    MemoryInstrumentation::CreateInstance(config.connector,
-                                          config.service_name);
+    MemoryInstrumentation::CreateInstance(std::move(coordinator));
   } else {
-    config.coordinator_for_testing->BindCoordinatorReceiver(
-        mojo::MakeRequest(&coordinator_), service_manager::BindSourceInfo());
+    coordinator_.Bind(std::move(coordinator));
   }
 
   task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -58,20 +54,18 @@
   // base::MemoryDumpManager that it is special and should coordinate periodic
   // dumps for tracing. Remove this once the periodic dump scheduler is moved
   // from base to the service. MDM should not care about being the coordinator.
-  bool is_coordinator_process =
-      config.process_type == mojom::ProcessType::BROWSER;
   base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
       base::BindRepeating(
           &ClientProcessImpl::RequestGlobalMemoryDump_NoCallback,
           base::Unretained(this)),
-      is_coordinator_process);
+      is_browser_process);
 
   tracing_observer_ = std::make_unique<TracingObserver>(
       base::trace_event::TraceLog::GetInstance(),
       base::trace_event::MemoryDumpManager::GetInstance());
 }
 
-ClientProcessImpl::~ClientProcessImpl() {}
+ClientProcessImpl::~ClientProcessImpl() = default;
 
 void ClientProcessImpl::RequestChromeMemoryDump(
     const base::trace_event::MemoryDumpRequestArgs& args,
@@ -124,7 +118,15 @@
     return;
   }
 
-  coordinator_->RequestGlobalMemoryDumpAndAppendToTrace(
+  // NOTE: If this ClientProcessImpl was responsible for initializing the
+  // global MemoryInstrumentation object, its Coordinator pipe was passed along
+  // to that object, and |coordinator_| is unbound.
+  mojom::Coordinator* coordinator = nullptr;
+  if (coordinator_)
+    coordinator = coordinator_.get();
+  else
+    coordinator = MemoryInstrumentation::GetInstance()->GetCoordinator();
+  coordinator->RequestGlobalMemoryDumpAndAppendToTrace(
       dump_type, level_of_detail,
       mojom::Coordinator::RequestGlobalMemoryDumpAndAppendToTraceCallback());
 }
@@ -171,15 +173,6 @@
   std::move(args.callback).Run(global_success, std::move(results));
 }
 
-ClientProcessImpl::Config::Config(service_manager::Connector* connector,
-                                  const std::string& service_name,
-                                  mojom::ProcessType process_type)
-    : connector(connector),
-      service_name(service_name),
-      process_type(process_type) {}
-
-ClientProcessImpl::Config::~Config() {}
-
 ClientProcessImpl::OSMemoryDumpArgs::OSMemoryDumpArgs() = default;
 ClientProcessImpl::OSMemoryDumpArgs::OSMemoryDumpArgs(OSMemoryDumpArgs&&) =
     default;
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
index d672811..dcf1c9c8 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
@@ -11,10 +11,11 @@
 #include "base/synchronization/lock.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_request_args.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 namespace memory_instrumentation {
 
@@ -31,27 +32,19 @@
 class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
     ClientProcessImpl : public mojom::ClientProcess {
  public:
-  struct COMPONENT_EXPORT(
-      RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) Config {
-   public:
-    Config(service_manager::Connector* connector,
-           const std::string& service_name,
-           mojom::ProcessType process_type);
-    ~Config();
-
-    service_manager::Connector* const connector;
-    Coordinator* coordinator_for_testing;
-    const std::string service_name;
-    const mojom::ProcessType process_type;
-  };
-
-  static void CreateInstance(const Config& config);
+  static void CreateInstance(
+      mojo::PendingReceiver<mojom::ClientProcess> receiver,
+      mojo::PendingRemote<mojom::Coordinator> coordinator,
+      bool is_browser_process = false);
 
  private:
   friend std::default_delete<ClientProcessImpl>;  // For testing
   friend class MemoryTracingIntegrationTest;
 
-  ClientProcessImpl(const Config& config);
+  ClientProcessImpl(mojo::PendingReceiver<mojom::ClientProcess> receiver,
+                    mojo::PendingRemote<mojom::Coordinator> coordinator,
+                    bool is_browser_process,
+                    bool initialize_memory_instrumentation);
   ~ClientProcessImpl() override;
 
   // Implements base::trace_event::MemoryDumpManager::RequestGlobalDumpCallback.
@@ -99,9 +92,8 @@
       delayed_os_memory_dump_callbacks_;
   base::Optional<uint64_t> most_recent_chrome_memory_dump_guid_;
 
-  mojom::CoordinatorPtr coordinator_;
-  mojo::Binding<mojom::ClientProcess> binding_;
-  const mojom::ProcessType process_type_;
+  mojo::Receiver<mojom::ClientProcess> receiver_;
+  mojo::Remote<mojom::Coordinator> coordinator_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
   // TODO(ssid): This should be moved to coordinator instead of clients once we
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h b/services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h
deleted file mode 100644
index f27d245..0000000
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_COORDINATOR_H_
-#define SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_COORDINATOR_H_
-
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-
-namespace service_manager {
-struct BindSourceInfo;
-}
-
-namespace memory_instrumentation {
-
-class Coordinator {
- public:
-  // Binds a Coordinator Receiver to this Coordinator instance.
-  virtual void BindCoordinatorReceiver(
-      mojo::PendingReceiver<mojom::Coordinator>,
-      const service_manager::BindSourceInfo& source_info) = 0;
-};
-
-}  // namespace memory_instrumentation
-
-#endif  // SERVICES_RESOURCE_COORDINATOR_PUBLIC_CPP_MEMORY_INSTRUMENTATION_COORDINATOR_H_
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
index e7d7b44..de5067b2 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
@@ -35,8 +35,8 @@
 
     base::ProcessId pid() const { return raw_dump_->pid; }
     mojom::ProcessType process_type() const { return raw_dump_->process_type; }
-    const std::vector<std::string>& service_names() const {
-      return raw_dump_->service_names;
+    const base::Optional<std::string>& service_name() const {
+      return raw_dump_->service_name;
     }
 
     const mojom::OSMemDump& os_dump() const { return *raw_dump_->os_dump; }
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
index bab3e0ef..ea896a00 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
@@ -5,11 +5,10 @@
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 
 #include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
 
 namespace memory_instrumentation {
 namespace {
+
 MemoryInstrumentation* g_instance = nullptr;
 
 void WrapGlobalMemoryDump(
@@ -22,10 +21,10 @@
 
 // static
 void MemoryInstrumentation::CreateInstance(
-    service_manager::Connector* connector,
-    const std::string& service_name) {
+    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
+        coordinator) {
   DCHECK(!g_instance);
-  g_instance = new MemoryInstrumentation(connector, service_name);
+  g_instance = new MemoryInstrumentation(std::move(coordinator));
 }
 
 // static
@@ -34,13 +33,8 @@
 }
 
 MemoryInstrumentation::MemoryInstrumentation(
-    service_manager::Connector* connector,
-    const std::string& service_name)
-    : connector_(connector),
-      connector_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      service_name_(service_name) {
-  DCHECK(connector_task_runner_);
-}
+    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator)
+    : coordinator_(std::move(coordinator)) {}
 
 MemoryInstrumentation::~MemoryInstrumentation() {
   g_instance = nullptr;
@@ -49,8 +43,7 @@
 void MemoryInstrumentation::RequestGlobalDump(
     const std::vector<std::string>& allocator_dump_names,
     RequestGlobalDumpCallback callback) {
-  const auto& coordinator = GetCoordinatorBindingForCurrentSequence();
-  coordinator->RequestGlobalMemoryDump(
+  coordinator_->RequestGlobalMemoryDump(
       MemoryDumpType::SUMMARY_ONLY, MemoryDumpLevelOfDetail::BACKGROUND,
       allocator_dump_names,
       base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
@@ -59,8 +52,7 @@
 void MemoryInstrumentation::RequestPrivateMemoryFootprint(
     base::ProcessId pid,
     RequestGlobalDumpCallback callback) {
-  const auto& coordinator = GetCoordinatorBindingForCurrentSequence();
-  coordinator->RequestPrivateMemoryFootprint(
+  coordinator_->RequestPrivateMemoryFootprint(
       pid, base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
 }
 
@@ -68,8 +60,7 @@
     base::ProcessId pid,
     const std::vector<std::string>& allocator_dump_names,
     RequestGlobalDumpCallback callback) {
-  const auto& coordinator = GetCoordinatorBindingForCurrentSequence();
-  coordinator->RequestGlobalMemoryDumpForPid(
+  coordinator_->RequestGlobalMemoryDumpForPid(
       pid, allocator_dump_names,
       base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
 }
@@ -78,33 +69,8 @@
     MemoryDumpType dump_type,
     MemoryDumpLevelOfDetail level_of_detail,
     RequestGlobalMemoryDumpAndAppendToTraceCallback callback) {
-  const auto& coordinator = GetCoordinatorBindingForCurrentSequence();
-  coordinator->RequestGlobalMemoryDumpAndAppendToTrace(
+  coordinator_->RequestGlobalMemoryDumpAndAppendToTrace(
       dump_type, level_of_detail, std::move(callback));
 }
 
-const mojom::CoordinatorPtr&
-MemoryInstrumentation::GetCoordinatorBindingForCurrentSequence() {
-  auto* coordinator = sequence_storage_coordinator_.GetValuePointer();
-  if (!coordinator) {
-    coordinator = sequence_storage_coordinator_.emplace();
-    mojom::CoordinatorRequest coordinator_req = mojo::MakeRequest(coordinator);
-
-    // The connector is not thread safe and BindInterface must be called on its
-    // own thread. Thankfully, the binding can happen _after_ having started
-    // invoking methods on the |coordinator| proxy objects.
-    connector_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &MemoryInstrumentation::BindCoordinatorRequestOnConnectorThread,
-            base::Unretained(this), std::move(coordinator_req)));
-  }
-  return *coordinator;
-}
-
-void MemoryInstrumentation::BindCoordinatorRequestOnConnectorThread(
-    mojom::CoordinatorRequest coordinator_request) {
-  connector_->BindInterface(service_name_, std::move(coordinator_request));
-}
-
 }  // namespace memory_instrumentation
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
index 34e7634..fd429c3 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
@@ -8,16 +8,10 @@
 #include "base/callback_forward.h"
 #include "base/component_export.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/sequence_local_storage_slot.h"
 #include "base/trace_event/memory_dump_request_args.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
+#include "mojo/public/cpp/bindings/shared_remote.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}  // namespace base
 
 namespace memory_instrumentation {
 
@@ -37,10 +31,17 @@
   using RequestGlobalMemoryDumpAndAppendToTraceCallback =
       base::OnceCallback<void(bool success, uint64_t dump_id)>;
 
-  static void CreateInstance(service_manager::Connector*,
-                             const std::string& service_name);
+  static void CreateInstance(
+      mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
+          coordinator);
   static MemoryInstrumentation* GetInstance();
 
+  // Retrieves a Coordinator interface to communicate with the service. This is
+  // safe to call from any thread.
+  memory_instrumentation::mojom::Coordinator* GetCoordinator() const {
+    return coordinator_.get();
+  }
+
   // Requests a global memory dump with |allocator_dump_names| indicating
   // the name of allocator dumps in which the consumer is interested. If
   // |allocator_dump_names| is empty, no dumps will be returned.
@@ -95,18 +96,13 @@
       RequestGlobalMemoryDumpAndAppendToTraceCallback);
 
  private:
-  MemoryInstrumentation(service_manager::Connector* connector,
-                        const std::string& service_name);
+  explicit MemoryInstrumentation(
+      mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
+          coordinator);
   ~MemoryInstrumentation();
 
-  const mojom::CoordinatorPtr& GetCoordinatorBindingForCurrentSequence();
-  void BindCoordinatorRequestOnConnectorThread(mojom::CoordinatorRequest);
-
-  service_manager::Connector* const connector_;
-  scoped_refptr<base::SingleThreadTaskRunner> connector_task_runner_;
-  base::SequenceLocalStorageSlot<mojom::CoordinatorPtr>
-      sequence_storage_coordinator_;
-  const std::string service_name_;
+  const mojo::SharedRemote<memory_instrumentation::mojom::Coordinator>
+      coordinator_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryInstrumentation);
 };
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
index 20ab87c..b210007 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_integration_unittest.cc
@@ -21,8 +21,9 @@
 #include "base/trace_event/trace_config.h"
 #include "base/trace_event/trace_config_memory_test_util.h"
 #include "base/trace_event/trace_log.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/resource_coordinator/public/cpp/memory_instrumentation/coordinator.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -97,21 +98,15 @@
 
 class MemoryTracingIntegrationTest;
 
-class MockCoordinator : public Coordinator, public mojom::Coordinator {
+class MockCoordinator : public mojom::Coordinator {
  public:
-  MockCoordinator(MemoryTracingIntegrationTest* client) : client_(client) {}
+  explicit MockCoordinator(MemoryTracingIntegrationTest* client)
+      : client_(client) {}
 
-  void BindCoordinatorReceiver(
-      mojo::PendingReceiver<mojom::Coordinator> receiver,
-      const service_manager::BindSourceInfo& source_info) override {
+  void BindReceiver(mojo::PendingReceiver<mojom::Coordinator> receiver) {
     receivers_.Add(this, std::move(receiver));
   }
 
-  void RegisterClientProcess(mojom::ClientProcessPtr,
-                             mojom::ProcessType) override {}
-
-  void RegisterHeapProfiler(mojom::HeapProfilerPtr heap_profiler) override {}
-
   void RequestGlobalMemoryDump(
       MemoryDumpType dump_type,
       MemoryDumpLevelOfDetail level_of_detail,
@@ -147,10 +142,15 @@
   void InitializeClientProcess(mojom::ProcessType process_type) {
     mdm_ = MemoryDumpManager::CreateInstanceForTesting();
     mdm_->set_dumper_registrations_ignored_for_testing(true);
-    const char* kServiceName = "TestServiceName";
-    ClientProcessImpl::Config config(nullptr, kServiceName, process_type);
-    config.coordinator_for_testing = coordinator_.get();
-    client_process_.reset(new ClientProcessImpl(config));
+
+    mojo::PendingRemote<mojom::Coordinator> coordinator;
+    mojo::PendingRemote<mojom::ClientProcess> process;
+    auto process_receiver = process.InitWithNewPipeAndPassReceiver();
+    coordinator_->BindReceiver(coordinator.InitWithNewPipeAndPassReceiver());
+    client_process_.reset(new ClientProcessImpl(
+        std::move(process_receiver), std::move(coordinator),
+        process_type == mojom::ProcessType::BROWSER,
+        /*initialize_memory_instrumentation=*/false));
   }
 
   void TearDown() override {
diff --git a/services/resource_coordinator/public/mojom/BUILD.gn b/services/resource_coordinator/public/mojom/BUILD.gn
index 1159b61..17ea149 100644
--- a/services/resource_coordinator/public/mojom/BUILD.gn
+++ b/services/resource_coordinator/public/mojom/BUILD.gn
@@ -13,7 +13,7 @@
     "lifecycle.mojom",
     "memory_instrumentation/constants.mojom",
     "memory_instrumentation/memory_instrumentation.mojom",
-    "service_constants.mojom",
+    "resource_coordinator_service.mojom",
   ]
 
   public_deps = [
diff --git a/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom b/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
index 56704aa..3a3c1b1 100644
--- a/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
+++ b/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
@@ -204,10 +204,8 @@
   // parameter can be removed.
   mojo_base.mojom.ProcessId pid;
 
-  // Shows which services the given process is running, to help separate out
-  // the statistics for a given service.  Clients should look through the entire
-  // list since there may be other entities used internally listed, too.
-  array<string> service_names;
+  // The name of the primary service running in the process, if any.
+  string? service_name;
 };
 
 // Metrics aggregated across all processes.
@@ -296,9 +294,6 @@
 // the whole system. The coordinator maintains a list of registered client
 // processes and polls them whenever a global dump is required.
 interface Coordinator {
-  // Registers a client process.
-  RegisterClientProcess(ClientProcess client_process, ProcessType process_type);
-
   // Broadcasts a dump request to all registered client processes and returns a
   // global dump which includes allocator dumps specified in |allocator_dump_names|.
   // For example, given an allocator dump name such as "malloc" or "cc/resource_memory",
@@ -326,11 +321,30 @@
   RequestGlobalMemoryDumpAndAppendToTrace(DumpType dump_type,
                                           LevelOfDetail level_of_detail) =>
       (bool success, uint64 dump_id);
+};
 
-  // When a heap profiler is registered, heap dumps will be added to the trace
-  // any time RequestGlobalMemoryDumpAndAppendToTrace is called.
-  // This is cleaner than having the memory_instrumentation service talk
-  // directly to the HeapProfiler, since that will spawn the HeapProfiler in a
-  // new process if it isn't already running.
-  RegisterHeapProfiler(HeapProfiler heap_profiler);
+// An interface which can be used by client processes to register themselves
+// with a CoordinatorController client (like the browser), who can then pass the
+// registration along to the service with authoritative information about the
+// process's identity.
+interface CoordinatorConnector {
+  // Registers the calling process. The implementation of this API must already
+  // know who the calling process is and should forward these arguments along to
+  // the CoordinatorController along with information about the process.
+  RegisterCoordinatorClient(pending_receiver<Coordinator> receiver,
+                            pending_remote<ClientProcess> client_process);
+};
+
+// Main interface to the memory instrumentation coordinator. This is considered
+// privileged and the browser should effectively be the only client.
+interface CoordinatorController {
+  // Binds a new Coordinator interface endpoint for a unique client process.
+  // Should be called once for each process, including the browser itself.
+  // |client_process| is an endpoint the service can use to push client events
+  // to the process.
+  RegisterClientProcess(pending_receiver<Coordinator> receiver,
+                        pending_remote<ClientProcess> client_process,
+                        ProcessType process_type,
+                        mojo_base.mojom.ProcessId process_id,
+                        string? service_name);
 };
diff --git a/services/resource_coordinator/public/mojom/resource_coordinator_service.mojom b/services/resource_coordinator/public/mojom/resource_coordinator_service.mojom
new file mode 100644
index 0000000..7cccf8dc
--- /dev/null
+++ b/services/resource_coordinator/public/mojom/resource_coordinator_service.mojom
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module resource_coordinator.mojom;
+
+import "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom";
+
+// The main interface to the Resource Coordinator service. This should be
+// considered a privileged interface and thus only bound by e.g. the browser
+// process.
+interface ResourceCoordinatorService {
+  // Binds the main control interface for memory the instrumentation subsystem.
+  BindMemoryInstrumentationCoordinatorController(
+      pending_receiver<memory_instrumentation.mojom.CoordinatorController>
+          receiver);
+
+  // Registers a remote HeapProfiler implementation for the Resource Coordinator
+  // service to use.
+  RegisterHeapProfiler(
+      pending_remote<memory_instrumentation.mojom.HeapProfiler> profiler,
+      pending_receiver<memory_instrumentation.mojom.HeapProfilerHelper>
+          helper_receiver);
+};
diff --git a/services/resource_coordinator/public/mojom/service_constants.mojom b/services/resource_coordinator/public/mojom/service_constants.mojom
deleted file mode 100644
index 92df94e..0000000
--- a/services/resource_coordinator/public/mojom/service_constants.mojom
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module resource_coordinator.mojom;
-
-const string kServiceName = "resource_coordinator";
diff --git a/services/resource_coordinator/resource_coordinator_service.cc b/services/resource_coordinator/resource_coordinator_service.cc
index 65c456e6..4040cf63 100644
--- a/services/resource_coordinator/resource_coordinator_service.cc
+++ b/services/resource_coordinator/resource_coordinator_service.cc
@@ -15,35 +15,23 @@
 namespace resource_coordinator {
 
 ResourceCoordinatorService::ResourceCoordinatorService(
-    service_manager::mojom::ServiceRequest request)
-    : service_binding_(this, std::move(request)),
-      service_keepalive_(&service_binding_, base::nullopt /* idle_timeout */) {}
+    mojo::PendingReceiver<mojom::ResourceCoordinatorService> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 ResourceCoordinatorService::~ResourceCoordinatorService() = default;
 
-void ResourceCoordinatorService::OnStart() {
-  // TODO(chiniforooshan): The abstract class Coordinator in the
-  // public/cpp/memory_instrumentation directory should not be needed anymore.
-  // We should be able to delete that and rename
-  // memory_instrumentation::CoordinatorImpl to
-  // memory_instrumentation::Coordinator.
-  memory_instrumentation_coordinator_ =
-      std::make_unique<memory_instrumentation::CoordinatorImpl>(
-          service_binding_.GetConnector());
-  registry_.AddInterface(base::BindRepeating(
-      &memory_instrumentation::CoordinatorImpl::BindCoordinatorReceiver,
-      base::Unretained(memory_instrumentation_coordinator_.get())));
-  registry_.AddInterface(base::BindRepeating(
-      &memory_instrumentation::CoordinatorImpl::BindHeapProfilerHelperRequest,
-      base::Unretained(memory_instrumentation_coordinator_.get())));
+void ResourceCoordinatorService::BindMemoryInstrumentationCoordinatorController(
+    mojo::PendingReceiver<memory_instrumentation::mojom::CoordinatorController>
+        receiver) {
+  memory_instrumentation_coordinator_.BindController(std::move(receiver));
 }
 
-void ResourceCoordinatorService::OnBindInterface(
-    const service_manager::BindSourceInfo& source_info,
-    const std::string& interface_name,
-    mojo::ScopedMessagePipeHandle interface_pipe) {
-  registry_.BindInterface(interface_name, std::move(interface_pipe),
-                          source_info);
+void ResourceCoordinatorService::RegisterHeapProfiler(
+    mojo::PendingRemote<memory_instrumentation::mojom::HeapProfiler> profiler,
+    mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfilerHelper>
+        receiver) {
+  memory_instrumentation_coordinator_.RegisterHeapProfiler(std::move(profiler),
+                                                           std::move(receiver));
 }
 
 }  // namespace resource_coordinator
diff --git a/services/resource_coordinator/resource_coordinator_service.h b/services/resource_coordinator/resource_coordinator_service.h
index 3c63ebf..3d2ecd5 100644
--- a/services/resource_coordinator/resource_coordinator_service.h
+++ b/services/resource_coordinator/resource_coordinator_service.h
@@ -5,50 +5,33 @@
 #ifndef SERVICES_RESOURCE_COORDINATOR_RESOURCE_COORDINATOR_SERVICE_H_
 #define SERVICES_RESOURCE_COORDINATOR_RESOURCE_COORDINATOR_SERVICE_H_
 
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
-
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "services/resource_coordinator/memory_instrumentation/coordinator_impl.h"
-
-#include "services/service_manager/public/cpp/binder_registry.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
-#include "services/service_manager/public/cpp/service_keepalive.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
+#include "services/resource_coordinator/public/mojom/resource_coordinator_service.mojom.h"
 
 namespace resource_coordinator {
 
-class ResourceCoordinatorService : public service_manager::Service {
+class ResourceCoordinatorService : public mojom::ResourceCoordinatorService {
  public:
   explicit ResourceCoordinatorService(
-      service_manager::mojom::ServiceRequest request);
+      mojo::PendingReceiver<mojom::ResourceCoordinatorService> receiver);
   ~ResourceCoordinatorService() override;
 
-  // service_manager::Service:
-  void OnStart() override;
-  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
-                       const std::string& interface_name,
-                       mojo::ScopedMessagePipeHandle interface_pipe) override;
+  // mojom::ResourceCoordinatorService implementation:
+  void BindMemoryInstrumentationCoordinatorController(
+      mojo::PendingReceiver<
+          memory_instrumentation::mojom::CoordinatorController> receiver)
+      override;
+  void RegisterHeapProfiler(
+      mojo::PendingRemote<memory_instrumentation::mojom::HeapProfiler> profiler,
+      mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfilerHelper>
+          receiver) override;
 
  private:
-  service_manager::ServiceBinding service_binding_;
-  service_manager::ServiceKeepalive service_keepalive_;
-
-  service_manager::BinderRegistryWithArgs<
-      const service_manager::BindSourceInfo&>
-      registry_;
-  std::unique_ptr<memory_instrumentation::CoordinatorImpl>
-      memory_instrumentation_coordinator_;
-
-  // WeakPtrFactory members should always come last so WeakPtrs are destructed
-  // before other members.
-  base::WeakPtrFactory<ResourceCoordinatorService> weak_factory_{this};
+  const mojo::Receiver<mojom::ResourceCoordinatorService> receiver_;
+  memory_instrumentation::CoordinatorImpl memory_instrumentation_coordinator_;
 
   DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorService);
 };
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 597451d..935057d2 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -920,27 +920,6 @@
             ]
         }
     ],
-    "AutofillOffNoServerData": [
-        {
-            "platforms": [
-                "android",
-                "android_webview",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillOffNoServerData"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillProfileValidation": [
         {
             "platforms": [
@@ -1056,6 +1035,23 @@
             ]
         }
     ],
+    "AutofillSaveCardShowNoThanks": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_20190726",
+                    "enable_features": [
+                        "AutofillSaveCardShowNoThanks"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillSmallFormSupport": [
         {
             "platforms": [
@@ -5183,6 +5179,24 @@
             ]
         }
     ],
+    "SafeBrowsingPasswordProtectionForSignedInUsers": [
+        {
+            "platforms": [
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "SafeBrowsingPasswordProtectionForSignedInUsers"
+                    ]
+                }
+            ]
+        }
+    ],
     "SafeBrowsingScoutTransitionStudy": [
         {
             "platforms": [
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 482acea..027c0c68 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -149,18 +149,10 @@
     "platform/modules/mediastream/web_platform_media_stream_source.h",
     "platform/modules/mediastream/web_platform_media_stream_track.h",
     "platform/modules/mediastream/webrtc_uma_histograms.h",
-    "platform/modules/p2p/empty_network_manager.h",
-    "platform/modules/p2p/ipc_network_manager.h",
-    "platform/modules/p2p/network_list_manager.h",
-    "platform/modules/p2p/network_list_observer.h",
-    "platform/modules/p2p/socket_client.h",
     "platform/modules/peerconnection/audio_codec_factory.h",
     "platform/modules/peerconnection/rtc_event_log_output_sink.h",
     "platform/modules/peerconnection/rtc_event_log_output_sink_proxy_util.h",
-    "platform/modules/peerconnection/rtc_video_decoder_factory_util.h",
-    "platform/modules/peerconnection/rtc_video_encoder_factory_util.h",
     "platform/modules/peerconnection/two_keys_adapter_map.h",
-    "platform/modules/peerconnection/video_codec_factory.h",
     "platform/modules/peerconnection/webrtc_audio_sink.h",
     "platform/modules/peerconnection/webrtc_util.h",
     "platform/modules/peerconnection/webrtc_video_track_source.h",
diff --git a/third_party/blink/public/platform/modules/p2p/DEPS b/third_party/blink/public/platform/modules/p2p/DEPS
deleted file mode 100644
index 66a3374..0000000
--- a/third_party/blink/public/platform/modules/p2p/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-    "+net/base/ip_endpoint.h",
-    "+services/network/public/cpp/p2p_socket_type.h",
-]
diff --git a/third_party/blink/public/platform/modules/p2p/OWNERS b/third_party/blink/public/platform/modules/p2p/OWNERS
deleted file mode 100644
index de19af2..0000000
--- a/third_party/blink/public/platform/modules/p2p/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/blink/renderer/platform/p2p/OWNERS
diff --git a/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h b/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h
deleted file mode 100644
index de64ea4d..0000000
--- a/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h
+++ /dev/null
@@ -1,29 +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_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace webrtc {
-class VideoDecoderFactory;
-}
-
-namespace blink {
-
-// TODO(crbug.com/787254): Remove this API when its clients are Onion souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoderFactory>
-CreateRTCVideoDecoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
diff --git a/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h b/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h
deleted file mode 100644
index 45bafd3f..0000000
--- a/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h
+++ /dev/null
@@ -1,29 +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_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace webrtc {
-class VideoEncoderFactory;
-}
-
-namespace blink {
-
-// TODO(crbug.com/787254): Remove this API when its clients are Onion souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoEncoderFactory>
-CreateRTCVideoEncoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
diff --git a/third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h b/third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h
deleted file mode 100644
index 99a4fbd3..0000000
--- a/third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h
+++ /dev/null
@@ -1,29 +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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
-#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace blink {
-
-// TODO(crbug.com/787254): Remove these APIs when their clients are Onion
-// souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoEncoderFactory>
-CreateWebrtcVideoEncoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories);
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoderFactory>
-CreateWebrtcVideoDecoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 64d1c79..8e11d81b 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -545,11 +545,6 @@
   }
 }
 
-void LocalFrameView::UpdateAcceleratedCompositingSettings() {
-  if (auto* layout_view = GetLayoutView())
-    layout_view->Compositor()->UpdateAcceleratedCompositingSettings();
-}
-
 void LocalFrameView::UpdateCountersAfterStyleChange() {
   auto* layout_view = GetLayoutView();
   DCHECK(layout_view);
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index 3b148f36..a071c23 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -770,8 +770,8 @@
     auto* local_frame = DynamicTo<LocalFrame>(frame);
     if (!local_frame)
       continue;
-    if (LocalFrameView* view = local_frame->View())
-      view->UpdateAcceleratedCompositingSettings();
+    LayoutView* layout_view = local_frame->ContentLayoutObject();
+    layout_view->Compositor()->UpdateAcceleratedCompositingSettings();
   }
 }
 
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index d6173ff..b1740d2 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -618,10 +618,6 @@
     return;
   WillChangeAnimationTarget();
 
-  // Clear values that may depend on the previous target.
-  if (target_element_)
-    DisconnectSyncBaseConditions();
-
   // If the animation state is not Inactive, always reset to a clear state
   // before leaving the old target element.
   if (GetActiveState() != kInactive)
@@ -1089,14 +1085,13 @@
 // this checks if there are any further calculations needed
 // to continue and makes sure the intervals are correct.
 bool SVGSMILElement::NeedsToProgress(SMILTime elapsed) {
-  // Check we're connected to something.
+  // Check we're connected to something and that our conditions have been
+  // "connected".
   DCHECK(time_container_);
+  DCHECK(sync_base_conditions_connected_);
   // Check that we have some form of start or are prepared to find it.
   DCHECK(is_waiting_for_first_interval_ || interval_.IsResolved());
 
-  if (!sync_base_conditions_connected_)
-    ConnectSyncBaseConditions();
-
   // Check if we need updating, otherwise just return.
   if (!interval_.IsResolved()) {
     DCHECK_EQ(GetActiveState(), kInactive);
diff --git a/third_party/blink/renderer/devtools/front_end/Runtime.js b/third_party/blink/renderer/devtools/front_end/Runtime.js
index 3e6552b..b829afe 100644
--- a/third_party/blink/renderer/devtools/front_end/Runtime.js
+++ b/third_party/blink/renderer/devtools/front_end/Runtime.js
@@ -150,6 +150,20 @@
   }
 
   /**
+   * @param {string} scriptName
+   * @param {string=} base
+   * @return {string}
+   */
+  static getResourceURL(scriptName, base) {
+    const sourceURL = (base || self._importScriptPathPrefix) + scriptName;
+    const schemaIndex = sourceURL.indexOf('://') + 3;
+    let pathIndex = sourceURL.indexOf('/', schemaIndex);
+    if (pathIndex === -1)
+      pathIndex = sourceURL.length;
+    return sourceURL.substring(0, pathIndex) + Runtime.normalizePath(sourceURL.substring(pathIndex));
+  }
+
+  /**
    * @param {!Array.<string>} scriptNames
    * @param {string=} base
    * @return {!Promise.<undefined>}
@@ -163,13 +177,7 @@
     let scriptToEval = 0;
     for (let i = 0; i < scriptNames.length; ++i) {
       const scriptName = scriptNames[i];
-      let sourceURL = (base || self._importScriptPathPrefix) + scriptName;
-
-      const schemaIndex = sourceURL.indexOf('://') + 3;
-      let pathIndex = sourceURL.indexOf('/', schemaIndex);
-      if (pathIndex === -1)
-        pathIndex = sourceURL.length;
-      sourceURL = sourceURL.substring(0, pathIndex) + Runtime.normalizePath(sourceURL.substring(pathIndex));
+      const sourceURL = Runtime.getResourceURL(scriptName, base);
 
       if (_loadedScripts[sourceURL])
         continue;
@@ -392,6 +400,14 @@
   }
 
   /**
+   * @param {string} moduleName
+   * @return {!Runtime.Module}
+   */
+  module(moduleName) {
+    return this._modulesMap[moduleName];
+  }
+
+  /**
    * @param {!Runtime.ModuleDescriptor} descriptor
    */
   _registerModule(descriptor) {
@@ -791,6 +807,16 @@
   }
 
   /**
+   * @param {string} resourceName
+   * @return {!Promise.<string>}
+   */
+  fetchResource(resourceName) {
+    const base = this._remoteBase();
+    const sourceURL = Runtime.getResourceURL(this._modularizeURL(resourceName), base);
+    return base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
+  }
+
+  /**
    * @param {string} value
    * @return {string}
    */
diff --git a/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp b/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
index 5d87553..d0b6aca 100644
--- a/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
@@ -99,9 +99,6 @@
   <message name="IDS_DEVTOOLS_46a64c89d66d278297b6346c60f67e2c" desc="Tooltip text that appears when hovering over the 'Value description' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
     A human-readable version of the value of a range widget (where necessary).
   </message>
-  <message name="IDS_DEVTOOLS_49ee3087348e8d44e1feda1917443987" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Name
-  </message>
   <message name="IDS_DEVTOOLS_4ada42850cc2d4e41f3da5254ec2feee" desc="Reason element in Accessibility Node View of the Accessibility panel">
     Element is inert.
   </message>
@@ -150,12 +147,6 @@
   <message name="IDS_DEVTOOLS_674d8a03d6bb22d48dff01565c2b10a3" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     Owns
   </message>
-  <message name="IDS_DEVTOOLS_689202409e48743b914713f96d93947c" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Value
-  </message>
-  <message name="IDS_DEVTOOLS_6a26f548831e6a8c26bfbbd9f6ec61e0" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Help
-  </message>
   <message name="IDS_DEVTOOLS_73f3b04d99cdbbfb2045ad2285986d77" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     Maximum value
   </message>
@@ -195,9 +186,6 @@
   <message name="IDS_DEVTOOLS_91b442d385b54e1418d81adc34871053" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     Selected
   </message>
-  <message name="IDS_DEVTOOLS_939aaa05e0943b39eab3a34fd609384d" desc="A context menu item in the AXBreadcrumbs Pane of the Accessibility panel">
-    Scroll into view
-  </message>
   <message name="IDS_DEVTOOLS_953f80ed9077d40149a8e68448f09e47" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     From label (wrapped)
   </message>
@@ -243,9 +231,6 @@
   <message name="IDS_DEVTOOLS_a858dfbc32e2169e89668adf8e997f6f" desc="Text in Accessibility Node View of the Accessibility panel">
     No accessibility node
   </message>
-  <message name="IDS_DEVTOOLS_abbd64f40c34c537d3a571af068fce29" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Orientation
-  </message>
   <message name="IDS_DEVTOOLS_aff2b966e54c2212e86343d2bb8d3f88" desc="Reason element in Accessibility Node View of the Accessibility panel">
     Part of label element: '''
   </message>
@@ -261,9 +246,6 @@
   <message name="IDS_DEVTOOLS_b459bb2b480be9a5043f103bbc2f1d49" desc="Tooltip text that appears when hovering over the 'Checked' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
     Whether this checkbox, radio button or tree item is checked, unchecked, or mixed (e.g. has both checked and un-checked children).
   </message>
-  <message name="IDS_DEVTOOLS_b5a7adde1af5c87d7fd797b6245c2a39" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Description
-  </message>
   <message name="IDS_DEVTOOLS_b651efdb98a5d6bd2b3935d0c3f4a5e2" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     Required
   </message>
@@ -273,9 +255,6 @@
   <message name="IDS_DEVTOOLS_b9db1026019a8730b64397052a61ded0" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
     Atomic (live regions)
   </message>
-  <message name="IDS_DEVTOOLS_b9f5c797ebbf55adccdd8539a65a0241" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
-    Disabled
-  </message>
   <message name="IDS_DEVTOOLS_bb129d779ae1ffda5fda12070a4a142b" desc="Tooltip text that appears when hovering over the 'From caption' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
     Value from figcaption element.
   </message>
@@ -342,9 +321,6 @@
   <message name="IDS_DEVTOOLS_e0dcc9aef6db5e61e4102efdf5d54378" desc="Text in Accessibility Node View of the Accessibility panel">
     Invalid source.
   </message>
-  <message name="IDS_DEVTOOLS_e0e4fc6213e8b3593495a7260c3a4c2e" desc="Title of the 'Accessibility' tool in the sidebar of the elements tool">
-    Accessibility
-  </message>
   <message name="IDS_DEVTOOLS_e1312fc3ec5859447389668b721d932f" desc="Tooltip text that appears when hovering over the 'Pressed' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
     Whether this toggle button is currently in a pressed state.
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp b/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
index a91ddae..284c67b8 100644
--- a/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
@@ -15,9 +15,6 @@
   <message name="IDS_DEVTOOLS_5fe41afb268c87f4f56027023d3e6406" desc="Text in Animation Timeline of the Animation Inspector">
     <ph name="PLAYBACKRATE______">$1s<ex>50</ex></ph>%
   </message>
-  <message name="IDS_DEVTOOLS_81aa2078d1eceede831b2976dbf32e62" desc="Tooltip text that appears when hovering over the largeicon clear button in the Animation Timeline of the Animation Inspector">
-    Clear all
-  </message>
   <message name="IDS_DEVTOOLS_96952fa958a61d47ed4dee3f2c3dee64" desc="Tooltip text that appears when hovering over largeicon pause button in Animation Timeline of the Animation Inspector">
     Pause all
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp b/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
index 90dc70f..2ff39e4 100644
--- a/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
@@ -18,9 +18,6 @@
   <message name="IDS_DEVTOOLS_1421c82f3616812789ac346b1638e39d" desc="Text of audits start button in Audits Start View">
     Run audits
   </message>
-  <message name="IDS_DEVTOOLS_1583d36995134f9120fac115c08e0174" desc="Text in Audits Status View">
-    Loading…
-  </message>
   <message name="IDS_DEVTOOLS_15a895a381c23eff5397d8b1f318a726" desc="Text in Audits Controller">
     No network or CPU throttling used. (Useful when not evaluating performance)
   </message>
@@ -39,9 +36,6 @@
   <message name="IDS_DEVTOOLS_2046d43f4cc1f59c06f764da2ca2355a" desc="Status text in the Audits panel">
     The print popup window is open. Please close it to continue.
   </message>
-  <message name="IDS_DEVTOOLS_2310408a63388fe57e3a4177168a8798" desc="Text in Audits Controller">
-    Desktop
-  </message>
   <message name="IDS_DEVTOOLS_24e8ca2483129261096ba8ba0fbcd247" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     70% of mobile pages take nearly 7 seconds for the visual content above the fold to display on the screen. [Source: Think with Google]
   </message>
@@ -54,15 +48,9 @@
   <message name="IDS_DEVTOOLS_3b7e043f46813f1d8ffbd462eb77fb6c" desc="Text in Audits Controller">
     How long does this app take to show content and become usable
   </message>
-  <message name="IDS_DEVTOOLS_3e3f8a3abd60f2389b744ca8ed0aa4d9" desc="Text in Audits Controller">
-    No throttling
-  </message>
   <message name="IDS_DEVTOOLS_3ee3aab0791156ff1d5e0481ed4589b2" desc="Text in Audits Controller">
     Applied Slow 4G, 4x CPU Slowdown
   </message>
-  <message name="IDS_DEVTOOLS_41fdb410354e76ef7674f98e1cc84c8f" desc="Text in Audits Start View labeling throttling configration control group">
-    Throttling
-  </message>
   <message name="IDS_DEVTOOLS_47e2dbd37d8d524f5c4105a96db27b59" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     75% of global mobile users in 2016 were on 2G or 3G [Source: GSMA Mobile]
   </message>
@@ -123,9 +111,6 @@
   <message name="IDS_DEVTOOLS_7bd1e4f7363173e2c8329551ca4d38cc" desc="New audit item label in Audits Report Selector">
     (new audit)
   </message>
-  <message name="IDS_DEVTOOLS_87d17f4624a514e81dc7c8e016a7405c" desc="Text in Audits Controller">
-    Mobile
-  </message>
   <message name="IDS_DEVTOOLS_88450f419690173d62fb0a30fb29a951" desc="Text in Audits Status View">
     Auditing <ph name="PAGEHOST">$1s<ex>github.com</ex></ph>
   </message>
@@ -141,9 +126,6 @@
   <message name="IDS_DEVTOOLS_93c09fb3e06297a9b9504113fa5915ea" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     BBC has seen a loss of 10% of their users for every extra second of page load [Source: WPO Stats]
   </message>
-  <message name="IDS_DEVTOOLS_9446a98ad14416153cc4d45ab8b531bf" desc="Text in Audits Controller">
-    Performance
-  </message>
   <message name="IDS_DEVTOOLS_a3456af9cc3d7cf0c2e288f889f050b7" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     If a site takes &gt;1 second to become interactive, users lose attention, and their perception of completing the page task is broken [Source: Google Developers Blog]
   </message>
@@ -162,9 +144,6 @@
   <message name="IDS_DEVTOOLS_b29bb7427a05d89f1dae6ab5459e2d5c" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     By reducing the response size of JSON needed for displaying comments, Instagram saw increased impressions [Source: WPO Stats]
   </message>
-  <message name="IDS_DEVTOOLS_bc28aa52ba5b534ad9d198157c375d67" desc="Text in Audits Controller">
-    Clear storage
-  </message>
   <message name="IDS_DEVTOOLS_bcf2457dd80557dd7ebdc1504b6149e6" desc="Text in Audits Controller">
     Does this page follow best practices for modern web development
   </message>
@@ -177,18 +156,12 @@
   <message name="IDS_DEVTOOLS_d2f618fd63c7c2028cd527f60e761bc6" desc="Text when lighthouse is loading the page in the Audits panel">
     Lighthouse is loading your page with mobile emulation.
   </message>
-  <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc="Text in Audits Start View">
-    Learn more
-  </message>
   <message name="IDS_DEVTOOLS_d88946b678e4c2f251d4e292e8142291" desc="Text in Audits Controller">
     SEO
   </message>
   <message name="IDS_DEVTOOLS_deeacee140c7d3a451440dd0e206e256" desc="Text in Audits Start View">
     Identify and fix common problems that affect your site&apos;s performance, accessibility, and user experience.
   </message>
-  <message name="IDS_DEVTOOLS_e0ac20adce6ffee48c7151b070aa5737" desc="Text in Audits Start View labeling device configration control group">
-    Device
-  </message>
   <message name="IDS_DEVTOOLS_e339ef3bcd3e92466fa83dc21e690a5b" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     As the number of elements on a page increases from 400 to 6,000, the probability of conversion drops 95%. [Source: Think with Google]
   </message>
@@ -201,9 +174,6 @@
   <message name="IDS_DEVTOOLS_e9fe69c2de7c38bbe442e38780d20081" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
     53% of all site visits are abandoned if page load takes more than 3 seconds [Source: Google DoubleClick blog]
   </message>
-  <message name="IDS_DEVTOOLS_ea4788705e6873b424c65e91c2846b19" desc="Text of the cancel button in Audits Status View">
-    Cancel
-  </message>
   <message name="IDS_DEVTOOLS_ea60ba1496b05c6a5816fb75d0665c8d" desc="Text of a DOM element in Audits Status View">
     If this issue is reproducible, please report it at the Lighthouse GitHub repo.
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp b/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
index 8981fc5..58fccd7 100644
--- a/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
@@ -1,50 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_0ca08f8f4a8a19f7f1ae87c119494327" desc="Title of the 'Overrides' tool in the Overrides Navigator View, which is part of the Sources tool">
-    Overrides
-  </message>
   <message name="IDS_DEVTOOLS_1106d01848580ffc52dd36e2d60316d9" desc="Title of the 'XHR/fetch Breakpoints' tool in the bottom sidebar of the Sources tool">
     XHR/fetch Breakpoints
   </message>
-  <message name="IDS_DEVTOOLS_193cfc9be3b995831c6af2fea6650e60" desc="Title of the 'Page' tool in the Network Navigator View, which is part of the Sources tool">
-    Page
-  </message>
   <message name="IDS_DEVTOOLS_2daf59f0ff992924e42c14c1e674bd6a" desc="Text in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Attribute modified
   </message>
   <message name="IDS_DEVTOOLS_30d67fd6c32c9a9ff5ecb4472b44ed54" desc="Input element container text content in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Break when URL contains:
   </message>
-  <message name="IDS_DEVTOOLS_340641a167ad6da1bcb4016357f4695d" desc="Title of the 'Content scripts' tool in the Content Scripts Navigator View, which is part of the Sources tool">
-    Content scripts
-  </message>
   <message name="IDS_DEVTOOLS_39c145d69ad05e44e74017346c116251" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Remove all DOM breakpoints
   </message>
-  <message name="IDS_DEVTOOLS_47bda3033cb8fe0e76c45c293db011b5" desc="Empty element text content in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
-    No breakpoints
-  </message>
   <message name="IDS_DEVTOOLS_59eaf6955f44a94237b6d26911c1d983" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Break on
   </message>
   <message name="IDS_DEVTOOLS_626585724f35f9d9fce0bd36525cb7de" desc="Title of the Marker Decorator of Elements">
     DOM Breakpoint
   </message>
-  <message name="IDS_DEVTOOLS_63a6a88c066880c5ac42394a22803ca6" desc="Tooltip text that appears when hovering over the largeicon refresh button in the Object Event Listeners Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
-    Refresh
-  </message>
   <message name="IDS_DEVTOOLS_66b74432bdc2797086f419010cc5ff86" desc="Title of the 'DOM Breakpoints' tool in the bottom sidebar of the Sources tool">
     DOM Breakpoints
   </message>
-  <message name="IDS_DEVTOOLS_6ba3a9ac3e0d57683c56299484b7ee3b" desc="Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
-    Remove all breakpoints
-  </message>
-  <message name="IDS_DEVTOOLS_7d341c08fd102f0b86285b5ff2e26ea7" desc="Aria-label for DOMBreakpoint checkboxes">
-    <ph name="BREAKPOINTTYPELABEL">$1s<ex>Node removed</ex></ph>: <ph name="LINKIFIED_DEEPTEXTCONTENT__">$2s<ex>div#id1</ex></ph>
-  </message>
-  <message name="IDS_DEVTOOLS_b4e79b551a1ceae24b7de243ab1fd27c" desc="Tooltip text that appears when hovering over the largeicon add button in the XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
-    Add breakpoint
-  </message>
   <message name="IDS_DEVTOOLS_b839f802a330e4d4145cb182e6767f45" desc="Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Any XHR or fetch
   </message>
@@ -54,9 +30,6 @@
   <message name="IDS_DEVTOOLS_c4bd9c57c6b315e3f7374cf77143ca58" desc="Text in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
     Subtree modified
   </message>
-  <message name="IDS_DEVTOOLS_d5bfaaca8e28f8b9b9211038f86a4494" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
-    Remove breakpoint
-  </message>
   <message name="IDS_DEVTOOLS_e30c4292775f68b2bc9eb3957a69f899" desc="Title of the 'Global Listeners' tool in the bottom sidebar of the Sources tool">
     Global Listeners
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp b/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
index 09b8959b..8888447 100644
--- a/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
@@ -6,10 +6,4 @@
   <message name="IDS_DEVTOOLS_6aed54027cf3a260de904a43cf439cc9" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
     Preserve log on page reload / navigation
   </message>
-  <message name="IDS_DEVTOOLS_edd24cce7afedea5a1b2f90675880687" desc="Title of a setting under the Network category in Settings">
-    Preserve log
-  </message>
-  <message name="IDS_DEVTOOLS_eec89088ee408b80387155272b113256" desc="A title of the 'Network' setting category">
-    Network
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp b/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
index 8bba0fe..de23afbe 100644
--- a/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
@@ -30,7 +30,4 @@
   <message name="IDS_DEVTOOLS_f550ec70278cc72604795d91ff8dcd30" desc="Text in Changes View of the Changes tab">
     Binary data
   </message>
-  <message name="IDS_DEVTOOLS_fa6711f918fe2018131a4ad0380b9e56" desc="Tooltip in Changes Sidebar of the Changes tab">
-    <ph name="THIS_UISOURCECODE_DISPLAYNAME__">$1s<ex>compile.html</ex></ph> (from source map)
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp b/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
index 346e0b25..0537b085 100644
--- a/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
@@ -1,8 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_146ffe2fd9fa5bec3b63b52543793ec7" desc="Tooltip text that appears when hovering over the smallicon expand more button in the Contrast Details of the Color Picker">
-    Show more
-  </message>
   <message name="IDS_DEVTOOLS_158eabad9d23e8a99bbcfd6f411c575f" desc="A context menu item in the Spectrum of the Color Picker">
     Remove color
   </message>
@@ -39,12 +36,6 @@
   <message name="IDS_DEVTOOLS_bbe0cb0a04956e97e8fc70f519d10e0d" desc="Color element title in Spectrum of the Color Picker">
     <ph name="PALETTE_COLORS_I_">$1s<ex>#9c1724</ex></ph>. Long-click to show alternate shades.
   </message>
-  <message name="IDS_DEVTOOLS_c74ea6dbff701bfa23819583c52ebd97" desc="Title of expand button in contrast details of the color picker">
-    Show less
-  </message>
-  <message name="IDS_DEVTOOLS_ce82e07fa1f0521f5cee30e368fe2e73" desc="Text in Contrast Details of the Color Picker">
-    : <ph name="AA_TOFIXED___">$1s<ex>3.0</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_d1e2107b34fa404fabd54bcce4fd858f" desc="Tooltip text that appears when hovering over the largeicon add button in the Spectrum of the Color Picker">
     Add to palette
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/common/UIString.js b/third_party/blink/renderer/devtools/front_end/common/UIString.js
index 8845ed7..cd5f7d08e 100644
--- a/third_party/blink/renderer/devtools/front_end/common/UIString.js
+++ b/third_party/blink/renderer/devtools/front_end/common/UIString.js
@@ -42,6 +42,28 @@
 
 /**
  * @param {string} string
+ * @param {?ArrayLike} values
+ * @return {string}
+ */
+Common.serializeUIString = function(string, values = []) {
+  const messageParts = [string];
+  const serializedMessage = {messageParts, values};
+  return JSON.stringify(serializedMessage);
+};
+
+/**
+ * @param {string} serializedMessage
+ * @return {*}
+ */
+Common.deserializeUIString = function(serializedMessage) {
+  if (!serializedMessage)
+    return {};
+
+  return JSON.parse(serializedMessage);
+};
+
+/**
+ * @param {string} string
  * @return {string}
  */
 Common.localize = function(string) {
diff --git a/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp b/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
index 01189af..837cd18 100644
--- a/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
@@ -3,42 +3,21 @@
   <message name="IDS_DEVTOOLS_013cf261f9ccf5d4f027bc001d0d1d0c" desc="Text in Linkifier">
     (unknown)
   </message>
-  <message name="IDS_DEVTOOLS_0b484cfcf50c8fabff48c0aad426f544" desc="Text in Dock Controller">
-    Dock to left
-  </message>
   <message name="IDS_DEVTOOLS_131c97f8ba5bc0277386d660a18f13b6" desc="Text in Linkifier">
     Reveal in <ph name="DESTINATION">$1s<ex>Sources panel</ex></ph>
   </message>
-  <message name="IDS_DEVTOOLS_393c3f5ea8ad35c02691d507bdbb31b0" desc="Text in Linkifier">
-    Reveal
-  </message>
   <message name="IDS_DEVTOOLS_7f52f5f786eb8d9bf9e56ce89fb3db3a" desc="Show all link text content in JSPresentation Utils">
     Show 1 more frame
   </message>
   <message name="IDS_DEVTOOLS_908ae571a925e675f5c55619aa16a99b" desc="Description in Image Preview">
     <ph name="RENDEREDWIDTH">$1s<ex>500</ex></ph> × <ph name="RENDEREDHEIGHT">$2s<ex>300</ex></ph> pixels (intrinsic: <ph name="INTRINSICWIDTH">$3s<ex>200</ex></ph> × <ph name="INTRINSICHEIGHT">$4s<ex>100</ex></ph> pixels)
   </message>
-  <message name="IDS_DEVTOOLS_93898e12951c906e5286ccb36d980ce5" desc="A context menu item in the JSPresentation Utils">
-    Blackbox script
-  </message>
-  <message name="IDS_DEVTOOLS_9df22f196a33acd0b372fe502de51211" desc="Text in Linkifier">
-    auto
-  </message>
   <message name="IDS_DEVTOOLS_a498f0751d1221223efb0defc71cc804" desc="Description in Image Preview">
     <ph name="RENDEREDWIDTH">$1s<ex>500</ex></ph> × <ph name="RENDEREDHEIGHT">$2s<ex>500</ex></ph> pixels
   </message>
-  <message name="IDS_DEVTOOLS_b9dee6bade160c89fb7f0e539d453513" desc="Text in Dock Controller">
-    Dock to bottom
-  </message>
-  <message name="IDS_DEVTOOLS_c3fe109bf99ade2d76a55e5737015e3e" desc="A context menu item in the JSPresentation Utils">
-    Stop blackboxing
-  </message>
   <message name="IDS_DEVTOOLS_c850ae12703fa2b00eeaf8445ecf00ef" desc="Show all link text content in JSPresentation Utils">
     Show <ph name="TOTALHIDDENCALLFRAMESCOUNT">$1s<ex>2</ex></ph> more frames
   </message>
-  <message name="IDS_DEVTOOLS_d3d2e617335f08df83599665eef8a418" desc="Tooltip text that appears when hovering over the largeicon delete button in the Dock Controller">
-    Close
-  </message>
   <message name="IDS_DEVTOOLS_e3de40c656e1189770049db9846b69df" desc="Text on the remote debugging window to indicate the connection is lost">
     WebSocket disconnected
   </message>
@@ -48,10 +27,4 @@
   <message name="IDS_DEVTOOLS_e6cd0f8a4fe4fb9e08505b784e48caa2" desc="Text in Linkifier">
     Link handling:
   </message>
-  <message name="IDS_DEVTOOLS_f53944c3a55bdb5ad65c6226e358a626" desc="Text in Dock Controller">
-    Undock into separate window
-  </message>
-  <message name="IDS_DEVTOOLS_fe7fb037b290768d6a6be30b237e183d" desc="Text in Dock Controller">
-    Dock to right
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp b/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
index b4cbf8e..320cd87 100644
--- a/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
@@ -15,9 +15,6 @@
   <message name="IDS_DEVTOOLS_04c247c2ba261c7511e4f479728bd7ea" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
     Do not treat evaluation as user activation
   </message>
-  <message name="IDS_DEVTOOLS_0511551e6cf7d61acd9b62f9304efa93" desc="Tooltip text that appears on the setting when hovering over it in Console View of the Console panel">
-    Do not clear log on page reload / navigation
-  </message>
   <message name="IDS_DEVTOOLS_07213a0161f52846ab198be103b5ab43" desc="Text in Console Sidebar of the Console panel">
     errors
   </message>
@@ -33,18 +30,12 @@
   <message name="IDS_DEVTOOLS_0bbce02e304562c295a1d57d66c296d3" desc="Text in Console View Message of the Console panel">
     &lt;URL&gt;
   </message>
-  <message name="IDS_DEVTOOLS_0eaadb4fcb48a0a0ed7bc9868be9fbaa" desc="Accessible name in Console View Message of the Console panel">
-    Warning
-  </message>
   <message name="IDS_DEVTOOLS_0fa06588bd5c83bd6f3b1734eefc6b16" desc="Text in Console View of the Console panel">
     Hide messages from <ph name="NEW_COMMON_PARSEDURL_CONSOLEMESSAGE_URL__DISPLAYNAME">$1s<ex>index.js</ex></ph>
   </message>
   <message name="IDS_DEVTOOLS_1a37d25ba6689d174f51ba8e2425fde6" desc="Filter name in Console Sidebar of the Console panel">
     &lt;other&gt;
   </message>
-  <message name="IDS_DEVTOOLS_1ebc7540a5327b857144f04cf1435b4e" desc="A context menu item in the Console View of the Console panel">
-    Replay XHR
-  </message>
   <message name="IDS_DEVTOOLS_26649c8f3cadc9c0170f2443e6fc0252" desc="Text in Console View Message of the Console panel">
     &lt;attribute&gt;
   </message>
@@ -102,18 +93,9 @@
   <message name="IDS_DEVTOOLS_4cad9e20fde3f8991c5dd1d6a0fe13e7" desc="A context menu item in the Console Pin Pane of the Console panel">
     Remove expression
   </message>
-  <message name="IDS_DEVTOOLS_4d1b0b75a9737b7dcdc3a15a84fe856b" desc="Title of search progress indicator in console view of the console panel">
-    Searching…
-  </message>
   <message name="IDS_DEVTOOLS_53f0fca28a013c116a1df533d9bdf764" desc="Message text in Console View Message of the Console panel">
     [Deprecation] <ph name="MESSAGETEXT">$1s<ex>console.log(1)</ex></ph>
   </message>
-  <message name="IDS_DEVTOOLS_5ef0c737746fae2ca90e66c39333f8f6" desc="Sdk console message message level error of level Labels in Console View of the Console panel">
-    Errors
-  </message>
-  <message name="IDS_DEVTOOLS_5f8442a46861496e9d2a3d11be13692b" desc="Title of progress indicator in console view of the console panel">
-    Writing file…
-  </message>
   <message name="IDS_DEVTOOLS_6047a6c9fb775557639afb3fbc90b4e7" desc="Text in Console View of the Console panel">
     Log levels
   </message>
@@ -144,24 +126,12 @@
   <message name="IDS_DEVTOOLS_7be1a30a7758269755609f1f7434d828" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
     Group similar messages in console
   </message>
-  <message name="IDS_DEVTOOLS_84d0c431d1472a0609d69b39dcb3a287" desc="Text in Console View Message of the Console panel">
-    (index)
-  </message>
-  <message name="IDS_DEVTOOLS_902b0d55fddef6f8d651fe1035b7d4bd" desc="Accessible name in Console View Message of the Console panel">
-    Error
-  </message>
   <message name="IDS_DEVTOOLS_93977f1310f482395375a9950b512462" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
     Eagerly evaluate console prompt text
   </message>
   <message name="IDS_DEVTOOLS_95c74dafb449d894014c2eb1d80ded01" desc="A context menu item in the Console Pin Pane of the Console panel">
     Edit expression
   </message>
-  <message name="IDS_DEVTOOLS_9aae9fe27dbf2db0ad90762b5b59d3a7" desc="Title of an action in the console tool to clear">
-    Clear console
-  </message>
-  <message name="IDS_DEVTOOLS_9d8c209e49e328528c39c273798e98c9" desc="A context menu item in the Console View of the Console panel">
-    Save as...
-  </message>
   <message name="IDS_DEVTOOLS_a092483ed730ed040e5df5776dca49e5" desc="Title of a setting under the Console category in Settings">
     Log XMLHttpRequests
   </message>
@@ -195,9 +165,6 @@
   <message name="IDS_DEVTOOLS_bafd7322c6e97d25b6299b5d6fe8920b" desc="Text in Console Sidebar of the Console panel">
     No
   </message>
-  <message name="IDS_DEVTOOLS_bccaa4aa80831b76c11240a16447975f" desc="Title of the 'Console' tool in the bottom drawer">
-    Console
-  </message>
   <message name="IDS_DEVTOOLS_c0274fa278f2e0dfef862234e0eb9b8b" desc="Element text content in Console View Message of the Console panel">
     &lt;exception&gt;
   </message>
@@ -243,9 +210,6 @@
   <message name="IDS_DEVTOOLS_d7746aa6b562c73487a4015eef3244e9" desc="Text in Console Context Selector of the Console panel">
     IFrame
   </message>
-  <message name="IDS_DEVTOOLS_d7778d0c64b6ba21494c97f77a66885a" desc="Text in Console View of the Console panel">
-    Filter
-  </message>
   <message name="IDS_DEVTOOLS_d779282283c011149d163edbcd5e5f11" desc="Side effect label title in Console Pin Pane of the Console panel">
     Evaluate, allowing side effects
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp b/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
index d4e0c86..9f3f28c 100644
--- a/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
@@ -3,28 +3,13 @@
   <message name="IDS_DEVTOOLS_2e7501c512976a9d9a9dca45bce9f128" desc="Text in Cookies Table of the Cookies table in the Application panel">
     Expires / Max-Age
   </message>
-  <message name="IDS_DEVTOOLS_382b0f5185773fa0f67a8ed8056c7759" desc="Data expires in Cookies Table of the Cookies table in the Application panel">
-    N/A
-  </message>
   <message name="IDS_DEVTOOLS_6c8f0cef6081f0f97ec0f01a5a3ce2a7" desc="Text in Cookies Table of the Cookies table in the Application panel">
     HttpOnly
   </message>
-  <message name="IDS_DEVTOOLS_6f6cb72d544962fa333e2e34ce64f719" desc="Text in Cookies Table of the Cookies table in the Application panel">
-    Size
-  </message>
   <message name="IDS_DEVTOOLS_71c7ae294b7abd866b3fb295b3b9e4a4" desc="Cookie table cookies table expires session value in Cookies Table of the Cookies table in the Application panel">
     Session
   </message>
-  <message name="IDS_DEVTOOLS_7a2ccf251ecb20b2b84ce0e3c3f72a29" desc="Text in Cookies Table of the Cookies table in the Application panel">
-    Secure
-  </message>
   <message name="IDS_DEVTOOLS_9f8e4d5e9b6d7a439dc6b5ebc5eedca4" desc="Text in Cookies Table of the Cookies table in the Application panel">
     SameSite
   </message>
-  <message name="IDS_DEVTOOLS_ac70412e939d72a9234cdebb1af5867b" desc="Text in Cookies Table of the Cookies table in the Application panel">
-    Path
-  </message>
-  <message name="IDS_DEVTOOLS_eae639a70006feff484a39363c977e24" desc="Text in Cookies Table of the Cookies table in the Application panel">
-    Domain
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp b/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
index 1dd15152..eee29fb 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
@@ -19,9 +19,6 @@
   <message name="IDS_DEVTOOLS_5bc06f5800d415cc95e1349edbaca425" desc="Text in Coverage List View of the Coverage tab">
     JS
   </message>
-  <message name="IDS_DEVTOOLS_6525b37c568c526bde7c02fac8195c73" desc="Unused percents span text content in Coverage List View of the Coverage tab">
-    <ph name="UNUSEDSIZE___THIS__COVERAGEINFO_SIZE________">$1.1f<ex>20.1</ex></ph> %%
-  </message>
   <message name="IDS_DEVTOOLS_73af525212a812236f1a3618e9cfa717" desc="Tooltip text that appears when hovering over the largeicon download button in the Coverage View of the Coverage tab">
     Export...
   </message>
@@ -44,9 +41,6 @@
   <message name="IDS_DEVTOOLS_9841bdc50c4226cb6ec5db76494249e6" desc="Title of the 'Coverage' tool in the bottom drawer">
     Coverage
   </message>
-  <message name="IDS_DEVTOOLS_a1fa27779242b4902f7ae3bdd5c6d508" desc="Text in Coverage List View of the Coverage tab">
-    Type
-  </message>
   <message name="IDS_DEVTOOLS_bca27ccb808f436cd1ce828dd47604b7" desc="Title of an action in the coverage tool to start with reload">
     Start instrumenting coverage and reload page
   </message>
@@ -56,7 +50,4 @@
   <message name="IDS_DEVTOOLS_d98bd5257b9f29c266777264411735a3" desc="Tooltip text that appears on the setting when hovering over it in Coverage View of the Coverage tab">
     Include extension content scripts
   </message>
-  <message name="IDS_DEVTOOLS_e6b391a8d2c4d45902a23a8b6585703d" desc="Text in Coverage List View of the Coverage tab">
-    URL
-  </message>
 </grit-part>
diff --git a/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp b/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
index d5918a93..c99b4a8 100644
--- a/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
@@ -18,7 +18,4 @@
   <message name="IDS_DEVTOOLS_ef61fb324d729c341ea8ab9901e23566" desc="A context menu item in the Data Grid of a data grid">
     Add new
   </message>
-  <message name="IDS_DEVTOOLS_f2a6c498fb90ee345d997f888fce3b18" desc="A context menu item in the Data Grid of a data grid">
-    Delete
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp b/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
index 065c7f51..fd33294 100644
--- a/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
@@ -81,9 +81,6 @@
   <message name="IDS_DEVTOOLS_bcca96534b404f08faf65d76be6aa782" desc="Text in Devices View of the Remote Devices tab">
     1 device detected.
   </message>
-  <message name="IDS_DEVTOOLS_c03ca67dda321195d74c951097f240c6" desc="Text of a DOM element in Devices View of the Remote Devices tab">
-    Devices
-  </message>
   <message name="IDS_DEVTOOLS_c3bf447eabe632720a3aa1a7ce401274" desc="Text of the new tab button in Devices View of the Remote Devices tab">
     Open
   </message>
@@ -105,18 +102,12 @@
   <message name="IDS_DEVTOOLS_e1f70f4a4265cb51c1b219aa60eaa441" desc="New tab input placeholder in Devices View of the Remote Devices tab">
     Enter URL
   </message>
-  <message name="IDS_DEVTOOLS_e24ee2487879116dcab772c0ac4fe341" desc="A context menu item in the Devices View of the Remote Devices tab">
-    Focus
-  </message>
   <message name="IDS_DEVTOOLS_ed725244eec042fa550990c608639b38" desc="Text in Devices View of the Remote Devices tab">
     Define the listening port on your device that maps to a port accessible from your development machine. Read <ph name="DOCUMENTATIONLINK">$1s<ex>documentation link</ex></ph> for more.
   </message>
   <message name="IDS_DEVTOOLS_f114563447e4786042d7e7ce05f1157c" desc="Text in Devices View of the Remote Devices tab">
     Device port (3333)
   </message>
-  <message name="IDS_DEVTOOLS_f4f70727dc34561dfde1a3c529b6205c" desc="Discovery list item text content in Devices View of the Remote Devices tab">
-    Settings
-  </message>
   <message name="IDS_DEVTOOLS_fa5ef75cf38d69be2973c570c1d47b29" desc="Error message for device port input box when add port forwarding rule">
     Device port must be a number
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp b/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
index 7cdbcc7e..8360b3a6 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
@@ -72,21 +72,12 @@
   <message name="IDS_DEVTOOLS_365fee797b55ffeac84d2ba82507b721" desc="Text in Styles Sidebar Pane of the Elements panel">
     user agent stylesheet
   </message>
-  <message name="IDS_DEVTOOLS_3afbd9828e011526955ca93b48b57524" desc="A title of the 'Screenshot' action category">
-    Screenshot
-  </message>
-  <message name="IDS_DEVTOOLS_3bb3e8c8a24891ba0f7608bcc96f8b0a" desc="Text in Elements Panel of the Elements panel">
-    Frame
-  </message>
   <message name="IDS_DEVTOOLS_3e255d6c811a40b9ad197fedeadc342c" desc="Text in Platform Fonts Widget of the Elements panel">
     Local file
   </message>
   <message name="IDS_DEVTOOLS_3e9bec182c7495247f5f93d3881d630b" desc="Text in Element State Pane Widget of the Elements panel">
     :hov
   </message>
-  <message name="IDS_DEVTOOLS_3f8f88e3686b2345cecc9530e19e6172" desc="A context menu item in the Elements Tree Outline of the Elements panel">
-    Store as global variable
-  </message>
   <message name="IDS_DEVTOOLS_417117e823d14c9b7c6533e4b04600a6" desc="Text in Elements Breadcrumbs of the Elements panel">
     (text)
   </message>
@@ -114,18 +105,9 @@
   <message name="IDS_DEVTOOLS_4ca94080ccbd5784f5fe296bf1ae3e12" desc="Title of the 'Event Listeners' tool in the sidebar of the elements tool">
     Event Listeners
   </message>
-  <message name="IDS_DEVTOOLS_4cf8e5f6ffbb182b5d480cbabae6a028" desc="A context menu item in the Elements Tree Element of the Elements panel">
-    Edit attribute
-  </message>
   <message name="IDS_DEVTOOLS_4d9468d79ef34f71ba78a28688fa5d31" desc="Alternative title text of a setting in Event Listeners Widget of the Elements panel">
     Ancestors
   </message>
-  <message name="IDS_DEVTOOLS_5134111907df828fc575c69e22480c1e" desc="Text in Elements Tree Element of the Elements panel">
-    Hide element
-  </message>
-  <message name="IDS_DEVTOOLS_539dddc574d3cd85ba73df93df7a76d0" desc="Title of the Stack Trace widget in the Elements panel">
-    Stack Trace
-  </message>
   <message name="IDS_DEVTOOLS_581b87189d0bd86aa707e42553032a3e" desc="Element text content in Elements Tree Element of the Elements panel">
     Children:
   </message>
@@ -138,24 +120,15 @@
   <message name="IDS_DEVTOOLS_5c6236c705b0086fbbdb2df3133f8a06" desc="Title of a setting under the Elements category in Settings">
     Reveal DOM node on hover
   </message>
-  <message name="IDS_DEVTOOLS_5de39fa1bce4bbf9232597a2120bc4d4" desc="Swatch icon element title in Color Swatch Popover Icon of the Elements panel">
-    Open cubic bezier editor.
-  </message>
   <message name="IDS_DEVTOOLS_5eeb03a9c080c299d4804ac765c818c2" desc="No matches element text content in Styles Sidebar Pane of the Elements panel">
     No matching selector or style
   </message>
-  <message name="IDS_DEVTOOLS_5fb63579fc981698f97d55bfecb213ea" desc="A context menu item in the Elements Tree Element of the Elements panel">
-    Copy
-  </message>
   <message name="IDS_DEVTOOLS_6053f828a109e7d9da3690a7416e4eec" desc="Text in Elements Tree Element of the Elements panel">
     Copy XPath
   </message>
   <message name="IDS_DEVTOOLS_605e072850e19521394f8bad7082acf4" desc="Text of a DOM element in Element State Pane Widget of the Elements panel">
     Force element state
   </message>
-  <message name="IDS_DEVTOOLS_63041e09c8660107e507c9c27c08199c" desc="A context menu item in the Elements Tree Element of the Elements panel">
-    Expand recursively
-  </message>
   <message name="IDS_DEVTOOLS_686676f33cf19ca00788564f43b992cb" desc="Aria accessible name in Computed Style Widget of the Elements panel">
     Filter Computed Styles
   </message>
@@ -231,24 +204,15 @@
   <message name="IDS_DEVTOOLS_a98895bde5922dd43c82ad7050abc05a" desc="Tooltip text that appears on the setting when hovering over it in Event Listeners Widget of the Elements panel">
     Show listeners on the ancestors
   </message>
-  <message name="IDS_DEVTOOLS_aa56a2e65d8106aef3c61e4f6bf94fdb" desc="A title of the 'Elements' @UI.ViewLocationResolver category">
-    Elements
-  </message>
   <message name="IDS_DEVTOOLS_abdf882c25e08d9ba219fe33f17591fe" desc="Link text content in Elements Tree Outline of the Elements panel">
     reveal
   </message>
-  <message name="IDS_DEVTOOLS_acc24772ac31677d076f17d9002b57cd" desc="A context menu item in the Elements Tree Element of the Elements panel">
-    Collapse children
-  </message>
   <message name="IDS_DEVTOOLS_ad4ac01e4a5688063dace5ba5d0f04de" desc="Tooltip text that appears when hovering over the largeicon add button in the Styles Sidebar Pane of the Elements panel">
     Insert Style Rule Below
   </message>
   <message name="IDS_DEVTOOLS_b0351810a5721f657b088608865849dd" desc="Text in Styles Sidebar Pane of the Elements panel">
     via inspector
   </message>
-  <message name="IDS_DEVTOOLS_b1c94ca2fbc3e78fc30069c8d0f01680" desc="Text in Event Listeners Widget of the Elements panel">
-    All
-  </message>
   <message name="IDS_DEVTOOLS_b70cdb878a204fecf91c7dd1af312421" desc="Text in Metrics Sidebar Pane of the Elements panel">
     padding
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp b/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
index 313f6988..191849ae 100644
--- a/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
@@ -48,12 +48,6 @@
   <message name="IDS_DEVTOOLS_2496af30b64c3a4ff21e8505ea439a73" desc="Text in Device Mode Toolbar of the Device Toolbar">
     50%
   </message>
-  <message name="IDS_DEVTOOLS_29260f495ba8adcc62fd1307c758ff4e" desc="Text in Device Mode Toolbar of the Device Toolbar">
-    Show rulers
-  </message>
-  <message name="IDS_DEVTOOLS_29296fcb28eb4edf5d0049b6cac7bbd1" desc="Text in Device Mode Toolbar of the Device Toolbar">
-    <ph name="THIS__MODEL_SCALE________">$1.0f<ex>13.0</ex></ph>%%
-  </message>
   <message name="IDS_DEVTOOLS_29eaeee66d8210c1261d748071fb7b0a" desc="Text in Sensors View of the Device Toolbar">
     Landscape right
   </message>
@@ -69,9 +63,6 @@
   <message name="IDS_DEVTOOLS_31d0615d58891f425fd66979cfa5193b" desc="Error message in the Devices settings pane that declares the maximum value for the width input">
     Width must be less than or equal to <ph name="EMULATION_DEVICEMODEMODEL_MAXDEVICESIZE">$1s<ex>9999</ex></ph>.
   </message>
-  <message name="IDS_DEVTOOLS_323d4eb70b252acb4a04eaf9e0882597" desc="Text in Sensors View of the Device Toolbar">
-    Geolocation
-  </message>
   <message name="IDS_DEVTOOLS_32954654ac8fe66a1d09be19001de2d4" desc="Width input title in Device Mode Toolbar of the Device Toolbar">
     Width
   </message>
@@ -108,15 +99,9 @@
   <message name="IDS_DEVTOOLS_414b730ab2cf9123d9230740864ffeec" desc="A context menu item in the Device Mode Toolbar of the Device Toolbar">
     Close DevTools
   </message>
-  <message name="IDS_DEVTOOLS_4252b72e6ebcd4d4b4c2e46a786f03d2" desc="Title of scale item in device mode toolbar of the device toolbar">
-    Zoom
-  </message>
   <message name="IDS_DEVTOOLS_45f80006d304f294d6c1de50c244856e" desc="Text of add geolocations button in Geolocations Settings Tab of the Device Toolbar">
     Add location...
   </message>
-  <message name="IDS_DEVTOOLS_4dab36ac83853282fc0d7bae20c19e90" desc="Title of more options button in device mode toolbar of the device toolbar">
-    More options
-  </message>
   <message name="IDS_DEVTOOLS_526d688f37a86d3c3f27d0c5016eb71d" desc="Text of orientation reset button in Sensors View of the Device Toolbar">
     Reset
   </message>
@@ -156,9 +141,6 @@
   <message name="IDS_DEVTOOLS_673a7b89eb57bf2bf891306c98cbecc3" desc="Error message in the Geolocations settings pane that declares that the value for the latitude input must be a number">
     Latitude must be a number
   </message>
-  <message name="IDS_DEVTOOLS_6adf97f83acf6453d4a6a4b1070f3754" desc="Text in Device Mode Toolbar of the Device Toolbar">
-    None
-  </message>
   <message name="IDS_DEVTOOLS_6e641146898080ed83f3007cd712f58f" desc="Error message in the Devices settings pane that declares the maximum value for the device pixel ratio input">
     Device pixel ratio must be less than or equal to <ph name="EMULATION_DEVICEMODEMODEL_MAXDEVICESCALEFACTOR">$1s<ex>10</ex></ph>.
   </message>
@@ -348,9 +330,6 @@
   <message name="IDS_DEVTOOLS_f01ee7fedba5e392f6f9adab7ec0c74a" desc="Error message in the Geolocations settings pane that declares the location name input must not be empty">
     Location name cannot be empty
   </message>
-  <message name="IDS_DEVTOOLS_f0f31c9700c6b10d8a20dc487b2ae6a8" desc="Text in Sensors View of the Device Toolbar">
-    Touch
-  </message>
   <message name="IDS_DEVTOOLS_f2a72a44f7b7d30829c0405ed2385345" desc="Text in Device Mode View of the Device Toolbar">
     Mobile S
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp b/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
index 688e675..0ae06b98 100644
--- a/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
@@ -3,9 +3,6 @@
   <message name="IDS_DEVTOOLS_0b9c1def3b0d84fe6234388ff8dfa8b7" desc="Passive button title in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
     Toggle whether event listener is passive or blocking
   </message>
-  <message name="IDS_DEVTOOLS_1063e38cb53d94d386f21227fcd84717" desc="Delete button text content in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
-    Remove
-  </message>
   <message name="IDS_DEVTOOLS_7667495b756ef15210cd60285d8de58a" desc="Empty holder text content in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
     No event listeners
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
index 4be1eb47..dc0d8b3b 100644
--- a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
+++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
@@ -756,7 +756,7 @@
    * @param {string} status
    */
   updateStatus(status) {
-    this._sendUpdateEvent(Common.UIString(status));
+    this._sendUpdateEvent(Common.serializeUIString(status));
   }
 
   /**
@@ -766,7 +766,7 @@
    */
   updateProgress(title, value, total) {
     const percentValue = ((total ? (value / total) : 0) * 100).toFixed(0);
-    this._sendUpdateEvent(Common.UIString(title, percentValue));
+    this._sendUpdateEvent(Common.serializeUIString(title, [percentValue]));
   }
 
   /**
@@ -779,12 +779,12 @@
   }
 
   /**
-   * @param {string} text
+   * @param {string} serializedText
    */
-  _sendUpdateEvent(text) {
+  _sendUpdateEvent(serializedText) {
     // May be undefined in tests.
     if (this._dispatcher)
-      this._dispatcher.sendEvent(HeapSnapshotModel.HeapSnapshotProgressEvent.Update, text);
+      this._dispatcher.sendEvent(HeapSnapshotModel.HeapSnapshotProgressEvent.Update, serializedText);
   }
 };
 
diff --git a/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp b/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
index 53ee7ea..8e07cb8 100644
--- a/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
@@ -15,7 +15,4 @@
   <message name="IDS_DEVTOOLS_91770f038cd944a1d3b9b347edeb2b10" desc="Title of the 'What's New' tool in the bottom drawer">
     What&apos;s New
   </message>
-  <message name="IDS_DEVTOOLS_a1c58e94227389415de133efdf78ea6e" desc="A title of the 'Appearance' setting category">
-    Appearance
-  </message>
 </grit-part>
diff --git a/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
index 5efd6b0b..b073284 100644
--- a/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
@@ -33,9 +33,6 @@
   <message name="IDS_DEVTOOLS_43f244627bf87f76a0dee86f364df473" desc="Checkbox subtitle for 'Layout Shift Regions' in the Rendering tool">
     Highlights areas of the page (blue) that were shifted. May not be suitable for people prone to photosensitive epilepsy.
   </message>
-  <message name="IDS_DEVTOOLS_482a4dca0bbd8fcdda5acc6f95f3c279" desc="A title of the 'DevTools' setting category">
-    DevTools
-  </message>
   <message name="IDS_DEVTOOLS_53f2f05226edcd77bd4351cb27d07ba8" desc="Text in Rendering Options">
     Highlights frames (red) detected to be ads.
   </message>
@@ -72,27 +69,18 @@
   <message name="IDS_DEVTOOLS_960568e27eb66ea554c3be4cfbefe3d0" desc="Text in Rendering Options">
     Layer borders
   </message>
-  <message name="IDS_DEVTOOLS_a02c83a7dbd96295beaefb72c2bee2de" desc="Text in Inspector Main">
-    Main
-  </message>
   <message name="IDS_DEVTOOLS_a15932c4dfbbcbc1ac6f5c27c6fa530f" desc="Text in Rendering Options">
     Highlights elements (teal) that can slow down scrolling, including touch &amp; wheel event handlers and other main-thread scrolling situations.
   </message>
   <message name="IDS_DEVTOOLS_a4c766a2e6eb33e7575331b6affd9778" desc="Checkbox subtitle for 'Paint flashing' in the Rendering tool">
     Highlights areas of the page (green) that need to be repainted. May not be suitable for people prone to photosensitive epilepsy.
   </message>
-  <message name="IDS_DEVTOOLS_a6e8f9aed2ac6481dc25a18a33342d03" desc="Title of the Rendering tool in the bottom drawer">
-    Rendering
-  </message>
   <message name="IDS_DEVTOOLS_cb835af5f855f79e8611dd3f8fec6aac" desc="Title of an action in the inspector main tool to reload">
     Reload page
   </message>
   <message name="IDS_DEVTOOLS_d543dbe64db0c952d6e13c9519218b3e" desc="Title of an action in the inspector main tool to hard reload">
     Hard reload page
   </message>
-  <message name="IDS_DEVTOOLS_ef95393ad48336d7c3543625354a3d56" desc="Text in Rendering Options">
-    Highlight ad frames
-  </message>
   <message name="IDS_DEVTOOLS_f23c9ba06e7123f0b4c906de90fbcc9f" desc="Title of a setting under the DevTools category that can be invoked through the Command Menu">
     Auto-open DevTools for popups
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
index 1432b09..3e094772 100644
--- a/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
@@ -1,6 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_65b4c7424dd695c30efa73da8396c90c" desc="Title of the 'Profiler' tool">
-    Profiler
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd b/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
index 230b8e4..af6a9228 100644
--- a/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
+++ b/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
@@ -67,6 +67,7 @@
       <part file="../ui/ui_strings.grdp" />
       <part file="../web_audio/web_audio_strings.grdp" />
       <part file="../workspace/workspace_strings.grdp" />
+      <part file="shared_strings.grdp" />
     </messages>
   </release>
 </grit>
diff --git a/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp b/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp
new file mode 100644
index 0000000..24b35df0
--- /dev/null
+++ b/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp
@@ -0,0 +1,586 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Strings in this file are shared, i.e. they appear multiple times. -->
+<grit-part>
+  <message name="IDS_DEVTOOLS_007c41a9025be2c8e14b496ed3ee00f8" desc="Text to save an item">
+    Save…
+  </message>
+  <message name="IDS_DEVTOOLS_0511551e6cf7d61acd9b62f9304efa93" desc="Tooltip text that appears on the setting to preserve log when hovering over the item">
+    Do not clear log on page reload / navigation
+  </message>
+  <message name="IDS_DEVTOOLS_0b484cfcf50c8fabff48c0aad426f544" desc="Text to dock the DevTools to the left of the browser tab">
+    Dock to left
+  </message>
+  <message name="IDS_DEVTOOLS_0ca08f8f4a8a19f7f1ae87c119494327" desc="Title as part of a tool to override existing configurations">
+    Overrides
+  </message>
+  <message name="IDS_DEVTOOLS_0eaadb4fcb48a0a0ed7bc9868be9fbaa" desc="Text to indicate an item is a warning">
+    Warning
+  </message>
+  <message name="IDS_DEVTOOLS_0f44e9e39cbe2f22bd1bd7b6070cf13d" desc="Text to enable blocking of network requests">
+    Enable request blocking
+  </message>
+  <message name="IDS_DEVTOOLS_105078d294d30c978ca2badf7f376934" desc="The action to scroll">
+    Scroll
+  </message>
+  <message name="IDS_DEVTOOLS_1063e38cb53d94d386f21227fcd84717" desc="Label for an item to remove something">
+    Remove
+  </message>
+  <message name="IDS_DEVTOOLS_11a755d598c0c417f9a36758c3da7481" desc="Text of an item that stops the running task">
+    Stop
+  </message>
+  <message name="IDS_DEVTOOLS_13348442cc6a27032d2b4aa28b75a5d3" desc="Title of a search bar or tool">
+    Search
+  </message>
+  <message name="IDS_DEVTOOLS_146ffe2fd9fa5bec3b63b52543793ec7" desc="Text to show more content">
+    Show more
+  </message>
+  <message name="IDS_DEVTOOLS_1583d36995134f9120fac115c08e0174" desc="Text when something is loading">
+    Loading…
+  </message>
+  <message name="IDS_DEVTOOLS_16f78b9465f03f7ec5a03c24918fbde3" desc="Status code of an event">
+    Status Code
+  </message>
+  <message name="IDS_DEVTOOLS_193cfc9be3b995831c6af2fea6650e60" desc="Text that refers to one or a group of webpages">
+    Page
+  </message>
+  <message name="IDS_DEVTOOLS_1eaeeaeb638fdf7f6eeb047abbfd0f1a" desc="Time of a single activity, as opposed to the total time">
+    Self Time
+  </message>
+  <message name="IDS_DEVTOOLS_1ebc7540a5327b857144f04cf1435b4e" desc="Text to replay an XHR request">
+    Replay XHR
+  </message>
+  <message name="IDS_DEVTOOLS_1f1e990a1d2ba8ab4dd873a192237c30" desc="Time in miliseconds">
+    <ph name="VALUE">$1.1f<ex>30.1</ex></ph> ms
+  </message>
+  <message name="IDS_DEVTOOLS_22b6fe30dec1ae9c09480cce01cd4065" desc="Text to run commands">
+    Run command
+  </message>
+  <message name="IDS_DEVTOOLS_2310408a63388fe57e3a4177168a8798" desc="Text for the desktop platform, as opposed to mobile">
+    Desktop
+  </message>
+  <message name="IDS_DEVTOOLS_26ae7bdd1d6fb8c4886e6fde8d12601c" desc="Text for the latency of a task">
+    Latency
+  </message>
+  <message name="IDS_DEVTOOLS_290612199861c31d1036b185b4e69b75" desc="Text for the summary view">
+    Summary
+  </message>
+  <message name="IDS_DEVTOOLS_29260f495ba8adcc62fd1307c758ff4e" desc="Text to show the measuring rulers on the target">
+    Show rulers
+  </message>
+  <message name="IDS_DEVTOOLS_29296fcb28eb4edf5d0049b6cac7bbd1" desc="Text for a percentage value">
+    <ph name="SCALE">$1.0f<ex>13.0</ex></ph>%%
+  </message>
+  <message name="IDS_DEVTOOLS_29e9d8e295b1d5b3002d2d3d5baa4c37" desc="Text for keyboard shortcuts">
+    Shortcuts
+  </message>
+  <message name="IDS_DEVTOOLS_2ab5656e27a0ed871c8de44368f807c6" desc="Title of the styles side pane in Elements panel">
+    Styles Pane
+  </message>
+  <message name="IDS_DEVTOOLS_2ae207ddfe5cd256a768769d93a879e5" desc="Title of the paint profiler, old name of the performance pane">
+    Paint Profiler
+  </message>
+  <message name="IDS_DEVTOOLS_2b81bb9b3deebcbfa05edad7a845005a" desc="Text for rendering frames">
+    Frames
+  </message>
+  <message name="IDS_DEVTOOLS_2bbc845892f400626baab5af687527c5" desc="Text for the start time of an activity">
+    Start Time
+  </message>
+  <message name="IDS_DEVTOOLS_2ce2fc341b0bd9219a3634ff43a90bde" desc="Generic text with two placeholders separated by a comma">
+    <ph name="ITEM_LABEL">$1s<ex>1 613 680</ex></ph>, <ph name="CHECKEDSTATE">$2s<ex>44 %</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_2f04f3e6eee339eeb0ddb6c39606424d" desc="Text for searching with regular expressinn">
+    Use Regular Expression
+  </message>
+  <message name="IDS_DEVTOOLS_31fde7b05ac8952dacf4af8a704074ec" desc="Text for previewing items">
+    Preview
+  </message>
+  <message name="IDS_DEVTOOLS_323d4eb70b252acb4a04eaf9e0882597" desc="Title for a group of cities">
+    Geolocation
+  </message>
+  <message name="IDS_DEVTOOLS_340641a167ad6da1bcb4016357f4695d" desc="Title for a type of source files">
+    Content scripts
+  </message>
+  <message name="IDS_DEVTOOLS_36917e785bd31d786ab9dd7790a9a4c2" desc="Text for a heap profile type">
+    JS Heap
+  </message>
+  <message name="IDS_DEVTOOLS_382b0f5185773fa0f67a8ed8056c7759" desc="Text for something not available">
+    N/A
+  </message>
+  <message name="IDS_DEVTOOLS_393c3f5ea8ad35c02691d507bdbb31b0" desc="Text for revealing an item in its destination">
+    Reveal
+  </message>
+  <message name="IDS_DEVTOOLS_3afbd9828e011526955ca93b48b57524" desc="Text for one or a group of screenshots">
+    Screenshot
+  </message>
+  <message name="IDS_DEVTOOLS_3bb3e8c8a24891ba0f7608bcc96f8b0a" desc="Text for a rendering frame">
+    Frame
+  </message>
+  <message name="IDS_DEVTOOLS_3e3f8a3abd60f2389b744ca8ed0aa4d9" desc="Text for no network throttling">
+    No throttling
+  </message>
+  <message name="IDS_DEVTOOLS_3ec365dd533ddb7ef3d1c111186ce872" desc="Text for the details of something">
+    Details
+  </message>
+  <message name="IDS_DEVTOOLS_3edf8ca26a1ec14dd6e91dd277ae1de6" desc="Text for the origin of something">
+    Origin
+  </message>
+  <message name="IDS_DEVTOOLS_3f03ed88ee58335aa3df453443b9c8bc" desc="Text to indicate the progress of a profile">
+    Profiling…
+  </message>
+  <message name="IDS_DEVTOOLS_3f8f88e3686b2345cecc9530e19e6172" desc="Text to store an HTML element or JavaScript variable or expression result as a global variable">
+    Store as global variable
+  </message>
+  <message name="IDS_DEVTOOLS_41fdb410354e76ef7674f98e1cc84c8f" desc="Text for throttling the network">
+    Throttling
+  </message>
+  <message name="IDS_DEVTOOLS_4252b72e6ebcd4d4b4c2e46a786f03d2" desc="Text for zooming in">
+    Zoom
+  </message>
+  <message name="IDS_DEVTOOLS_46a2a41cc6e552044816a2d04634545d" desc="The current state of an item">
+    State
+  </message>
+  <message name="IDS_DEVTOOLS_4789f23283b3a61f858b641a1bef19a3" desc="Text for the memory of the page">
+    Memory
+  </message>
+  <message name="IDS_DEVTOOLS_47bda3033cb8fe0e76c45c293db011b5" desc="Text to indicate there are no breakpoints">
+    No breakpoints
+  </message>
+  <message name="IDS_DEVTOOLS_482a4dca0bbd8fcdda5acc6f95f3c279" desc="Title of the DevTools">
+    DevTools
+  </message>
+  <message name="IDS_DEVTOOLS_49ee3087348e8d44e1feda1917443987" desc="Text for the name of something">
+    Name
+  </message>
+  <message name="IDS_DEVTOOLS_4bd7c2ff07dcc66801a9368957d4bff8" desc="Text for the initiator of something">
+    Initiator
+  </message>
+  <message name="IDS_DEVTOOLS_4c3880bb027f159e801041b1021e88e8" desc="Text for one or a group of functions">
+    Method
+  </message>
+  <message name="IDS_DEVTOOLS_4cf8e5f6ffbb182b5d480cbabae6a028" desc="Text to modify the attribute of an item">
+    Edit attribute
+  </message>
+  <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="Text to find an item">
+    Find
+  </message>
+  <message name="IDS_DEVTOOLS_4d1b0b75a9737b7dcdc3a15a84fe856b" desc="Text to indicate the searching is in progress">
+    Searching…
+  </message>
+  <message name="IDS_DEVTOOLS_4dab36ac83853282fc0d7bae20c19e90" desc="Text to show more options">
+    More options
+  </message>
+  <message name="IDS_DEVTOOLS_502996d9790340c5fd7b86a5b93b1c9f" desc="Text to show the priority of an item">
+    Priority
+  </message>
+  <message name="IDS_DEVTOOLS_5134111907df828fc575c69e22480c1e" desc="Text to hide an element">
+    Hide element
+  </message>
+  <message name="IDS_DEVTOOLS_51360304ea03557e79bdf5ff9cd2e234" desc="Text for the issuer of an item">
+    Issuer
+  </message>
+  <message name="IDS_DEVTOOLS_52b3bc5e77aa070243c36cd40a4d6b6d" desc="Text for autocompletion">
+    Autocompletion
+  </message>
+  <message name="IDS_DEVTOOLS_539dddc574d3cd85ba73df93df7a76d0" desc="Text for the execution stack trace">
+    Stack Trace
+  </message>
+  <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="Text to indicate the source of an image">
+    Image from <ph name="URL">$1s<ex>example.com</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_54f664c70c22054ea0d8d26fc3997ce7" desc="Text to indicate the network connectivity is online">
+    Online
+  </message>
+  <message name="IDS_DEVTOOLS_597b56e53847cd6a4712ac183f61fa68" desc="Text for web cookies">
+    Cookies
+  </message>
+  <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="Text to pretty print a file">
+    Pretty print
+  </message>
+  <message name="IDS_DEVTOOLS_5a0a64ecca63ba9a006b6397cbdc2b8c" desc="Text to go to a given line">
+    Go to line
+  </message>
+  <message name="IDS_DEVTOOLS_5b6cf869265c13af8566f192b4ab3d2a" desc="Text for the documentation of something">
+    Documentation
+  </message>
+  <message name="IDS_DEVTOOLS_5de39fa1bce4bbf9232597a2120bc4d4" desc="Text to open the cubic bezier editor">
+    Open cubic bezier editor.
+  </message>
+  <message name="IDS_DEVTOOLS_5ef0c737746fae2ca90e66c39333f8f6" desc="Text for errors">
+    Errors
+  </message>
+  <message name="IDS_DEVTOOLS_5f0ea62e5bc9f795512ef292ff162a2a" desc="Text to disable cache while DevTools is open">
+    Disable cache (while DevTools is open)
+  </message>
+  <message name="IDS_DEVTOOLS_5f8442a46861496e9d2a3d11be13692b" desc="Text to indicate DevTools is writing to a file">
+    Writing file…
+  </message>
+  <message name="IDS_DEVTOOLS_5fb63579fc981698f97d55bfecb213ea" desc="Text for copying">
+    Copy
+  </message>
+  <message name="IDS_DEVTOOLS_63041e09c8660107e507c9c27c08199c" desc="Text to expand something recursively">
+    Expand recursively
+  </message>
+  <message name="IDS_DEVTOOLS_6311ae17c1ee52b36e68aaf4ad066387" desc="Text for other types of items">
+    Other
+  </message>
+  <message name="IDS_DEVTOOLS_63a6a88c066880c5ac42394a22803ca6" desc="Text to refresh the page">
+    Refresh
+  </message>
+  <message name="IDS_DEVTOOLS_6525b37c568c526bde7c02fac8195c73" desc="Text for percentage">
+    <ph name="PERCENTAGE">$1.1f<ex>20.1</ex></ph> %%
+  </message>
+  <message name="IDS_DEVTOOLS_65b4c7424dd695c30efa73da8396c90c" desc="Title of the Profiler tool">
+    Profiler
+  </message>
+  <message name="IDS_DEVTOOLS_689202409e48743b914713f96d93947c" desc="Text for the value of something">
+    Value
+  </message>
+  <message name="IDS_DEVTOOLS_6a0d9eaee314c567fd72fb97ee707a36" desc="Text to record a series of actions for analysis">
+    Record
+  </message>
+  <message name="IDS_DEVTOOLS_6a26f548831e6a8c26bfbbd9f6ec61e0" desc="Text for the viewing the help options">
+    Help
+  </message>
+  <message name="IDS_DEVTOOLS_6adf97f83acf6453d4a6a4b1070f3754" desc="Text to show there is nothing">
+    None
+  </message>
+  <message name="IDS_DEVTOOLS_6ba3a9ac3e0d57683c56299484b7ee3b" desc="Text to remove all breakpoints">
+    Remove all breakpoints
+  </message>
+  <message name="IDS_DEVTOOLS_6bb61b1a929f2a0186f2671cd8258bd9" desc="Text to show something is not optimized">
+    Not optimized: <ph name="REASON">$1s<ex>Optimized too many times</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_6f6cb72d544962fa333e2e34ce64f719" desc="Text for the size of something">
+    Size
+  </message>
+  <message name="IDS_DEVTOOLS_74540c79e377bea903e1023a46df5574" desc="Text to open a file">
+    Open file
+  </message>
+  <message name="IDS_DEVTOOLS_787ae37366b7a8c53f381abfd315c647" desc="Text that refers to the Elements Panel">
+    Elements Panel
+  </message>
+  <message name="IDS_DEVTOOLS_7a2ccf251ecb20b2b84ce0e3c3f72a29" desc="Text to show something is secure">
+    Secure
+  </message>
+  <message name="IDS_DEVTOOLS_7b3a6b02f467b95f2b5267aa94708c07" desc="Text for the name of a thread of the page">
+    Thread <ph name="TID">$1s<ex>1</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_7d341c08fd102f0b86285b5ff2e26ea7" desc="Text with two placeholders separated by a colon">
+    <ph name="BREAKPOINT_TYPE_LABEL">$1s<ex>Node removed</ex></ph>: <ph name="LINKIFIED_CONTENT">$2s<ex>div#id1</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_8166a4b3fb4979da3a24ed21ced7fdf7" desc="Text for an option to learn more about something">
+    Learn more
+  </message>
+  <message name="IDS_DEVTOOLS_81aa2078d1eceede831b2976dbf32e62" desc="Text to clear everything">
+    Clear all
+  </message>
+  <message name="IDS_DEVTOOLS_84d0c431d1472a0609d69b39dcb3a287" desc="Text for the index of something">
+    (index)
+  </message>
+  <message name="IDS_DEVTOOLS_850985cd851d0fe440f03f77762e2590" desc="Text for the network request Content-Length header">
+    Content-Length
+  </message>
+  <message name="IDS_DEVTOOLS_86408593c34af77fdd90df932f8b5261" desc="Text for a programming function">
+    Function
+  </message>
+  <message name="IDS_DEVTOOLS_87bfda183c4f851a101e97bbb1bbace7" desc="Title of the Layers tool">
+    Layers
+  </message>
+  <message name="IDS_DEVTOOLS_87d17f4624a514e81dc7c8e016a7405c" desc="Text for the mobile platform, as opposed to desktop">
+    Mobile
+  </message>
+  <message name="IDS_DEVTOOLS_883d7615c4d2de3fa1218f1298c46d0e" desc="Text for network request headers">
+    Headers
+  </message>
+  <message name="IDS_DEVTOOLS_884680dd63eae99eab1a407133df66b7" desc="Text to view a security certificate">
+    View certificate
+  </message>
+  <message name="IDS_DEVTOOLS_888a77f5ac0748b6c8001822417df8b6" desc="Text for security or network protocol">
+    Protocol
+  </message>
+  <message name="IDS_DEVTOOLS_8d9da4bc0e49a50e09ac9f7e56789d39" desc="Text to indicate the network connectivity is offline">
+    Offline
+  </message>
+  <message name="IDS_DEVTOOLS_902b0d55fddef6f8d651fe1035b7d4bd" desc="Text for errors">
+    Error
+  </message>
+  <message name="IDS_DEVTOOLS_90da6f38945a1c7e7ba11e3adcbe6919" desc="Text for pausing the debugger on exceptions">
+    Pause on exceptions
+  </message>
+  <message name="IDS_DEVTOOLS_93898e12951c906e5286ccb36d980ce5" desc="Text for scripts that should not be stepped into when debugging">
+    Blackbox script
+  </message>
+  <message name="IDS_DEVTOOLS_939aaa05e0943b39eab3a34fd609384d" desc="Text to scroll the displayed content into view">
+    Scroll into view
+  </message>
+  <message name="IDS_DEVTOOLS_9446a98ad14416153cc4d45ab8b531bf" desc="Text for the performance of something">
+    Performance
+  </message>
+  <message name="IDS_DEVTOOLS_95bbad55f11c237ed89546e748093ba7" desc="Text for the request animation frame event">
+    Request Animation Frame
+  </message>
+  <message name="IDS_DEVTOOLS_96b0141273eabab320119c467cdcaf17" desc="Text for sum">
+    Total
+  </message>
+  <message name="IDS_DEVTOOLS_96e9bc575b5d3ed541113a249da8bd24" desc="Text to take screenshots">
+    Capture screenshots
+  </message>
+  <message name="IDS_DEVTOOLS_997a8c473db4f81c5fb3d5900030d44d" desc="Text that shows there is no recording">
+    (no recordings)
+  </message>
+  <message name="IDS_DEVTOOLS_9aae9fe27dbf2db0ad90762b5b59d3a7" desc="Text to clear the console">
+    Clear console
+  </message>
+  <message name="IDS_DEVTOOLS_9d8c209e49e328528c39c273798e98c9" desc="Text to save content as a specific file type">
+    Save as...
+  </message>
+  <message name="IDS_DEVTOOLS_9df22f196a33acd0b372fe502de51211" desc="Text short for automatic">
+    auto
+  </message>
+  <message name="IDS_DEVTOOLS_9dffbf69ffba8bc38bc4e01abf4b1675" desc="Generic label for any text">
+    Text
+  </message>
+  <message name="IDS_DEVTOOLS_9e65b51e82f2a9b9f72ebe3e083582bb" desc="Text to show an item is empty">
+    (empty)
+  </message>
+  <message name="IDS_DEVTOOLS_9f29da220ed82809ec5dd70af4e52904" desc="Text for the total time of something">
+    Total Time
+  </message>
+  <message name="IDS_DEVTOOLS_a02c83a7dbd96295beaefb72c2bee2de" desc="Text that refers to the main target">
+    Main
+  </message>
+  <message name="IDS_DEVTOOLS_a1c58e94227389415de133efdf78ea6e" desc="Text for DevTools appearance">
+    Appearance
+  </message>
+  <message name="IDS_DEVTOOLS_a1fa27779242b4902f7ae3bdd5c6d508" desc="Text that refers to some types">
+    Type
+  </message>
+  <message name="IDS_DEVTOOLS_a2e4822a98337283e39f7b60acf85ec9" desc="Text to show an item is empty">
+    empty
+  </message>
+  <message name="IDS_DEVTOOLS_a3d5de3eac8bb00ae86fd1a1005f1500" desc="Text for timestamps of items">
+    Timestamp
+  </message>
+  <message name="IDS_DEVTOOLS_a4ecfc70574394990cf17bd83df499f7" desc="Text that refers to some events">
+    Event
+  </message>
+  <message name="IDS_DEVTOOLS_a6e8f9aed2ac6481dc25a18a33342d03" desc="Title of the Rendering tool">
+    Rendering
+  </message>
+  <message name="IDS_DEVTOOLS_a76d4ef5f3f6a672bbfab2865563e530" desc="Text that refers to the time">
+    Time
+  </message>
+  <message name="IDS_DEVTOOLS_aa56a2e65d8106aef3c61e4f6bf94fdb" desc="Title of the Elements Panel">
+    Elements
+  </message>
+  <message name="IDS_DEVTOOLS_aab112fba39c10ed5df335ae0e47f329" desc="Text that indicates something is not optimized">
+    Not optimized
+  </message>
+  <message name="IDS_DEVTOOLS_ab57fd0432e25d5b3013133a1c910d56" desc="A unit">
+    KB
+  </message>
+  <message name="IDS_DEVTOOLS_abbd64f40c34c537d3a571af068fce29" desc="Text for the orientation of something">
+    Orientation
+  </message>
+  <message name="IDS_DEVTOOLS_ac70412e939d72a9234cdebb1af5867b" desc="Text that refers to a file path">
+    Path
+  </message>
+  <message name="IDS_DEVTOOLS_acc24772ac31677d076f17d9002b57cd" desc="Text to collapse children of a parent group">
+    Collapse children
+  </message>
+  <message name="IDS_DEVTOOLS_af4bb376939e77df0e7c2332b837a866" desc="Text that refers to closure as a programming term">
+    Closure
+  </message>
+  <message name="IDS_DEVTOOLS_af9ccba3ec4346e3acf785f9bea514d8" desc="Text to show a tool or panel">
+    Show <ph name="EXTENSION_TITLE">$1s<ex>Audits</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_afb4ea732ebcf8bd51a3d99a1b8909a8" desc="Text to show something is linked to another">
+    Linked to <ph name="PATH">$1s<ex>example.url</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_b1c94ca2fbc3e78fc30069c8d0f01680" desc="Text for everything">
+    All
+  </message>
+  <message name="IDS_DEVTOOLS_b1d75786654fa93f10c31c3b544bbd03" desc="Text to run a code snippet">
+    Run snippet
+  </message>
+  <message name="IDS_DEVTOOLS_b2844b8e17ecaaeae68d018fe9418af0" desc="Text to indicate the expiry date">
+    Valid until
+  </message>
+  <message name="IDS_DEVTOOLS_b4e79b551a1ceae24b7de243ab1fd27c" desc="Text to add a breakpoint">
+    Add breakpoint
+  </message>
+  <message name="IDS_DEVTOOLS_b5a7adde1af5c87d7fd797b6245c2a39" desc="Text for the description of something">
+    Description
+  </message>
+  <message name="IDS_DEVTOOLS_b6434258c743f8673997b5aeb3721c27" desc="Text that refers to the network request method">
+    Request Method
+  </message>
+  <message name="IDS_DEVTOOLS_b94d8a074eddd267702810179875737f" desc="Text that refers to the debugger">
+    Debugger
+  </message>
+  <message name="IDS_DEVTOOLS_b9dee6bade160c89fb7f0e539d453513" desc="Text to dock the DevTools to the bottom of the browser tab">
+    Dock to bottom
+  </message>
+  <message name="IDS_DEVTOOLS_b9f5c797ebbf55adccdd8539a65a0241" desc="Text to indicate something is not enabled">
+    Disabled
+  </message>
+  <message name="IDS_DEVTOOLS_ba5b676ccf658f863ef2e3df082ee262" desc="Text for the event that an animation frame is fired">
+    Animation Frame Fired
+  </message>
+  <message name="IDS_DEVTOOLS_bc28aa52ba5b534ad9d198157c375d67" desc="Text to clear storage of the web page">
+    Clear storage
+  </message>
+  <message name="IDS_DEVTOOLS_bc955333ff170762be4971a8fde558cf" desc="Title of the WebAudio tool">
+    WebAudio
+  </message>
+  <message name="IDS_DEVTOOLS_bccaa4aa80831b76c11240a16447975f" desc="Title of the Console tool">
+    Console
+  </message>
+  <message name="IDS_DEVTOOLS_be8545ae7ab0276e15898aae7acfbd7a" desc="Text that refers to the resources of the web page">
+    Resource
+  </message>
+  <message name="IDS_DEVTOOLS_c03ca67dda321195d74c951097f240c6" desc="Title of the Devices tab">
+    Devices
+  </message>
+  <message name="IDS_DEVTOOLS_c2cc7082a89c1ad6631a2f66af5f00c0" desc="Text that refers to the network connection">
+    Connection
+  </message>
+  <message name="IDS_DEVTOOLS_c3fe109bf99ade2d76a55e5737015e3e" desc="Text to stop preventing the debugger from stepping into library code">
+    Stop blackboxing
+  </message>
+  <message name="IDS_DEVTOOLS_c74ea6dbff701bfa23819583c52ebd97" desc="Text to show less content">
+    Show less
+  </message>
+  <message name="IDS_DEVTOOLS_c7892ebbb139886662c6f2fc8c450710" desc="Text that refers to the subject of a security certificate">
+    Subject
+  </message>
+  <message name="IDS_DEVTOOLS_c949475bc69a57c419ac976fe8870652" desc="Text to search by matching case of the input">
+    Match Case
+  </message>
+  <message name="IDS_DEVTOOLS_c9ad95228aa735bdda1aebf38da022af" desc="Text to parse something">
+    Parse
+  </message>
+  <message name="IDS_DEVTOOLS_c9cc8cce247e49bae79f15173ce97354" desc="Text to save something">
+    Save
+  </message>
+  <message name="IDS_DEVTOOLS_c9deece3e6de26d07ef6409b96f21fd0" desc="Title of Blackboxing settings">
+    Blackboxing
+  </message>
+  <message name="IDS_DEVTOOLS_ce82e07fa1f0521f5cee30e368fe2e73" desc="Text that starts with a colon and includes a placeholder">
+    : <ph name="AA_NUMBER">$1s<ex>3.0</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_d31827f0a164d52b636bb1f71ca4a351" desc="Text to cancel the animation frame">
+    Cancel Animation Frame
+  </message>
+  <message name="IDS_DEVTOOLS_d3d2e617335f08df83599665eef8a418" desc="Text to close something">
+    Close
+  </message>
+  <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc="Text that is usually a hyperlink to more documentation">
+    Learn more
+  </message>
+  <message name="IDS_DEVTOOLS_d5bfaaca8e28f8b9b9211038f86a4494" desc="Text to remove a breakpoint">
+    Remove breakpoint
+  </message>
+  <message name="IDS_DEVTOOLS_d64ed3e9c10229648e069f56e32f4c8e" desc="Text for a network response">
+    Response
+  </message>
+  <message name="IDS_DEVTOOLS_d6b6b668dbca9d4fe774bb654226ebe3" desc="Text that refers to the animation of the web page">
+    Animation
+  </message>
+  <message name="IDS_DEVTOOLS_d7778d0c64b6ba21494c97f77a66885a" desc="Text to filter result items">
+    Filter
+  </message>
+  <message name="IDS_DEVTOOLS_dc30bc0c7914db5918da4263fce93ad2" desc="Text to clear content">
+    Clear
+  </message>
+  <message name="IDS_DEVTOOLS_e02d2ae03de9d493df2b6b2d2813d302" desc="Text for the duration of something">
+    Duration
+  </message>
+  <message name="IDS_DEVTOOLS_e0ac20adce6ffee48c7151b070aa5737" desc="Text that refers to device such as a phone">
+    Device
+  </message>
+  <message name="IDS_DEVTOOLS_e0e4fc6213e8b3593495a7260c3a4c2e" desc="Text for accessibility of the web page">
+    Accessibility
+  </message>
+  <message name="IDS_DEVTOOLS_e24ee2487879116dcab772c0ac4fe341" desc="Text to focus on something">
+    Focus
+  </message>
+  <message name="IDS_DEVTOOLS_e55f75a29310d7b60f7ac1d390c8ae42" desc="Text for a module, the programming concept">
+    Module
+  </message>
+  <message name="IDS_DEVTOOLS_e576c23d915755d83e2d1f47bd9f6c22" desc="Text to show no results have been found">
+    No results found
+  </message>
+  <message name="IDS_DEVTOOLS_e6b391a8d2c4d45902a23a8b6585703d" desc="Text for web URLs">
+    URL
+  </message>
+  <message name="IDS_DEVTOOLS_e77fef0167598bb39846637ac3915f4e" desc="Text to clear everything">
+    Clear All
+  </message>
+  <message name="IDS_DEVTOOLS_ea4788705e6873b424c65e91c2846b19" desc="Text to cancel something">
+    Cancel
+  </message>
+  <message name="IDS_DEVTOOLS_eae639a70006feff484a39363c977e24" desc="Text for the domain of a website">
+    Domain
+  </message>
+  <message name="IDS_DEVTOOLS_eb0f48a107df1a0f343d4cd513b555e6" desc="Text for a security certificate">
+    Certificate
+  </message>
+  <message name="IDS_DEVTOOLS_eb902cf204f3e4dfffeb56d92a9b5c26" desc="Text to show since when an item is valid">
+    Valid from
+  </message>
+  <message name="IDS_DEVTOOLS_ec211f7c20af43e742bf2570c3cb84f9" desc="Text to add something">
+    Add
+  </message>
+  <message name="IDS_DEVTOOLS_ec53a8c4f07baed5d8825072c89799be" desc="Text for the status of something">
+    Status
+  </message>
+  <message name="IDS_DEVTOOLS_edd24cce7afedea5a1b2f90675880687" desc="Text to preserve the log after refreshing">
+    Preserve log
+  </message>
+  <message name="IDS_DEVTOOLS_ee33e909372d935d190f4fcb2a92d542" desc="The milisecond unit">
+    ms
+  </message>
+  <message name="IDS_DEVTOOLS_eec89088ee408b80387155272b113256" desc="Title of the Network tool">
+    Network
+  </message>
+  <message name="IDS_DEVTOOLS_ef95393ad48336d7c3543625354a3d56" desc="Text to highlight the rendering frames for ads">
+    Highlight ad frames
+  </message>
+  <message name="IDS_DEVTOOLS_f0f31c9700c6b10d8a20dc487b2ae6a8" desc="Text for the touch type to simulate on a device">
+    Touch
+  </message>
+  <message name="IDS_DEVTOOLS_f19dbf2edb3a0bd74b0524d960ff21eb" desc="Text to load something">
+    Load
+  </message>
+  <message name="IDS_DEVTOOLS_f28128b38efbc6134dc40751ee21fd29" desc="Text for documents, a type of resources">
+    Documents
+  </message>
+  <message name="IDS_DEVTOOLS_f2a6c498fb90ee345d997f888fce3b18" desc="Text to delete something">
+    Delete
+  </message>
+  <message name="IDS_DEVTOOLS_f31bbdd1b3e85bccd652680e16935819" desc="Text for the source of something">
+    Source
+  </message>
+  <message name="IDS_DEVTOOLS_f4f70727dc34561dfde1a3c529b6205c" desc="Title for a setting">
+    Settings
+  </message>
+  <message name="IDS_DEVTOOLS_f53944c3a55bdb5ad65c6226e358a626" desc="Text to undock the DevTools">
+    Undock into separate window
+  </message>
+  <message name="IDS_DEVTOOLS_f907e651164789346ae0a1e257c462d8" desc="Label for a group of JavaScript files">
+    Script
+  </message>
+  <message name="IDS_DEVTOOLS_fa6711f918fe2018131a4ad0380b9e56" desc="Name of an item from source map">
+    <ph name="DISPLAY_NAME">$1s<ex>compile.html</ex></ph> (from source map)
+  </message>
+  <message name="IDS_DEVTOOLS_fb61758d0f0fda4ba867c3d5a46c16a7" desc="Name of the Sources panel">
+    Sources
+  </message>
+  <message name="IDS_DEVTOOLS_fdbd92f0c6b67291ca954b74885d434e" desc="Name of a profile">
+    Profile <ph name="NUMBER">$1d<ex>2</ex></ph>
+  </message>
+  <message name="IDS_DEVTOOLS_fe7fb037b290768d6a6be30b237e183d" desc="Text to dock the DevTools to the right of the browser tab">
+    Dock to right
+  </message>
+</grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp b/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
index 45c92a3f..f3daa15 100644
--- a/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
@@ -33,9 +33,6 @@
   <message name="IDS_DEVTOOLS_2a2924d1d77c00d27ce2509c34861804" desc="Text in Layer Details View of the Layers panel">
     Layer for clip.
   </message>
-  <message name="IDS_DEVTOOLS_2ae207ddfe5cd256a768769d93a879e5" desc="Paint profiler button text content in Layer Details View of the Layers panel">
-    Paint Profiler
-  </message>
   <message name="IDS_DEVTOOLS_2ca2308d45c04266f0fb51786e407287" desc="Text in Layer Details View of the Layers panel">
     Composition due to association with an element with CSS filters applied and composited descendants.
   </message>
@@ -48,9 +45,6 @@
   <message name="IDS_DEVTOOLS_398b889c147f3b2cb3c674cfb07315b5" desc="Text in Layer Details View of the Layers panel">
     Composition due to association with an element with opacity applied and composited descendants.
   </message>
-  <message name="IDS_DEVTOOLS_3f03ed88ee58335aa3df453443b9c8bc" desc="Progress banner text content in Paint Profiler View of the Layers panel">
-    Profiling…
-  </message>
   <message name="IDS_DEVTOOLS_441f5e043a240bac8dca50f90f7be3de" desc="Text in DView of the Layers panel">
     repaints on scroll
   </message>
@@ -138,9 +132,6 @@
   <message name="IDS_DEVTOOLS_9b8379825de60ccb900acf83934e1409" desc="Text in Layer View Host of the Layers panel">
     Show internal layers
   </message>
-  <message name="IDS_DEVTOOLS_9dffbf69ffba8bc38bc4e01abf4b1675" desc="Text in Paint Profiler View of the Layers panel">
-    Text
-  </message>
   <message name="IDS_DEVTOOLS_a673813c8d6c5f511cc4d80830fc4503" desc="Text in DView of the Layers panel">
     Can&apos;t display layers,
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp b/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
index 47b78385..3e094772 100644
--- a/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
@@ -1,9 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_3ec365dd533ddb7ef3d1c111186ce872" desc="Text in Layers Panel of the Layers panel">
-    Details
-  </message>
-  <message name="IDS_DEVTOOLS_87bfda183c4f851a101e97bbb1bbace7" desc="Title of the 'Layers' tool">
-    Layers
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp b/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
index 7f943da..72ae39e 100644
--- a/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
@@ -9,9 +9,6 @@
   <message name="IDS_DEVTOOLS_0a0afb342478f201b92cbc89d19bf14d" desc="Title of a setting under the Appearance category that can be invoked through the Command Menu">
     Switch to dark theme
   </message>
-  <message name="IDS_DEVTOOLS_13348442cc6a27032d2b4aa28b75a5d3" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut">
-    Search
-  </message>
   <message name="IDS_DEVTOOLS_15fa1acc2a998159c4ed2a950c5c231d" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut">
     Toggle drawer
   </message>
@@ -21,9 +18,6 @@
   <message name="IDS_DEVTOOLS_1cf59b16fd253d6ff4bbee7c237cea0d" desc="Text in Main">
     Show console
   </message>
-  <message name="IDS_DEVTOOLS_2ab5656e27a0ed871c8de44368f807c6" desc="Text in Main">
-    Styles Pane
-  </message>
   <message name="IDS_DEVTOOLS_2ad9d63b69c4a10a5cc9cad923133bc4" desc="A drop-down menu option to dock to bottom">
     Bottom
   </message>
@@ -69,9 +63,6 @@
   <message name="IDS_DEVTOOLS_75def4784fa71c4ccde7762316ed0e3e" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut in the Section">
     Find next/previous
   </message>
-  <message name="IDS_DEVTOOLS_787ae37366b7a8c53f381abfd315c647" desc="Text in Main">
-    Elements Panel
-  </message>
   <message name="IDS_DEVTOOLS_8645bf45e76c3f958ae99c114c419743" desc="Text in Main">
     Hide console drawer
   </message>
@@ -111,9 +102,6 @@
   <message name="IDS_DEVTOOLS_b8da6df14bf06283cbf588df6998722e" desc="A title of the 'Panel' @UI.ViewLocationResolver category">
     Panel
   </message>
-  <message name="IDS_DEVTOOLS_b94d8a074eddd267702810179875737f" desc="Text in Main">
-    Debugger
-  </message>
   <message name="IDS_DEVTOOLS_b9cd538a753713464d2ea17d7e975041" desc="A context menu item in the Main">
     More tools
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp b/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
index f7d0938e..ad5f9a0 100644
--- a/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
@@ -12,9 +12,6 @@
   <message name="IDS_DEVTOOLS_17f66753218a6a1e2762c6a60db3d7c4" desc="Text in Throttling Presets of the Network panel">
     Mid-tier mobile
   </message>
-  <message name="IDS_DEVTOOLS_26ae7bdd1d6fb8c4886e6fde8d12601c" desc="Text in Throttling Settings Tab of the Network panel">
-    Latency
-  </message>
   <message name="IDS_DEVTOOLS_275e2c1079aeffdb5f4e22580127b95b" desc="Text in Throttling Settings Tab of the Network panel">
     <ph name="CONDITIONS_LATENCY">$1d<ex>3</ex></ph>ms
   </message>
@@ -42,9 +39,6 @@
   <message name="IDS_DEVTOOLS_8493534a13107469ea63be99410bebfa" desc="Title of an action in the network conditions tool to network low end mobile">
     Enable slow 3G throttling
   </message>
-  <message name="IDS_DEVTOOLS_8d9da4bc0e49a50e09ac9f7e56789d39" desc="Text in Throttling Manager of the Network panel">
-    Offline
-  </message>
   <message name="IDS_DEVTOOLS_8fd93ea382b6642f13ff291b76f5bc85" desc="Text in Throttling Settings Tab of the Network panel">
     Profile Name
   </message>
@@ -87,9 +81,6 @@
   <message name="IDS_DEVTOOLS_eb81441fe20963ff9e8e69c5b32fc625" desc="Text in Mobile Throttling Selector of the Network panel">
     Presets
   </message>
-  <message name="IDS_DEVTOOLS_ee33e909372d935d190f4fcb2a92d542" desc="Text in Throttling Settings Tab of the Network panel">
-    ms
-  </message>
   <message name="IDS_DEVTOOLS_f410c3f1a07f566591283f599701e4ab" desc="Text in Throttling Manager of the Network panel">
     Add…
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp b/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
index 5c131ff7..9f2efcf 100644
--- a/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
@@ -36,9 +36,6 @@
   <message name="IDS_DEVTOOLS_0db377921f4ce762c62526131097968f" desc="Text in Request Headers View of the Network panel">
     General
   </message>
-  <message name="IDS_DEVTOOLS_0f44e9e39cbe2f22bd1bd7b6070cf13d" desc="Text in Blocked URLs Pane of the Network panel">
-    Enable request blocking
-  </message>
   <message name="IDS_DEVTOOLS_0f591b1d87c91e77d4fa11dc6e44288c" desc="Text in Network Item View of the Network panel">
     Request and response timeline
   </message>
@@ -54,9 +51,6 @@
   <message name="IDS_DEVTOOLS_12881f9e98bb240671bc3e1787d64a03" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
     Color code by resource type
   </message>
-  <message name="IDS_DEVTOOLS_16f78b9465f03f7ec5a03c24918fbde3" desc="Text in Request Headers View of the Network panel">
-    Status Code
-  </message>
   <message name="IDS_DEVTOOLS_1854180b02f297deebed0ec452090842" desc="Cell title in Network Data Grid Node of the Network panel">
     Served from memory cache, resource size: <ph name="RESOURCESIZE">$1s<ex>50 B</ex></ph>
   </message>
@@ -99,9 +93,6 @@
   <message name="IDS_DEVTOOLS_29d37bdcfeb74d25d56bcf841866ae32" desc="Cell title in Network Data Grid Node of the Network panel">
     Served from ServiceWorker, resource size: <ph name="RESOURCESIZE">$1s<ex>4 B</ex></ph>
   </message>
-  <message name="IDS_DEVTOOLS_2bbc845892f400626baab5af687527c5" desc="Text in Network Log View Columns of the Network panel">
-    Start Time
-  </message>
   <message name="IDS_DEVTOOLS_2d13df6f8b5e4c5af9f87e0dc39df69d" desc="Text in Network Data Grid Node of the Network panel">
     Pending
   </message>
@@ -117,9 +108,6 @@
   <message name="IDS_DEVTOOLS_31977081ea2c828cc70e6151ab5d7da8" desc="Text in Request Headers View of the Network panel">
     view decoded
   </message>
-  <message name="IDS_DEVTOOLS_31fde7b05ac8952dacf4af8a704074ec" desc="Text in Network Item View of the Network panel">
-    Preview
-  </message>
   <message name="IDS_DEVTOOLS_336439019ce67912717a20d54298bf24" desc="Text in Request Timing View of the Network panel">
     Receiving Push
   </message>
@@ -198,12 +186,6 @@
   <message name="IDS_DEVTOOLS_4a7ba0d17eafde708ca8f5f34debcfef" desc="Text in Network Log View of the Network panel">
     <ph name="TRANSFERSIZE">$1s<ex>4</ex></ph> B transferred
   </message>
-  <message name="IDS_DEVTOOLS_4bd7c2ff07dcc66801a9368957d4bff8" desc="Text in Network Log View Columns of the Network panel">
-    Initiator
-  </message>
-  <message name="IDS_DEVTOOLS_4c3880bb027f159e801041b1021e88e8" desc="Text in Network Log View Columns of the Network panel">
-    Method
-  </message>
   <message name="IDS_DEVTOOLS_4dea2ac78e9450e62e96c166ef9f5d4c" desc="Text in Network Log View Columns of the Network panel">
     Manage Header Columns…
   </message>
@@ -216,15 +198,9 @@
   <message name="IDS_DEVTOOLS_5023e5b1d1c02cf168a9a67dda6d2d87" desc="Text in Network Panel of the Network panel">
     Show overview
   </message>
-  <message name="IDS_DEVTOOLS_502996d9790340c5fd7b86a5b93b1c9f" desc="Text in Network Log View Columns of the Network panel">
-    Priority
-  </message>
   <message name="IDS_DEVTOOLS_5101cdda28ea3097ac00cdbfdcedc353" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
     Use default colors
   </message>
-  <message name="IDS_DEVTOOLS_51360304ea03557e79bdf5ff9cd2e234" desc="Text in Signed Exchange Info View of the Network panel">
-    Issuer
-  </message>
   <message name="IDS_DEVTOOLS_53fa249ce3d02c8a686b657b31d02ee7" desc="Text in Network Log View of the Network panel">
     Copy response
   </message>
@@ -246,18 +222,12 @@
   <message name="IDS_DEVTOOLS_59535aed1e49266dfd0b93172f5a7242" desc="Text in Network Panel of the Network panel">
     Group by frame
   </message>
-  <message name="IDS_DEVTOOLS_597b56e53847cd6a4712ac183f61fa68" desc="Text in Network Item View of the Network panel">
-    Cookies
-  </message>
   <message name="IDS_DEVTOOLS_5cb98890f19c13e5fce52287187d9803" desc="Text in Network Log View of the Network panel">
     <ph name="SELECTEDNODENUMBER">$1s<ex>3</ex></ph> / <ph name="NODECOUNT">$2s<ex>5</ex></ph> requests
   </message>
   <message name="IDS_DEVTOOLS_5e2f683aacb9d5f3635b3f88583dec80" desc="Text in Network Config View of the Network panel">
     Custom...
   </message>
-  <message name="IDS_DEVTOOLS_5f0ea62e5bc9f795512ef292ff162a2a" desc="Tooltip text that appears on the setting when hovering over it in Network Panel of the Network panel">
-    Disable cache (while DevTools is open)
-  </message>
   <message name="IDS_DEVTOOLS_5f903b8316b9649547e1b3ceef934183" desc="Title of an action in the network tool to toggle recording">
     Stop recording network log
   </message>
@@ -267,9 +237,6 @@
   <message name="IDS_DEVTOOLS_619d32de7168c6e770464dfc43e374d1" desc="Text in Request Headers View of the Network panel">
     Request Headers
   </message>
-  <message name="IDS_DEVTOOLS_6311ae17c1ee52b36e68aaf4ad066387" desc="Cell title in Network Data Grid Node of the Network panel">
-    Other
-  </message>
   <message name="IDS_DEVTOOLS_6490fac2ddb40e1e2a7e0c43fb661c7b" desc="Text in Request Preview View of the Network panel">
     Failed to load response data
   </message>
@@ -351,18 +318,12 @@
   <message name="IDS_DEVTOOLS_814f9c3c7e7aa04c21f2e61f5b2dcf18" desc="Text in Network Log View of the Network panel">
     Copy response headers
   </message>
-  <message name="IDS_DEVTOOLS_8166a4b3fb4979da3a24ed21ced7fdf7" desc="Text in Signed Exchange Info View of the Network panel">
-    Learn more
-  </message>
   <message name="IDS_DEVTOOLS_827452688eed02a12178e96f924ac529" desc="Text in Network Log View Columns of the Network panel">
     Scheme
   </message>
   <message name="IDS_DEVTOOLS_838c672414343cdd527a63d910fb132c" desc="Text in Network Log View of the Network panel">
     Hide data URLs
   </message>
-  <message name="IDS_DEVTOOLS_850985cd851d0fe440f03f77762e2590" desc="Text in Network Log View Columns of the Network panel">
-    Content-Length
-  </message>
   <message name="IDS_DEVTOOLS_8644fe7afb1a31ea7274f5ee90dff50b" desc="Text in Request Headers View of the Network panel">
     view URL encoded
   </message>
@@ -372,15 +333,6 @@
   <message name="IDS_DEVTOOLS_881e9a305ce80960413ab7f227ef879e" desc="Text in Network Config View of the Network panel">
     User agent
   </message>
-  <message name="IDS_DEVTOOLS_883d7615c4d2de3fa1218f1298c46d0e" desc="Text in Network Item View of the Network panel">
-    Headers
-  </message>
-  <message name="IDS_DEVTOOLS_884680dd63eae99eab1a407133df66b7" desc="View cert link text content in Signed Exchange Info View of the Network panel">
-    View certificate
-  </message>
-  <message name="IDS_DEVTOOLS_888a77f5ac0748b6c8001822417df8b6" desc="Text in Network Log View Columns of the Network panel">
-    Protocol
-  </message>
   <message name="IDS_DEVTOOLS_889f316cd1f0ac68f8ea3052e8568061" desc="Text in Network Log View of the Network panel">
     Copy as PowerShell
   </message>
@@ -438,15 +390,9 @@
   <message name="IDS_DEVTOOLS_94966d90747b97d1f0f206c98a8b1ac3" desc="Text in Resource Web Socket Frame View of the Network panel">
     Send
   </message>
-  <message name="IDS_DEVTOOLS_96b0141273eabab320119c467cdcaf17" desc="Text in Request Timing View of the Network panel">
-    Total
-  </message>
   <message name="IDS_DEVTOOLS_96d960cc2b3394824ebfbf25bb960a90" desc="Text in Resource Web Socket Frame View of the Network panel">
     <ph name="LOCALIZEDDESCRIPTION">$1s<ex>Text Message</ex></ph> (Opcode <ph name="OPCODE">$2s<ex>0</ex></ph>, mask)
   </message>
-  <message name="IDS_DEVTOOLS_96e9bc575b5d3ed541113a249da8bd24" desc="Text in Network Panel of the Network panel">
-    Capture screenshots
-  </message>
   <message name="IDS_DEVTOOLS_97b7320892b0db86ff1d8dc28ba1af95" desc="Text in Network Log View of the Network panel">
     Are you sure you want to clear browser cache?
   </message>
@@ -483,9 +429,6 @@
   <message name="IDS_DEVTOOLS_9e08e91089d39bc26c4c57e9780c2f60" desc="Text in Request Headers View of the Network panel">
     (from memory cache)
   </message>
-  <message name="IDS_DEVTOOLS_9e65b51e82f2a9b9f72ebe3e083582bb" desc="Text in Request Headers View of the Network panel">
-    (empty)
-  </message>
   <message name="IDS_DEVTOOLS_9ffaf77e2c524827dff95993361e7115" desc="Text in Network Item View of the Network panel">
     Raw response data
   </message>
@@ -519,9 +462,6 @@
   <message name="IDS_DEVTOOLS_a74e6894e1f36ce12a6773b9a6b9aea8" desc="Text in Network Log View of the Network panel">
     <ph name="NODECOUNT">$1s<ex>6</ex></ph> requests
   </message>
-  <message name="IDS_DEVTOOLS_a76d4ef5f3f6a672bbfab2865563e530" desc="Text in Event Source Messages View of the Network panel">
-    Time
-  </message>
   <message name="IDS_DEVTOOLS_a976624c5265b8187b19aea9df9230eb" desc="Title of a setting under the Network category in Settings">
     Color-code resource types
   </message>
@@ -552,15 +492,9 @@
   <message name="IDS_DEVTOOLS_b1f63146853f7f450d8622aae6a73408" desc="Text in Network Log View of the Network panel">
     Copy as cURL (bash)
   </message>
-  <message name="IDS_DEVTOOLS_b2844b8e17ecaaeae68d018fe9418af0" desc="Text in Signed Exchange Info View of the Network panel">
-    Valid until
-  </message>
   <message name="IDS_DEVTOOLS_b4774747599df05309e1de2e2734dd3e" desc="Text in Request Timing View of the Network panel">
     Request to ServiceWorker
   </message>
-  <message name="IDS_DEVTOOLS_b6434258c743f8673997b5aeb3721c27" desc="Text in Request Headers View of the Network panel">
-    Request Method
-  </message>
   <message name="IDS_DEVTOOLS_b72ac10807b29c77f5b7e4b80ea40414" desc="Text in Request Timing View of the Network panel">
     Explanation
   </message>
@@ -594,9 +528,6 @@
   <message name="IDS_DEVTOOLS_c0c7145bdb8a2311e11528eaacf7f41d" desc="Tooltip to explain what request cookies are">
     Cookies that were sent to the server in the &apos;cookie&apos; header of the request
   </message>
-  <message name="IDS_DEVTOOLS_c2cc7082a89c1ad6631a2f66af5f00c0" desc="Text in Network Log View Columns of the Network panel">
-    Connection
-  </message>
   <message name="IDS_DEVTOOLS_c3c14eb17a6cf9c6120f381790ed06eb" desc="Text in Network Log View of the Network panel">
     Copy all as PowerShell
   </message>
@@ -609,9 +540,6 @@
   <message name="IDS_DEVTOOLS_c6f969f563d21beac9731f177053484c" desc="Text in Network Log View of the Network panel">
     <ph name="SELECTEDRESOURCESIZE">$1s<ex>40</ex></ph> B / <ph name="RESOURCESIZE">$2s<ex>50</ex></ph> B resources
   </message>
-  <message name="IDS_DEVTOOLS_c7892ebbb139886662c6f2fc8c450710" desc="Text in Signed Exchange Info View of the Network panel">
-    Subject
-  </message>
   <message name="IDS_DEVTOOLS_c81e295bfd7fbaec6257ea14992f4643" desc="Text in Network Item View of the Network panel">
     Request and response cookies
   </message>
@@ -648,9 +576,6 @@
   <message name="IDS_DEVTOOLS_d3b69e993f4e9bf9c479c7e794ede387" desc="Text in Network Item View of the Network panel">
     Timing
   </message>
-  <message name="IDS_DEVTOOLS_d64ed3e9c10229648e069f56e32f4c8e" desc="Text in Network Item View of the Network panel">
-    Response
-  </message>
   <message name="IDS_DEVTOOLS_d76e44f856d0114826e7436a630a3fa7" desc="Text of a DOM element in Network Data Grid Node of the Network panel">
     (signed-exchange)
   </message>
@@ -666,9 +591,6 @@
   <message name="IDS_DEVTOOLS_db67b2de0114bd82fe1383aa067fa6b2" desc="A context menu item in the Network Log View of the Network panel">
     Unblock <ph name="CROPPEDURL">$1s<ex>example.com</ex></ph>
   </message>
-  <message name="IDS_DEVTOOLS_dc30bc0c7914db5918da4263fce93ad2" desc="Tooltip text that appears when hovering over the largeicon clear button in the Network Panel of the Network panel">
-    Clear
-  </message>
   <message name="IDS_DEVTOOLS_dc5d60b066d9a30e68dd648dcabf8579" desc="Text in Request Cookies View of the Network panel">
     This request has no cookies.
   </message>
@@ -693,9 +615,6 @@
   <message name="IDS_DEVTOOLS_df080c10e2e9f1e98c180fe2645f6132" desc="Text in Request Headers View of the Network panel">
     Request URL
   </message>
-  <message name="IDS_DEVTOOLS_e02d2ae03de9d493df2b6b2d2813d302" desc="Text that labels the length of time a network request took.">
-    Duration
-  </message>
   <message name="IDS_DEVTOOLS_e12d71bcdc8fd61f60b6fdccb4b5fedd" desc="Latency download total format in Network Time Calculator of the Network panel">
     <ph name="PH1">$1s<ex>20ms</ex></ph> latency, <ph name="PH2">$2s<ex>20ms</ex></ph> download (<ph name="PH3">$3s<ex>40ms</ex></ph> total)
   </message>
@@ -717,24 +636,12 @@
   <message name="IDS_DEVTOOLS_e6fb9da54f521b9c33d41121d4fcd35c" desc="Text of a DOM element in Network Data Grid Node of the Network panel">
     (memory cache)
   </message>
-  <message name="IDS_DEVTOOLS_e77fef0167598bb39846637ac3915f4e" desc="Tooltip text that appears when hovering over the largeicon clear button in the Resource Web Socket Frame View of the Network panel">
-    Clear All
-  </message>
   <message name="IDS_DEVTOOLS_ea52c36203c5f99c3ce2442d531b1a22" desc="Text in Request Timing View of the Network panel">
     SSL
   </message>
   <message name="IDS_DEVTOOLS_eb0bd7de3ba805621bf9e03e4d16b510" desc="Text of a DOM element in Request Timing View of the Network panel">
     Queued at <ph name="CALCULATOR_FORMATVALUE_REQUEST_ISSUETIME______">$1s<ex>120.39ms</ex></ph>
   </message>
-  <message name="IDS_DEVTOOLS_eb0f48a107df1a0f343d4cd513b555e6" desc="Text in Signed Exchange Info View of the Network panel">
-    Certificate
-  </message>
-  <message name="IDS_DEVTOOLS_eb902cf204f3e4dfffeb56d92a9b5c26" desc="Text in Signed Exchange Info View of the Network panel">
-    Valid from
-  </message>
-  <message name="IDS_DEVTOOLS_ec53a8c4f07baed5d8825072c89799be" desc="Text in Network Log View Columns of the Network panel">
-    Status
-  </message>
   <message name="IDS_DEVTOOLS_ec559fc895e8cc77ef0c4d6fdff5bdcb" desc="Text in Request Headers View of the Network panel">
     Form Data
   </message>
@@ -783,9 +690,6 @@
   <message name="IDS_DEVTOOLS_f9069c6541beaac49cce4b2542069f02" desc="Text in Request Headers View of the Network panel">
     Referrer Policy
   </message>
-  <message name="IDS_DEVTOOLS_f907e651164789346ae0a1e257c462d8" desc="Text in Network Data Grid Node of the Network panel">
-    Script
-  </message>
   <message name="IDS_DEVTOOLS_f95d3d09fc16ae9294fbef87ac8d17cb" desc="Text in Network Data Grid Node of the Network panel">
     (pending)
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp b/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
index 66386f9..90a9d0c 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
@@ -24,9 +24,6 @@
   <message name="IDS_DEVTOOLS_59aeb2c9970b7b25be2fab2317e31fcb" desc="Text in Java Script Autocomplete">
     keywords
   </message>
-  <message name="IDS_DEVTOOLS_a2e4822a98337283e39f7b60acf85ec9" desc="Text in Remote Object Preview Formatter">
-    empty
-  </message>
   <message name="IDS_DEVTOOLS_a6565c5180039dd2ca1249796bba00a5" desc="Text in Object Properties Section">
     No properties
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp b/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
index 7d323e6..7c20973 100644
--- a/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
@@ -3,9 +3,6 @@
   <message name="IDS_DEVTOOLS_05dedc41542c728955023577fd58be7a" desc="Text for screen reader to announce a collapsed group">
     <ph name="GROUPNAME">$1s<ex>Network</ex></ph> collapsed
   </message>
-  <message name="IDS_DEVTOOLS_105078d294d30c978ca2badf7f376934" desc="Title of a setting under the Performance category that can be invoked through the Command Menu">
-    Scroll
-  </message>
   <message name="IDS_DEVTOOLS_28d0edd045e05cf5af64e35ae0c4c6ef" desc="Text in Network Priorities of the Performance panel">
     Low
   </message>
@@ -18,9 +15,6 @@
   <message name="IDS_DEVTOOLS_3f21c340f01b96cb3325a5d38ece9da6" desc="Title of a setting under the Memory category in Settings">
     Live memory allocation annotations
   </message>
-  <message name="IDS_DEVTOOLS_4789f23283b3a61f858b641a1bef19a3" desc="A title of the 'Memory' setting category">
-    Memory
-  </message>
   <message name="IDS_DEVTOOLS_4a6d0345e7b6cfcf339237b9cf2d27b4" desc="Title of a setting under the Performance category in Settings">
     Flamechart mouse wheel action:
   </message>
@@ -54,9 +48,6 @@
   <message name="IDS_DEVTOOLS_90c96ccfe47a731972d5e64deb5fea36" desc="Title of a setting under the Memory category that can be invoked through the Command Menu">
     Hide live memory allocation annotations
   </message>
-  <message name="IDS_DEVTOOLS_ab57fd0432e25d5b3013133a1c910d56" desc="Units in Line Level Profile of the Performance panel">
-    KB
-  </message>
   <message name="IDS_DEVTOOLS_b5b8e20937205384be7b9e0c29a28fdb" desc="Text in Network Priorities of the Performance panel">
     Lowest
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp b/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
index f377362..7a52eec 100644
--- a/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
@@ -30,7 +30,4 @@
   <message name="IDS_DEVTOOLS_e99180abf47a8b3a856e0bcb2656990a" desc="Text in Performance Monitor of the Performance monitor tab">
     Paused
   </message>
-  <message name="IDS_DEVTOOLS_f28128b38efbc6134dc40751ee21fd29" desc="Text in Performance Monitor of the Performance monitor tab">
-    Documents
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp b/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
index 5bd615d..6d69eb3 100644
--- a/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
@@ -39,9 +39,6 @@
   <message name="IDS_DEVTOOLS_ab130072b340b847d8d45ec45d191c3b" desc="Text of a DOM element in Workspace Settings Tab of the Workspace settings in Settings">
     Mappings are inferred automatically.
   </message>
-  <message name="IDS_DEVTOOLS_afb4ea732ebcf8bd51a3d99a1b8909a8" desc="Text in Isolated File System of the Workspace settings in Settings">
-    Linked to <ph name="PATH">$1s<ex>example.url</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_cf703cce77386955bfbff86f6ad9be03" desc="Text in Isolated File System Manager of the Workspace settings in Settings">
     Unable to add filesystem: <ph name="ERRORMESSAGE">$1s<ex>folder does not exist</ex></ph>
   </message>
@@ -54,9 +51,6 @@
   <message name="IDS_DEVTOOLS_e2b63f5cab4f80fb6745f2f941105371" desc="Title of a setting under the Persistence category in Settings">
     Enable Local Overrides
   </message>
-  <message name="IDS_DEVTOOLS_ec211f7c20af43e742bf2570c3cb84f9" desc="Text of add button in Edit File System View of the Workspace settings in Settings">
-    Add
-  </message>
   <message name="IDS_DEVTOOLS_fddede572fa09e1b1bb28504d8c43343" desc="Text in Edit File System View of the Workspace settings in Settings">
     Folder path
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
index 5ca2aea..85aee7c 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
@@ -1502,8 +1502,9 @@
 
     if (HeapSnapshotModel.HeapSnapshotProgressEvent.Update !== eventName)
       return;
-    const subtitle = /** @type {string} */ (data);
-    this.updateStatus(subtitle);
+    const serializedMessage = /** @type {string} */ (data);
+    const messageObject = Common.deserializeUIString(serializedMessage);
+    this.updateStatus(ls(messageObject.messageParts, messageObject.values));
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
index e282a629..9aa023fa 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
@@ -3,9 +3,6 @@
   <message name="IDS_DEVTOOLS_00018e8c8fc32e1ec073c0cdbadb5575" desc="Text in Heap Profile View of a profiler tool">
     <ph name="NUMBER_WITHTHOUSANDSSEPARATOR_VALUE________">$1s<ex>1,021</ex></ph> KB
   </message>
-  <message name="IDS_DEVTOOLS_007c41a9025be2c8e14b496ed3ee00f8" desc="A context menu item in the Profiles Panel of a profiler tool">
-    Save…
-  </message>
   <message name="IDS_DEVTOOLS_02184526968aa861a744df910647fcf0" desc="Text in Heap Snapshot Data Grids of a profiler tool">
     Freed Size
   </message>
@@ -36,9 +33,6 @@
   <message name="IDS_DEVTOOLS_0aa6f4210bf373c95eda00232e93cd98" desc="Text in Heap Snapshot Data Grids of a profiler tool">
     Distance
   </message>
-  <message name="IDS_DEVTOOLS_11a755d598c0c417f9a36758c3da7481" desc="Control button text content in Profile Launcher View of a profiler tool">
-    Stop
-  </message>
   <message name="IDS_DEVTOOLS_13b5bfe96f3e2fe411c9f66f4a582adf" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
     in
   </message>
@@ -57,21 +51,9 @@
   <message name="IDS_DEVTOOLS_1d36783e12317ed400ebeddeb072a27b" desc="Text in Profile View of a profiler tool">
     Chart
   </message>
-  <message name="IDS_DEVTOOLS_1eaeeaeb638fdf7f6eeb047abbfd0f1a" desc="Text in CPUProfile View of a profiler tool">
-    Self Time
-  </message>
-  <message name="IDS_DEVTOOLS_1f1e990a1d2ba8ab4dd873a192237c30" desc="Text in CPUProfile View of a profiler tool">
-    <ph name="VALUE">$1.1f<ex>30.1</ex></ph> ms
-  </message>
   <message name="IDS_DEVTOOLS_27c0ad7a8ff8f9df8e13bb2d974c95d0" desc="Text in Heap Snapshot View of a profiler tool">
     Allocation
   </message>
-  <message name="IDS_DEVTOOLS_290612199861c31d1036b185b4e69b75" desc="Text in Heap Snapshot Data Grids of a profiler tool">
-    Summary
-  </message>
-  <message name="IDS_DEVTOOLS_2ce2fc341b0bd9219a3634ff43a90bde" desc="Alternate text read when describing the size of a memory allocation and its percentage of heap.">
-    <ph name="THIS_DATA_COLUMNID_">$1s<ex>1 613 680</ex></ph>, <ph name="THIS_DATA_PERCENTCOLUMN_">$2s<ex>44 %</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_2d7b69664bc4226fb198124fb707e57c" desc="Text in Heap Profile View of a profiler tool">
     Snapshot <ph name="THIS_NEXTPROFILEUID__">$1s<ex>1</ex></ph>
   </message>
@@ -93,9 +75,6 @@
   <message name="IDS_DEVTOOLS_35066690e799cd4e59123262e41b29c5" desc="Text in CPUProfile View of a profiler tool">
     Stop CPU profiling
   </message>
-  <message name="IDS_DEVTOOLS_36917e785bd31d786ab9dd7790a9a4c2" desc="Text in Live Heap Profile View of a profiler tool">
-    JS Heap
-  </message>
   <message name="IDS_DEVTOOLS_3a9619400e054970a7ab8b67c4ce5109" desc="Tooltip text that appears when hovering over the largeicon refresh button in the Profile View of a profiler tool">
     Restore all functions
   </message>
@@ -196,9 +175,6 @@
     Native memory snapshots show sampled native allocations in the renderer process since start up.
               Chrome has to be started with --memlog=all flag. Check flags at chrome://flags
   </message>
-  <message name="IDS_DEVTOOLS_6bb61b1a929f2a0186f2671cd8258bd9" desc="Warning icon title in Profile Data Grid of a profiler tool">
-    Not optimized: <ph name="THIS__DEOPTREASON">$1s<ex>Optimized too many times</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_6d27e30b2f09c2a451a6d123c1a35805" desc="Text in Profiles Panel of a profiler tool">
     Run <ph name="_">$1d<ex>2</ex></ph>
   </message>
@@ -247,9 +223,6 @@
   <message name="IDS_DEVTOOLS_85000e6433d4ac4033e6d7f5a3466f92" desc="A context menu item in the Heap Profiler Panel of a profiler tool">
     Reveal in Summary view
   </message>
-  <message name="IDS_DEVTOOLS_86408593c34af77fdd90df932f8b5261" desc="Text in Heap Snapshot Data Grids of a profiler tool">
-    Function
-  </message>
   <message name="IDS_DEVTOOLS_86a699c935e3e7e36e334bb61a336f02" desc="Text in Heap Profile View of a profiler tool">
     Start heap profiling
   </message>
@@ -297,9 +270,6 @@
   <message name="IDS_DEVTOOLS_9e854bf5f75e670228f33f9fe857793d" desc="Text in Heap Snapshot Data Grids of a profiler tool">
     Size of the object plus the graph it retains in bytes
   </message>
-  <message name="IDS_DEVTOOLS_9f29da220ed82809ec5dd70af4e52904" desc="Text in CPUProfile View of a profiler tool">
-    Total Time
-  </message>
   <message name="IDS_DEVTOOLS_a6122a65eaa676f700ae68d393054a37" desc="Control button text content in Profile Launcher View of a profiler tool">
     Start
   </message>
@@ -318,9 +288,6 @@
   <message name="IDS_DEVTOOLS_a97cce5b0a66cd7d7b7b7d2e06b7605c" desc="Text in Profiles Panel of a profiler tool">
     Can&apos;t load file. Supported file extensions: &apos;<ph name="ARRAY_FROM_EXTENSIONS__JOIN________">$1s<ex>'.js', '.json'</ex></ph>&apos;.
   </message>
-  <message name="IDS_DEVTOOLS_aab112fba39c10ed5df335ae0e47f329" desc="Text in CPUProfile View of a profiler tool">
-    Not optimized
-  </message>
   <message name="IDS_DEVTOOLS_ad49e602302b1ca117245c4f19ef4450" desc="Retaining paths title text content in Heap Snapshot View of a profiler tool">
     Retainers
   </message>
@@ -354,9 +321,6 @@
   <message name="IDS_DEVTOOLS_c33e404a441c6ba9648f88af3c68a1ca" desc="Text in Heap Snapshot View of a profiler tool">
     Statistics
   </message>
-  <message name="IDS_DEVTOOLS_c9cc8cce247e49bae79f15173ce97354" desc="Save link element text content in Profiles Panel of a profiler tool">
-    Save
-  </message>
   <message name="IDS_DEVTOOLS_ca0dbad92a874b2f69b549293387925e" desc="Text in Heap Snapshot View of a profiler tool">
     Code
   </message>
@@ -433,9 +397,6 @@
   <message name="IDS_DEVTOOLS_ef15fd2f45e6bb5ce57587895ba64f93" desc="Text in Heap Profile View of a profiler tool">
     Browser
   </message>
-  <message name="IDS_DEVTOOLS_f19dbf2edb3a0bd74b0524d960ff21eb" desc="Text of button in Profile Launcher View of a profiler tool">
-    Load
-  </message>
   <message name="IDS_DEVTOOLS_f3e40bc520cf1f22e4d36d5c5f8d2618" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
     User object reachable from window
   </message>
@@ -454,9 +415,6 @@
   <message name="IDS_DEVTOOLS_fbbe8b507083defdbfe14a341551c77b" desc="Text in CPUProfile View of a profiler tool">
     CPU profiles show where the execution time is spent in your page&apos;s JavaScript functions.
   </message>
-  <message name="IDS_DEVTOOLS_fdbd92f0c6b67291ca954b74885d434e" desc="Text in Heap Profile View of a profiler tool">
-    Profile <ph name="TYPE_NEXTPROFILEUID__">$1d<ex>2</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_ffd4ebcdf9ad139d4cd2c84d853f4f34" desc="Text in Heap Profile View of a profiler tool">
     Total Size (bytes)
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp b/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
index fae6e7b..09b9116 100644
--- a/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
@@ -9,15 +9,6 @@
   <message name="IDS_DEVTOOLS_2448f896f98bcda2db043a999a00e1d2" desc="Cell text content in Protocol Monitor of the Protocol Monitor tab">
     <ph name="THIS_DATA_COLUMNID_">$1s<ex>30</ex></ph> ms
   </message>
-  <message name="IDS_DEVTOOLS_5b6cf869265c13af8566f192b4ab3d2a" desc="A context menu item in the Protocol Monitor of the Protocol Monitor tab">
-    Documentation
-  </message>
-  <message name="IDS_DEVTOOLS_6a0d9eaee314c567fd72fb97ee707a36" desc="Tooltip text that appears when hovering over largeicon start recording button in Protocol Monitor of the Protocol Monitor tab">
-    Record
-  </message>
-  <message name="IDS_DEVTOOLS_a3d5de3eac8bb00ae86fd1a1005f1500" desc="Text in Protocol Monitor of the Protocol Monitor tab">
-    Timestamp
-  </message>
   <message name="IDS_DEVTOOLS_a854885880458e27324853c6f46e28f7" desc="Text in Protocol Monitor of the Protocol Monitor tab">
     No message selected
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp b/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
index edeeb667..e34f7e8 100644
--- a/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
@@ -3,19 +3,7 @@
   <message name="IDS_DEVTOOLS_06f884351ae9dbaaca31602b74d0ed4e" desc="Text in Quick Open of the Command Menu">
     Type &apos;?&apos; to see available commands
   </message>
-  <message name="IDS_DEVTOOLS_22b6fe30dec1ae9c09480cce01cd4065" desc="Title of the Filtered List WidgetProvider of Quick Open">
-    Run command
-  </message>
-  <message name="IDS_DEVTOOLS_74540c79e377bea903e1023a46df5574" desc="Title of an action in the quickOpen tool to show">
-    Open file
-  </message>
   <message name="IDS_DEVTOOLS_8bb9829a676055080c3d4507e0b5f201" desc="Text in Command Menu of the Command Menu">
     No commands found
   </message>
-  <message name="IDS_DEVTOOLS_af9ccba3ec4346e3acf785f9bea514d8" desc="Text in Command Menu of the Command Menu">
-    Show <ph name="EXTENSION_TITLE__">$1s<ex>Audits</ex></ph>
-  </message>
-  <message name="IDS_DEVTOOLS_e576c23d915755d83e2d1f47bd9f6c22" desc="Text in Filtered List Widget of the Command Menu">
-    No results found
-  </message>
 </grit-part>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp b/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
index 99eaeb8b..c425de1a 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
@@ -52,9 +52,6 @@
   <message name="IDS_DEVTOOLS_29104d3ede0231043a4b92a90b9c2873" desc="Title of needs refresh in indexed dbviews of the application panel">
     Some entries may have been modified
   </message>
-  <message name="IDS_DEVTOOLS_2b81bb9b3deebcbfa05edad7a845005a" desc="Text in Application Panel Sidebar of the Application panel">
-    Frames
-  </message>
   <message name="IDS_DEVTOOLS_2bf0a735c3ff964861a2b55319edd355" desc="Text in Clear Storage View of the Application panel">
     Unregister service workers
   </message>
@@ -88,9 +85,6 @@
   <message name="IDS_DEVTOOLS_3eab5d12656f2f4462f6594019e77355" desc="Text in Database Table View of the Application panel">
     Visible columns
   </message>
-  <message name="IDS_DEVTOOLS_3edf8ca26a1ec14dd6e91dd277ae1de6" desc="Text in Background Service View of the Application panel">
-    Origin
-  </message>
   <message name="IDS_DEVTOOLS_458efe6e41ed41835b8d84b28db3f394" desc="Filter label text content in Service Workers View of the Application panel">
     Service workers from other origins
   </message>
@@ -106,12 +100,6 @@
   <message name="IDS_DEVTOOLS_536cf547cb6ecfe32be6ed3ffdabf893" desc="Text of button in Clear Storage View of the Application panel">
     Clear site data
   </message>
-  <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="Image alt in App Manifest View of the Application panel">
-    Image from <ph name="URL">$1s<ex>example.com</ex></ph>
-  </message>
-  <message name="IDS_DEVTOOLS_54f664c70c22054ea0d8d26fc3997ce7" desc="Connectivity icon text content in Application Cache Items View of the Application panel">
-    Online
-  </message>
   <message name="IDS_DEVTOOLS_55bce575c41275ddaf5fbd1beb7d6018" desc="Text in Service Workers View of the Application panel">
     #<ph name="INSTALLING_ID">$1s<ex>2</ex></ph> trying to install
   </message>
@@ -239,9 +227,6 @@
   <message name="IDS_DEVTOOLS_a274f4d4670213a9045ce258c6c56b80" desc="Text in Background Service View of the Application panel">
     Notifications
   </message>
-  <message name="IDS_DEVTOOLS_a4ecfc70574394990cf17bd83df499f7" desc="Text in Background Service View of the Application panel">
-    Event
-  </message>
   <message name="IDS_DEVTOOLS_a7d5ee58baead2f3bc229d3d9c047875" desc="Text in Service Workers View of the Application panel">
     Unregister service worker
   </message>
@@ -287,9 +272,6 @@
   <message name="IDS_DEVTOOLS_bb8839cf9d324a22591ff426c28c5345" desc="Tooltip text that appears when hovering over the largeicon play button in the Indexed DBViews of the Application panel">
     Show next page
   </message>
-  <message name="IDS_DEVTOOLS_be8545ae7ab0276e15898aae7acfbd7a" desc="Text in Application Cache Items View of the Application panel">
-    Resource
-  </message>
   <message name="IDS_DEVTOOLS_bebc9b50966d8d2bd1913a3c25b707d4" desc="Text in Indexed DBViews of the Application panel">
     Data may be stale
   </message>
@@ -413,9 +395,6 @@
   <message name="IDS_DEVTOOLS_ef399b2d446bb37b7c32ad2cc1b6045b" desc="Text in Service Workers View of the Application panel">
     stop
   </message>
-  <message name="IDS_DEVTOOLS_f31bbdd1b3e85bccd652680e16935819" desc="Text in Service Workers View of the Application panel">
-    Source
-  </message>
   <message name="IDS_DEVTOOLS_fb1508747fe448fd8b006e923ba1c3ef" desc="Text in Background Service View of the Application panel">
     Payment Handler
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
index 2dc383e..9853891 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
@@ -201,9 +201,6 @@
   <message name="IDS_DEVTOOLS_9028784c589c0c809700c7fbc66a5d96" desc="Text in Network Manager">
     Resource interpreted as <ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s<ex>application</ex></ph> but transferred with MIME type <ph name="NETWORKREQUEST_MIMETYPE">$2s<ex>image</ex></ph>: &quot;<ph name="NETWORKREQUEST_URL__">$3s<ex>https://example.com</ex></ph>&quot;.
   </message>
-  <message name="IDS_DEVTOOLS_90da6f38945a1c7e7ba11e3adcbe6919" desc="Title of a setting under the Debugger category that can be invoked through the Command Menu">
-    Pause on exceptions
-  </message>
   <message name="IDS_DEVTOOLS_9108ae673b7efa9620aec771edc9d4de" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
     setTimeout fired
   </message>
@@ -216,9 +213,6 @@
   <message name="IDS_DEVTOOLS_93dee6366d66361f36985cf5c88346aa" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
     Create AudioContext
   </message>
-  <message name="IDS_DEVTOOLS_95bbad55f11c237ed89546e748093ba7" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
-    Request Animation Frame
-  </message>
   <message name="IDS_DEVTOOLS_96d008db67fc0b5551a926842bbb6a71" desc="Text in DOMDebugger Model">
     Notification
   </message>
@@ -252,9 +246,6 @@
   <message name="IDS_DEVTOOLS_ae0d59f889c8a03301b9adb5ff1f5bd2" desc="Tooltip to explain why a cookie was blocked">
     This set-cookie had the &quot;SameSite=Strict&quot; attribute but came from a cross-origin response. This includes navigation requests intitiated by other origins.
   </message>
-  <message name="IDS_DEVTOOLS_af4bb376939e77df0e7c2332b837a866" desc="Text in Debugger Model">
-    Closure
-  </message>
   <message name="IDS_DEVTOOLS_b1d4660db82a3d7b85dca58e8635ce13" desc="Tooltip to explain why a cookie was blocked">
     This set-cookie had the &quot;SameSite=Lax&quot; attribute but came from a cross-origin response.
   </message>
@@ -276,12 +267,6 @@
   <message name="IDS_DEVTOOLS_ba50636875d999db0c9218b48b23027d" desc="Title of a setting under the Debugger category that can be invoked through the Command Menu">
     Do not capture async stack traces
   </message>
-  <message name="IDS_DEVTOOLS_ba5b676ccf658f863ef2e3df082ee262" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
-    Animation Frame Fired
-  </message>
-  <message name="IDS_DEVTOOLS_bc955333ff170762be4971a8fde558cf" desc="Text in DOMDebugger Model">
-    WebAudio
-  </message>
   <message name="IDS_DEVTOOLS_c432f4e5fdec5760a2f06b38f646168e" desc="Text in Console Model">
     Profile &apos;<ph name="DATA_TITLE">$1s<ex>title</ex></ph>&apos; started.
   </message>
@@ -294,9 +279,6 @@
   <message name="IDS_DEVTOOLS_c89686a387d2b12b3c729ce35a0bcb5b" desc="Text in DOMDebugger Model">
     Window
   </message>
-  <message name="IDS_DEVTOOLS_c9ad95228aa735bdda1aebf38da022af" desc="Text in DOMDebugger Model">
-    Parse
-  </message>
   <message name="IDS_DEVTOOLS_ccab918ce9f085b521a52ac13f653c0b" desc="Tooltip to explain why a cookie was blocked">
     An unknown error was encountered when trying to send this cookie.
   </message>
@@ -306,15 +288,9 @@
   <message name="IDS_DEVTOOLS_d24a22fef757966373800aa9795458dc" desc="Text in Source Map">
     ? [sm]
   </message>
-  <message name="IDS_DEVTOOLS_d31827f0a164d52b636bb1f71ca4a351" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
-    Cancel Animation Frame
-  </message>
   <message name="IDS_DEVTOOLS_d4fad802fc7bf0248d34c685533bd56f" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
     Disable request blocking
   </message>
-  <message name="IDS_DEVTOOLS_d6b6b668dbca9d4fe774bb654226ebe3" desc="Text in DOMDebugger Model">
-    Animation
-  </message>
   <message name="IDS_DEVTOOLS_dcd9c13c4f8ae68ea7ae92edf9191264" desc="Text in Server Timing">
     Deprecated syntax found. Please use: &lt;name&gt;;dur=&lt;duration&gt;;desc=&lt;description&gt;
   </message>
@@ -336,9 +312,6 @@
   <message name="IDS_DEVTOOLS_e485c975c1d6c17d9dfd81128b83f63a" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
     Set innerHTML
   </message>
-  <message name="IDS_DEVTOOLS_e55f75a29310d7b60f7ac1d390c8ae42" desc="Text in Debugger Model">
-    Module
-  </message>
   <message name="IDS_DEVTOOLS_e69d85cd1acdf030f0cede48b61d7720" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
     Hide scroll performance bottlenecks
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp b/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
index f5e416f3..9f1dae71 100644
--- a/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
@@ -1,8 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_2f04f3e6eee339eeb0ddb6c39606424d" desc="Text in Search View of the Search tab">
-    Use Regular Expression
-  </message>
   <message name="IDS_DEVTOOLS_44b4e531d5b06deb40b631e4aa3c7e36" desc="Text in Search Results Pane of the Search tab">
     Show <ph name="MATCHESLEFTCOUNT">$1d<ex>2</ex></ph> more
   </message>
@@ -21,9 +18,6 @@
   <message name="IDS_DEVTOOLS_c440d4f6fc7dd9239ada58277b900249" desc="Search results message element text content in Search View of the Search tab">
     Found <ph name="THIS__SEARCHMATCHESCOUNT">$1d<ex>2</ex></ph> matching lines in 1 file.
   </message>
-  <message name="IDS_DEVTOOLS_c949475bc69a57c419ac976fe8870652" desc="Text in Search View of the Search tab">
-    Match Case
-  </message>
   <message name="IDS_DEVTOOLS_d1e64da6074bf343a0a6bd2cd6515189" desc="Text in Search View of the Search tab">
     Indexing interrupted.
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp b/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
index 1249bdaa..275b8d8 100644
--- a/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
@@ -3,9 +3,6 @@
   <message name="IDS_DEVTOOLS_0f653ae68147586eb189d7baf37a696a" desc="Text of button in Settings Screen of the Settings">
     Restore defaults and reload
   </message>
-  <message name="IDS_DEVTOOLS_29e9d8e295b1d5b3002d2d3d5baa4c37" desc="Text in Settings Screen of the Settings">
-    Shortcuts
-  </message>
   <message name="IDS_DEVTOOLS_2cce43a6505a5d1bdf7ea98bf7fd1bc8" desc="Blackbox label in Framework Blackbox Settings Tab of the Settings">
     Blackbox
   </message>
@@ -42,9 +39,6 @@
   <message name="IDS_DEVTOOLS_c745d3ac390f120535d734cd14e2f6aa" desc="Blackbox content scripts title in Framework Blackbox Settings Tab of the Settings">
     Blackbox content scripts (extension scripts in the page)
   </message>
-  <message name="IDS_DEVTOOLS_c9deece3e6de26d07ef6409b96f21fd0" desc="Title of Blackboxing settings">
-    Blackboxing
-  </message>
   <message name="IDS_DEVTOOLS_d0834fcec6337785ee749c8f5464f6f6" desc="Text in Settings Screen of the Settings">
     Preferences
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js b/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
index a6d611d..ad3092e 100644
--- a/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
+++ b/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
@@ -28,7 +28,7 @@
     const nextId = this._lastSnippetIdentifierSetting.get() + 1;
     this._lastSnippetIdentifierSetting.set(nextId);
 
-    const snippetName = `Script snippet #${nextId}`;
+    const snippetName = ls`Script snippet #${nextId}`;
     const snippets = this._snippetsSetting.get();
     snippets.push({name: snippetName, content: ''});
     this._snippetsSetting.set(snippets);
diff --git a/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp b/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
index 0ec05112d..770ad82 100644
--- a/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <grit-part>
-  <message name="IDS_DEVTOOLS_b1d75786654fa93f10c31c3b544bbd03" desc="Title of the Filtered List WidgetProvider of Quick Open">
-    Run snippet
+  <message name="IDS_DEVTOOLS_a8c377be97611cba090c400b4b54f753" desc="Default snippet name when a new snippet is created in the Sources panel">
+    Script snippet #<ph name="NEXTID">$1s<ex>1</ex></ph>
   </message>
   <message name="IDS_DEVTOOLS_e0fe9b9cadde935642ad15a85c79d7b1" desc="Text in Snippets Quick Open of the Sources panel when opening snippets">
     No snippets found.
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
index d6ec6d3..46db3e6 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
@@ -15,12 +15,6 @@
   <message name="IDS_DEVTOOLS_33443fc55632401a517b16878389f2f6" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
     Set indentation to 4 spaces
   </message>
-  <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="Text in JSONView of the Sources panel">
-    Find
-  </message>
-  <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="Tooltip text that appears when hovering over largeicon pretty print button in Source Frame of the Sources panel">
-    Pretty print
-  </message>
   <message name="IDS_DEVTOOLS_5ada9c9e1dad2e7e20aaa7688d7bd6c7" desc="Text in Source Frame of the Sources panel">
     Line <ph name="LOCATION_______">$1s<ex>2</ex></ph>, Column <ph name="LOCATION_______">$2s<ex>2</ex></ph>
   </message>
@@ -69,9 +63,6 @@
   <message name="IDS_DEVTOOLS_fb49df2db96d183474fb9e954a9f0e52" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
     Set indentation to tab character
   </message>
-  <message name="IDS_DEVTOOLS_fb61758d0f0fda4ba867c3d5a46c16a7" desc="A title of the 'Sources' setting category">
-    Sources
-  </message>
   <message name="IDS_DEVTOOLS_fe81050cdc3adc7c1912fc08b7aec77f" desc="A drop-down menu option to set indentation to 4 spaces">
     4 spaces
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp b/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
index d940c100..4b6ad4e 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
@@ -165,18 +165,12 @@
   <message name="IDS_DEVTOOLS_520d0db389f362bf79ef56ca0af3dcab" desc="Tooltip text that appears when hovering over the largeicon pretty print button in the Inplace Formatter Editor Action of the Sources panel">
     Format
   </message>
-  <message name="IDS_DEVTOOLS_52b3bc5e77aa070243c36cd40a4d6b6d" desc="Title of a setting under the Sources category in Settings">
-    Autocompletion
-  </message>
   <message name="IDS_DEVTOOLS_58943fa26a94bc86f7f45106080e4496" desc="Title of an action under the Debugger category that can be invoked through the Command Menu">
     Resume script execution
   </message>
   <message name="IDS_DEVTOOLS_590d0b32e1139c6c3bcb0f99ed978dff" desc="Text in Debugger Paused Message of the Sources panel">
     subtree modifications
   </message>
-  <message name="IDS_DEVTOOLS_5a0a64ecca63ba9a006b6397cbdc2b8c" desc="Title of the Filtered List WidgetProvider of Quick Open">
-    Go to line
-  </message>
   <message name="IDS_DEVTOOLS_5a3bb6a64da384e59876cd0bc00a6eae" desc="Unblackbox link text content in Debugger Plugin of the Sources panel">
     Unblackbox this script
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
index 2124a43f..251cd22e 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
@@ -283,9 +283,6 @@
   <message name="IDS_DEVTOOLS_44ff4e8748811d0661f820aeb28ecaf4" desc="Text in Timeline UIUtils of the Performance panel">
     XHR Ready State Change
   </message>
-  <message name="IDS_DEVTOOLS_46a2a41cc6e552044816a2d04634545d" desc="Text in Timeline UIUtils of the Performance panel">
-    State
-  </message>
   <message name="IDS_DEVTOOLS_46fa564bb1eed5cd3992cac85e8f094b" desc="Title of show screenshots setting in timeline panel of the performance panel">
     Screenshots
   </message>
@@ -502,9 +499,6 @@
   <message name="IDS_DEVTOOLS_7ac6c415cd08c0ba2c0a1f54c0a62a52" desc="Text in Timeline UIUtils of the Performance panel">
     ''' (from push)
   </message>
-  <message name="IDS_DEVTOOLS_7b3a6b02f467b95f2b5267aa94708c07" desc="Text in Timeline Flame Chart Data Provider of the Performance panel">
-    Thread <ph name="__THREADINDEX">$1s<ex>2</ex></ph>
-  </message>
   <message name="IDS_DEVTOOLS_80a4b8755d836d50c19e6eefb976bc2e" desc="Text in Timeline UIUtils of the Performance panel">
     <ph name="SELFCATEGORY_TITLE">$1s<ex>blink.console</ex></ph> (self)
   </message>
@@ -612,9 +606,6 @@
   <message name="IDS_DEVTOOLS_97c091732895087b8900d81105e54446" desc="Text in Timeline UIUtils of the Performance panel">
     Frame Start (main thread)
   </message>
-  <message name="IDS_DEVTOOLS_997a8c473db4f81c5fb3d5900030d44d" desc="Text in Timeline History Manager of the Performance panel">
-    (no recordings)
-  </message>
   <message name="IDS_DEVTOOLS_9a2837081f4b4cd67f625bd8e7567383" desc="Text in Timeline UIUtils of the Performance panel">
     Compile Script
   </message>
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizability.js b/third_party/blink/renderer/devtools/scripts/check_localizability.js
index 91e7158..98e695c 100644
--- a/third_party/blink/renderer/devtools/scripts/check_localizability.js
+++ b/third_party/blink/renderer/devtools/scripts/check_localizability.js
@@ -49,6 +49,7 @@
       filePaths = process.argv.slice(2);
     await Promise.all(filePathPromises);
 
+    filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
     const auditFilePromises = filePaths.map(filePath => auditFileForLocalizability(filePath, errors));
     await Promise.all(auditFilePromises);
   } catch (err) {
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
index 4281b65c..ccf31363 100644
--- a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
+++ b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
@@ -19,6 +19,7 @@
 // { IDS_md5-hash => {
 //     string: string,
 //     code: string,
+//     isShared: boolean,
 //     filepath: string,
 //     grdpPath: string,
 //     location: {
@@ -93,9 +94,20 @@
   if (path.basename(filePath) === 'module.json')
     return parseLocalizableStringFromModuleJson(fileContent, filePath);
 
-  const ast = esprima.parseModule(fileContent, {loc: true});
-  for (const node of ast.body)
+  let ast;
+  try {
+    ast = esprima.parseModule(fileContent, {loc: true});
+  } catch (e) {
+    throw new Error(
+        `DevTools localization parser failed:\n${localizationUtils.getRelativeFilePathFromSrc(filePath)}: ${
+            e.message}` +
+        `\nThis error is likely due to unsupported JavaScript features.` +
+        ` Such features are not supported by eslint either and will cause presubmit to fail.` +
+        ` Please update the code and use official JavaScript features.`);
+  }
+  for (const node of ast.body) {
     parseLocalizableStringFromNode(node, filePath);
+  }
 }
 
 function parseLocalizableStringFromModuleJson(fileContent, filePath) {
@@ -208,18 +220,27 @@
 }
 
 function addString(str, code, filePath, location, argumentNodes) {
-  const currentString = {string: str, code: code, filepath: filePath, grdpPath: fileToGRDPMap.get(filePath)};
+  const ids = localizationUtils.getIDSKey(str);
+
+  // In the case of duplicates, the corresponding grdp message should be added
+  // to the shared strings file only if the duplicate strings span across different
+  // grdp files
+  const existingString = frontendStrings.get(ids);
+  if (existingString) {
+    if (!existingString.isShared && existingString.grdpPath !== fileToGRDPMap.get(filePath)) {
+      existingString.isShared = true;
+      existingString.grdpPath = localizationUtils.SHARED_STRINGS_PATH;
+    }
+    return;
+  }
+
+  const currentString =
+      {string: str, code: code, isShared: false, filepath: filePath, grdpPath: fileToGRDPMap.get(filePath)};
   if (location)
     currentString.location = location;
   if (argumentNodes && argumentNodes.length > 0)
     currentString.arguments = argumentNodes.map(argNode => escodegen.generate(argNode));
 
-  // In the case of duplicates, to enforce that entries are added to
-  // a consistent GRDP file, we use the file path that sorts lowest as
-  // the winning entry into frontendStrings.
-  const ids = localizationUtils.getIDSKey(str);
-  if (frontendStrings.has(ids) && frontendStrings.get(ids).filepath <= filePath)
-    return;
   frontendStrings.set(ids, currentString);
 }
 
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
index 7a2436d0..72521b8 100644
--- a/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
+++ b/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
@@ -34,6 +34,7 @@
 const THIRD_PARTY_PATH = path.resolve(__dirname, '..', '..', '..', '..', '..');
 const SRC_PATH = path.resolve(THIRD_PARTY_PATH, '..');
 const GRD_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'devtools_ui_strings.grd');
+const SHARED_STRINGS_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'shared_strings.grdp');
 const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'node', 'node_modules');
 const escodegen = require(path.resolve(REPO_NODE_MODULES_PATH, 'escodegen'));
 const esprima = require(path.resolve(REPO_NODE_MODULES_PATH, 'esprima'));
@@ -278,6 +279,7 @@
   lineNumberOfIndex,
   modifyStringIntoGRDFormat,
   parseFileContent,
+  SHARED_STRINGS_PATH,
   sanitizeStringIntoCppFormat,
   sanitizeStringIntoFrontendFormat,
   verifyFunctionCallee
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
index 16d3c49..8db94a2 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -24,10 +24,7 @@
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
-#include "third_party/blink/public/platform/modules/p2p/empty_network_manager.h"
-#include "third_party/blink/public/platform/modules/p2p/ipc_network_manager.h"
 #include "third_party/blink/public/platform/modules/peerconnection/audio_codec_factory.h"
-#include "third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h"
 #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_media_constraints.h"
@@ -41,12 +38,15 @@
 #include "third_party/blink/public/web/modules/webrtc/webrtc_audio_device_impl.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/platform/p2p/empty_network_manager.h"
 #include "third_party/blink/renderer/platform/p2p/filtering_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/ipc_network_manager.h"
 #include "third_party/blink/renderer/platform/p2p/ipc_socket_factory.h"
 #include "third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h"
 #include "third_party/blink/renderer/platform/p2p/port_allocator.h"
 #include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
 #include "third_party/blink/renderer/platform/peerconnection/stun_field_trial.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
 #include "third_party/webrtc/api/call/call_factory_interface.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc/api/rtc_event_log/rtc_event_log_factory.h"
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
index eb86194..e4aec08 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
@@ -627,15 +627,8 @@
     network::mojom::blink::WebSocketMessageType type,
     base::span<const char> data,
     uint64_t* consumed_buffered_amount) {
-  // TODO(darin): Avoid this copy.
-  Vector<uint8_t> data_to_pass;
-  // This cast is always valid because the data size is limited by
-  // sending_quota_, which is controlled by the browser process and in practice
-  // is always much smaller than 4GB.
-  // TODO(ricea): Change the type of sending_quota_ to wtf_size_t.
-  data_to_pass.ReserveInitialCapacity(static_cast<wtf_size_t>(data.size()));
-  data_to_pass.Append(data.data(), static_cast<wtf_size_t>(data.size()));
-
+  base::span<const uint8_t> data_to_pass(
+      reinterpret_cast<const uint8_t*>(data.data()), data.size());
   websocket_->SendFrame(fin, type, data_to_pass);
 
   sending_quota_ -= data.size();
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
index 84ec758..b6516c1 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -112,8 +112,10 @@
 
     void SendFrame(bool fin,
                    WebSocketMessageType type,
-                   const Vector<uint8_t>& data) override {
-      frames_.push_back(Frame{fin, type, data});
+                   base::span<const uint8_t> data) override {
+      Vector<uint8_t> data_to_pass;
+      data_to_pass.AppendRange(data.begin(), data.end());
+      frames_.push_back(Frame{fin, type, std::move(data_to_pass)});
     }
     void StartReceiving() override {
       DCHECK(!is_start_receiving_called_);
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index 7a66e50..f0b3f495 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -248,7 +248,11 @@
   DCHECK_NE(exception_code, DOMExceptionCode::kSecurityError);
 
   if (exception_state) {
+    // The generated bindings will reject the returned promise for us.
+    // Detaching the resolver prevents it from thinking we abandoned
+    // the promise.
     exception_state->ThrowDOMException(exception_code, message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(
         MakeGarbageCollected<DOMException>(exception_code, message));
@@ -259,7 +263,11 @@
     const String& sanitized_message,
     ExceptionState* exception_state) {
   if (exception_state) {
+    // The generated V8 bindings will reject the returned promise for us.
+    // Detaching the resolver prevents it from thinking we abandoned
+    // the promise.
     exception_state->ThrowSecurityError(sanitized_message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(MakeGarbageCollected<DOMException>(
         DOMExceptionCode::kSecurityError, sanitized_message));
@@ -270,7 +278,11 @@
     const String& message,
     ExceptionState* exception_state) {
   if (exception_state) {
+    // The generated bindings will reject the returned promise for us.
+    // Detaching the resolver prevents it from thinking we abandoned
+    // the promise.
     exception_state->ThrowTypeError(message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(V8ThrowException::CreateTypeError(
         resolver_->GetScriptState()->GetIsolate(), message));
@@ -306,6 +318,7 @@
 
   if (exception_state) {
     exception_state->ThrowDOMException(exception_code, message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(
         MakeGarbageCollected<DOMException>(exception_code, message));
@@ -319,6 +332,7 @@
     ExceptionState* exception_state) {
   if (exception_state) {
     exception_state->ThrowSecurityError(sanitized_message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(MakeGarbageCollected<DOMException>(
         DOMExceptionCode::kSecurityError, sanitized_message));
@@ -332,6 +346,7 @@
     ExceptionState* exception_state) {
   if (exception_state) {
     exception_state->ThrowTypeError(message);
+    resolver_->Detach();
   } else {
     resolver_->Reject(V8ThrowException::CreateTypeError(
         GetScriptState()->GetIsolate(), message));
@@ -470,18 +485,18 @@
 ScriptPromise XR::supportsSession(ScriptState* script_state,
                                   const String& mode,
                                   ExceptionState& exception_state) {
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
-
   LocalFrame* frame = GetFrame();
   Document* doc = frame ? frame->GetDocument() : nullptr;
   if (!doc) {
     // Reject if the frame or document is inaccessible.
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       kNavigatorDetachedError);
-    return promise;
+    return ScriptPromise();  // Will be rejected by generated bindings
   }
 
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
+
   XRSession::SessionMode session_mode = stringToSessionMode(mode);
   PendingSupportsSessionQuery* query =
       MakeGarbageCollected<PendingSupportsSessionQuery>(resolver, session_mode);
@@ -640,9 +655,6 @@
                                  ExceptionState& exception_state) {
   // TODO(https://crbug.com/968622): Make sure we don't forget to call
   // metrics-related methods when the promise gets resolved/rejected.
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
-
   LocalFrame* frame = GetFrame();
   Document* doc = frame ? frame->GetDocument() : nullptr;
   if (!doc) {
@@ -652,7 +664,7 @@
     // Document to get UkmRecorder anyway).
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       kNavigatorDetachedError);
-    return promise;
+    return ScriptPromise();  // Will be rejected by generated bindings
   }
 
   XRSession::SessionMode session_mode = stringToSessionMode(mode);
@@ -697,6 +709,9 @@
       break;
   }
 
+  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+  ScriptPromise promise = resolver->Promise();
+
   PendingRequestSessionQuery* query =
       MakeGarbageCollected<PendingRequestSessionQuery>(
           GetSourceId(), resolver, session_mode, std::move(required_features),
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index bba1af3..c891f629 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1230,19 +1230,24 @@
     "mojo/string16_mojom_traits.cc",
     "mojo/string16_mojom_traits.h",
     "p2p/empty_network_manager.cc",
+    "p2p/empty_network_manager.h",
     "p2p/filtering_network_manager.cc",
     "p2p/filtering_network_manager.h",
     "p2p/host_address_request.cc",
     "p2p/host_address_request.h",
     "p2p/ipc_network_manager.cc",
+    "p2p/ipc_network_manager.h",
     "p2p/ipc_socket_factory.cc",
     "p2p/ipc_socket_factory.h",
     "p2p/mdns_responder_adapter.cc",
     "p2p/mdns_responder_adapter.h",
+    "p2p/network_list_manager.h",
+    "p2p/network_list_observer.h",
     "p2p/network_manager_uma.cc",
     "p2p/network_manager_uma.h",
     "p2p/port_allocator.cc",
     "p2p/port_allocator.h",
+    "p2p/socket_client.h",
     "p2p/socket_client_delegate.h",
     "p2p/socket_client_impl.cc",
     "p2p/socket_client_impl.h",
@@ -1276,6 +1281,7 @@
     "peerconnection/transmission_encoding_info_handler.cc",
     "peerconnection/transmission_encoding_info_handler.h",
     "peerconnection/video_codec_factory.cc",
+    "peerconnection/video_codec_factory.h",
     "peerconnection/webrtc_audio_sink.cc",
     "peerconnection/webrtc_video_track_source.cc",
     "prerender.cc",
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index 777a3ed..85292fa3c 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -443,15 +443,19 @@
       return false;
   }
 
-  // WritePixels is not supported by deferral. Since we are directly rendering,
-  // we can't do deferral on top of the canvas. Disable deferral completely.
-  last_recording_ = nullptr;
-  is_deferral_enabled_ = false;
-  have_recorded_draw_commands_ = false;
-  recorder_.reset();
-  // install the current matrix/clip stack onto the immediate canvas
-  if (GetOrCreateResourceProvider()) {
-    resource_host_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
+  if (is_deferral_enabled_) {
+    // WritePixels is not supported by deferral. Since we are directly
+    // rendering, we can't do deferral on top of the canvas. Disable deferral
+    // completely.
+    last_recording_ = nullptr;
+    is_deferral_enabled_ = false;
+    have_recorded_draw_commands_ = false;
+    recorder_.reset();
+    // install the current matrix/clip stack onto the immediate canvas
+    if (GetOrCreateResourceProvider()) {
+      resource_host_->RestoreCanvasMatrixClipStack(
+          ResourceProvider()->Canvas());
+    }
   }
 
   ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y);
diff --git a/third_party/blink/renderer/platform/p2p/empty_network_manager.cc b/third_party/blink/renderer/platform/p2p/empty_network_manager.cc
index e64ac48..4895e42 100644
--- a/third_party/blink/renderer/platform/p2p/empty_network_manager.cc
+++ b/third_party/blink/renderer/platform/p2p/empty_network_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/platform/modules/p2p/empty_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/empty_network_manager.h"
 
 #include "base/bind.h"
 #include "base/location.h"
diff --git a/third_party/blink/public/platform/modules/p2p/empty_network_manager.h b/third_party/blink/renderer/platform/p2p/empty_network_manager.h
similarity index 78%
rename from third_party/blink/public/platform/modules/p2p/empty_network_manager.h
rename to third_party/blink/renderer/platform/p2p/empty_network_manager.h
index 41f5495..77d43634 100644
--- a/third_party/blink/public/platform/modules/p2p/empty_network_manager.h
+++ b/third_party/blink/renderer/platform/p2p/empty_network_manager.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_EMPTY_NETWORK_MANAGER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_EMPTY_NETWORK_MANAGER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
-#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/webrtc/rtc_base/network.h"
 #include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
 
@@ -21,17 +21,14 @@
 // A NetworkManager implementation which handles the case where local address
 // enumeration is not requested and just returns empty network lists. This class
 // is not thread safe and should only be used by WebRTC's network thread.
-//
-// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
-// all users of it have been Onion souped. Also, move it away from std::vector.
 class EmptyNetworkManager : public rtc::NetworkManagerBase,
                             public sigslot::has_slots<> {
  public:
   // This class is created by WebRTC's signaling thread but used by WebRTC's
   // worker thread |task_runner|.
-  BLINK_PLATFORM_EXPORT explicit EmptyNetworkManager(
+  PLATFORM_EXPORT explicit EmptyNetworkManager(
       rtc::NetworkManager* network_manager);
-  BLINK_PLATFORM_EXPORT ~EmptyNetworkManager() override;
+  PLATFORM_EXPORT ~EmptyNetworkManager() override;
 
   // rtc::NetworkManager:
   void StartUpdating() override;
@@ -69,4 +66,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_EMPTY_NETWORK_MANAGER_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
diff --git a/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc b/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
index d8540d5..a928561 100644
--- a/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
+++ b/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
@@ -18,7 +18,7 @@
 #include "media/base/media_permission.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/p2p/empty_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/empty_network_manager.h"
 #include "third_party/webrtc/rtc_base/ip_address.h"
 
 using NetworkList = rtc::NetworkManager::NetworkList;
diff --git a/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc b/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
index 52d7d120..1ac806d 100644
--- a/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
+++ b/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/platform/modules/p2p/ipc_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/ipc_network_manager.h"
 
 #include <string>
 #include <utility>
diff --git a/third_party/blink/public/platform/modules/p2p/ipc_network_manager.h b/third_party/blink/renderer/platform/p2p/ipc_network_manager.h
similarity index 73%
rename from third_party/blink/public/platform/modules/p2p/ipc_network_manager.h
rename to third_party/blink/renderer/platform/p2p/ipc_network_manager.h
index d70b628..8db0420 100644
--- a/third_party/blink/public/platform/modules/p2p/ipc_network_manager.h
+++ b/third_party/blink/renderer/platform/p2p/ipc_network_manager.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_IPC_NETWORK_MANAGER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_IPC_NETWORK_MANAGER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
 
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_manager.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_observer.h"
-#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/webrtc/rtc_base/mdns_responder_interface.h"
 #include "third_party/webrtc/rtc_base/network.h"
 
@@ -26,7 +26,7 @@
                           public blink::NetworkListObserver {
  public:
   // Constructor doesn't take ownership of the |network_list_manager|.
-  BLINK_PLATFORM_EXPORT IpcNetworkManager(
+  PLATFORM_EXPORT IpcNetworkManager(
       blink::NetworkListManager* network_list_manager,
       std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder);
   ~IpcNetworkManager() override;
@@ -45,6 +45,8 @@
  private:
   void SendNetworksChangedSignal();
 
+  // TODO(crbug.com/787254): Consider moving NetworkListManager to Oilpan and
+  // avoid using a raw pointer.
   blink::NetworkListManager* network_list_manager_;
   std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder_;
   int start_count_ = 0;
@@ -55,4 +57,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_IPC_NETWORK_MANAGER_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
diff --git a/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc b/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc
index 152dd782..b00dc6f 100644
--- a/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc
+++ b/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/platform/modules/p2p/ipc_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/ipc_network_manager.h"
 
 #include <algorithm>
 #include <memory>
@@ -11,7 +11,7 @@
 #include "net/base/network_change_notifier.h"
 #include "net/base/network_interfaces.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
 #include "third_party/webrtc/rtc_base/mdns_responder_interface.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc b/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
index e124f40..a28777e 100644
--- a/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
+++ b/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
@@ -424,7 +424,8 @@
   send_bytes_available_ -= data_size;
 
   const int8_t* data_char = reinterpret_cast<const int8_t*>(data);
-  std::vector<int8_t> data_vector(data_char, data_char + data_size);
+  Vector<int8_t> data_vector;
+  data_vector.AppendRange(data_char, data_char + data_size);
   uint64_t packet_id = client_->Send(address_chrome, data_vector, options);
 
   // Ensure packet_id is not 0. It can't be the case according to
diff --git a/third_party/blink/public/platform/modules/p2p/network_list_manager.h b/third_party/blink/renderer/platform/p2p/network_list_manager.h
similarity index 70%
rename from third_party/blink/public/platform/modules/p2p/network_list_manager.h
rename to third_party/blink/renderer/platform/p2p/network_list_manager.h
index 0928325..0be11c05 100644
--- a/third_party/blink/public/platform/modules/p2p/network_list_manager.h
+++ b/third_party/blink/renderer/platform/p2p/network_list_manager.h
@@ -6,18 +6,18 @@
 // IpcNetworkManager such that it doesn't depend on implementation of
 // P2PSocketDispatcher.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_MANAGER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_MANAGER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
 
-#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
 
 namespace blink {
 
 class NetworkListObserver;
 
-// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
-// all users of it have been Onion souped.
-class BLINK_PLATFORM_EXPORT NetworkListManager {
+// TODO(crbug.com/787254): Verify whether this abstract class is still
+// needed now that its Clients have all switched to Blink.
+class PLATFORM_EXPORT NetworkListManager {
  public:
   // Add a new network list observer. Each observer is called
   // immidiately after it is registered and then later whenever
@@ -39,4 +39,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_MANAGER_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
diff --git a/third_party/blink/public/platform/modules/p2p/network_list_observer.h b/third_party/blink/renderer/platform/p2p/network_list_observer.h
similarity index 61%
rename from third_party/blink/public/platform/modules/p2p/network_list_observer.h
rename to third_party/blink/renderer/platform/p2p/network_list_observer.h
index 8c80fbd..714c9a7 100644
--- a/third_party/blink/public/platform/modules/p2p/network_list_observer.h
+++ b/third_party/blink/renderer/platform/p2p/network_list_observer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_OBSERVER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_OBSERVER_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_OBSERVER_H_
 
 #include <vector>
 
@@ -15,8 +15,10 @@
 
 namespace blink {
 
-// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
-// all users of it have been Onion souped. Also, move it away from std::vector.
+// TODO(crbug.com/787254): Verify whether this abstract class is still
+// needed now that its Clients have all switched to Blink.
+//
+// TODO(crbug.com/787254): Move this class away from std::vector.
 class NetworkListObserver {
  public:
   virtual ~NetworkListObserver() {}
@@ -32,4 +34,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_NETWORK_LIST_OBSERVER_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_OBSERVER_H_
diff --git a/third_party/blink/public/platform/modules/p2p/socket_client.h b/third_party/blink/renderer/platform/p2p/socket_client.h
similarity index 69%
rename from third_party/blink/public/platform/modules/p2p/socket_client.h
rename to third_party/blink/renderer/platform/p2p/socket_client.h
index 6d7fe7a..4b0ef9b8 100644
--- a/third_party/blink/public/platform/modules/p2p/socket_client.h
+++ b/third_party/blink/renderer/platform/p2p/socket_client.h
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_SOCKET_CLIENT_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_SOCKET_CLIENT_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_H_
 
 #include <stdint.h>
 
-#include <vector>
-
 #include "net/base/ip_endpoint.h"
 #include "services/network/public/cpp/p2p_socket_type.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace rtc {
 struct PacketOptions;
@@ -22,8 +21,10 @@
 
 // P2P socket that routes all calls over IPC.
 //
-// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
-// all users of it have been Onion souped. Also, move it away from std::vector.
+// TODO(crbug.com/787254): Verify whether this class is still needed
+// now that all its clients are in Blink.
+//
+// Also, move it away from std::vector.
 class P2PSocketClient {
  public:
   virtual ~P2PSocketClient() {}
@@ -31,7 +32,7 @@
   // Send the |data| to the |address| using Differentiated Services Code Point
   // |dscp|. Return value is the unique packet_id for this packet.
   virtual uint64_t Send(const net::IPEndPoint& address,
-                        const std::vector<int8_t>& data,
+                        const Vector<int8_t>& data,
                         const rtc::PacketOptions& options) = 0;
 
   virtual void SetOption(network::P2PSocketOption option, int value) = 0;
@@ -47,4 +48,4 @@
 };
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_P2P_SOCKET_CLIENT_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_H_
diff --git a/third_party/blink/renderer/platform/p2p/socket_client_impl.cc b/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
index f6fcb5b..65a8945 100644
--- a/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
+++ b/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
@@ -67,7 +67,7 @@
 }
 
 uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint& address,
-                                   const std::vector<int8_t>& data,
+                                   const Vector<int8_t>& data,
                                    const rtc::PacketOptions& options) {
   uint64_t unique_id = GetUniqueId(random_socket_id_, ++next_packet_id_);
 
@@ -81,19 +81,12 @@
 }
 
 void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint& address,
-                                           const std::vector<int8_t>& data,
+                                           const Vector<int8_t>& data,
                                            const rtc::PacketOptions& options,
                                            uint64_t packet_id) {
   TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id);
 
-  // TODO(crbug.com/787254): Remove this helper when socket_client.h gets moved
-  // from blink/public to blink/renderer, and operates over WTF::Vector.
-  Vector<int8_t> copy(data.size());
-  for (size_t i = 0; i < data.size(); i++)
-    copy[i] = data[i];
-
-  socket_->Send(std::move(copy),
-                network::P2PPacketInfo(address, options, packet_id),
+  socket_->Send(data, network::P2PPacketInfo(address, options, packet_id),
                 net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
 }
 
diff --git a/third_party/blink/renderer/platform/p2p/socket_client_impl.h b/third_party/blink/renderer/platform/p2p/socket_client_impl.h
index daac33d..080c3fa5 100644
--- a/third_party/blink/renderer/platform/p2p/socket_client_impl.h
+++ b/third_party/blink/renderer/platform/p2p/socket_client_impl.h
@@ -7,8 +7,6 @@
 
 #include <stdint.h>
 
-#include <vector>
-
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
@@ -17,7 +15,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/p2p_socket_type.h"
 #include "services/network/public/mojom/p2p.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/p2p/socket_client.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace base {
@@ -52,7 +50,7 @@
   // Send the |data| to the |address| using Differentiated Services Code Point
   // |dscp|. Return value is the unique packet_id for this packet.
   uint64_t Send(const net::IPEndPoint& address,
-                const std::vector<int8_t>& data,
+                const Vector<int8_t>& data,
                 const rtc::PacketOptions& options) override;
 
   // Setting socket options.
@@ -80,7 +78,7 @@
   // Helper function to be called by Send to handle different threading
   // condition.
   void SendWithPacketId(const net::IPEndPoint& address,
-                        const std::vector<int8_t>& data,
+                        const Vector<int8_t>& data,
                         const rtc::PacketOptions& options,
                         uint64_t packet_id);
 
diff --git a/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc b/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
index 19c50b0..c82473e 100644
--- a/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
+++ b/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
@@ -8,8 +8,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "services/network/public/cpp/p2p_param_traits.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_observer.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
 #include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/p2p/socket_dispatcher.h b/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
index cb8a85f..5342377 100644
--- a/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
+++ b/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
@@ -35,7 +35,7 @@
 #include "net/base/network_interfaces.h"
 #include "services/network/public/cpp/p2p_socket_type.h"
 #include "services/network/public/mojom/p2p.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
@@ -85,6 +85,8 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
 
+  // TODO(crbug.com/787254): When moving NetworkListObserver to Oilpan,
+  // thread-safety needs to be taken into account.
   scoped_refptr<base::ObserverListThreadSafe<blink::NetworkListObserver>>
       network_list_observers_;
 
diff --git a/third_party/blink/renderer/platform/peerconnection/DEPS b/third_party/blink/renderer/platform/peerconnection/DEPS
index c422df2..5bff309 100644
--- a/third_party/blink/renderer/platform/peerconnection/DEPS
+++ b/third_party/blink/renderer/platform/peerconnection/DEPS
@@ -3,6 +3,7 @@
     "-third_party/blink/renderer/platform",
 
     # Module.
+    "+third_party/blink/renderer/platform/p2p",
     "+third_party/blink/renderer/platform/peerconnection",
     "+third_party/blink/renderer/platform/media_capabilities",
     "+third_party/blink/renderer/platform/webrtc",
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
index ba2a0ab10..2ab30075 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc
@@ -10,7 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
 
 namespace blink {
@@ -59,11 +58,6 @@
 
 }  // namespace
 
-std::unique_ptr<webrtc::VideoDecoderFactory> CreateRTCVideoDecoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories) {
-  return std::make_unique<RTCVideoDecoderFactory>(gpu_factories);
-}
-
 RTCVideoDecoderFactory::RTCVideoDecoderFactory(
     media::GpuVideoAcceleratorFactories* gpu_factories)
     : gpu_factories_(gpu_factories) {
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
index a0943b8..fc5bcb11 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
@@ -11,7 +11,6 @@
 #include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
 #include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder.h"
@@ -104,11 +103,6 @@
 
 }  // anonymous namespace
 
-std::unique_ptr<webrtc::VideoEncoderFactory> CreateRTCVideoEncoderFactory(
-    media::GpuVideoAcceleratorFactories* gpu_factories) {
-  return std::make_unique<RTCVideoEncoderFactory>(gpu_factories);
-}
-
 RTCVideoEncoderFactory::RTCVideoEncoderFactory(
     media::GpuVideoAcceleratorFactories* gpu_factories)
     : gpu_factories_(gpu_factories) {
diff --git a/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h b/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h
index 4ee1273..223e0145 100644
--- a/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h
+++ b/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_manager.h"
-#include "third_party/blink/public/platform/modules/p2p/network_list_observer.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/webrtc/p2p/stunprober/stun_prober.h"
 #include "third_party/webrtc/rtc_base/network.h"
diff --git a/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc b/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
index 753f0e8..9ce0d60 100644
--- a/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
+++ b/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
@@ -11,10 +11,10 @@
 #include "base/logging.h"
 #include "base/system/sys_info.h"
 #include "third_party/blink/public/platform/modules/peerconnection/audio_codec_factory.h"
-#include "third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
 #include "third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
 #include "third_party/webrtc/api/audio_codecs/audio_encoder_factory.h"
 #include "third_party/webrtc/api/audio_codecs/audio_format.h"
diff --git a/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc b/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
index 5adc8b1..85ae4df 100644
--- a/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/public/platform/modules/peerconnection/video_codec_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
 
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h"
 #include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h"
 #include "third_party/webrtc/media/base/codec.h"
@@ -178,7 +178,7 @@
 
   if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
       Platform::Current()->IsWebRtcHWEncodingEnabled()) {
-    encoder_factory = blink::CreateRTCVideoEncoderFactory(gpu_factories);
+    encoder_factory = std::make_unique<RTCVideoEncoderFactory>(gpu_factories);
   }
 
 #if defined(OS_ANDROID)
@@ -195,7 +195,7 @@
 
   if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
       Platform::Current()->IsWebRtcHWDecodingEnabled()) {
-    decoder_factory = blink::CreateRTCVideoDecoderFactory(gpu_factories);
+    decoder_factory = std::make_unique<RTCVideoDecoderFactory>(gpu_factories);
   }
 
   return std::make_unique<DecoderAdapter>(std::move(decoder_factory));
diff --git a/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h b/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h
new file mode 100644
index 0000000..522d9ae
--- /dev/null
+++ b/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
+
+namespace media {
+class GpuVideoAcceleratorFactories;
+}
+
+namespace blink {
+
+PLATFORM_EXPORT std::unique_ptr<webrtc::VideoEncoderFactory>
+CreateWebrtcVideoEncoderFactory(
+    media::GpuVideoAcceleratorFactories* gpu_factories);
+PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoderFactory>
+CreateWebrtcVideoDecoderFactory(
+    media::GpuVideoAcceleratorFactories* gpu_factories);
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
index 98213870..79f9842 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -73,7 +73,7 @@
     'Fuchsia',
     'IOS', 'IOS12.2', 'IOS13.0',
     'Linux',
-    'Mac', 'Retina', 'Mac10.10', 'Mac10.11', 'Mac10.12', 'Mac10.13', 'Mac10.14', 'Mac10.15',
+    'Mac', 'Mac10.10', 'Mac10.11', 'Retina', 'Mac10.12', 'Mac10.13',
     'Win', 'Win7', 'Win10'
 ]
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py
index 8a01764e..07f0dc83 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -129,8 +129,6 @@
         ('mac10.11', 'x86'),
         ('mac10.12', 'x86'),
         ('mac10.13', 'x86'),
-        ('mac10.14', 'x86'),
-        ('mac10.15', 'x86'),
         ('win7', 'x86'),
         ('win10', 'x86'),
         ('trusty', 'x86_64'),
@@ -142,7 +140,7 @@
     )
 
     CONFIGURATION_SPECIFIER_MACROS = {
-        'mac': ['retina', 'mac10.10', 'mac10.11', 'mac10.12', 'mac10.13', 'mac10.14', 'mac10.15'],
+        'mac': ['retina', 'mac10.10', 'mac10.11', 'mac10.12', 'mac10.13'],
         'win': ['win7', 'win10'],
         'linux': ['trusty'],
         'fuschia': ['fuchsia'],
diff --git a/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run-expected.txt b/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run-expected.txt
index 616fff3..6503b21 100644
--- a/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run-expected.txt
@@ -14,6 +14,13 @@
 URL: http://127.0.0.1:8000/devtools/audits/resources/audits-emulate-pass.html
 Version: 5.2.0
 TestedAsMobileDevice: true
+ViewportDimensions: {
+  "innerWidth": 412,
+  "innerHeight": 660,
+  "outerWidth": 412,
+  "outerHeight": 660,
+  "devicePixelRatio": 2.625
+}
 
 
 content-width: pass 
diff --git a/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run.js b/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run.js
index a541927..d55b64f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run.js
+++ b/third_party/blink/web_tests/http/tests/devtools/audits/audits-emulate-run.js
@@ -17,6 +17,7 @@
   TestRunner.addResult(`URL: ${lhr.finalUrl}`);
   TestRunner.addResult(`Version: ${lhr.lighthouseVersion}`);
   TestRunner.addResult(`TestedAsMobileDevice: ${artifacts.TestedAsMobileDevice}`);
+  TestRunner.addResult(`ViewportDimensions: ${JSON.stringify(artifacts.ViewportDimensions, null, 2)}`);
   TestRunner.addResult('\n');
 
   const auditName = 'content-width';
diff --git a/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run-expected.txt b/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run-expected.txt
index 47ca57b..a85d484 100644
--- a/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run-expected.txt
@@ -284,6 +284,13 @@
 URL: http://127.0.0.1:8000/devtools/resources/inspected-page.html
 Version: 5.2.0
 TestedAsMobileDevice: true
+ViewportDimensions: {
+  "innerWidth": 981,
+  "innerHeight": 1570,
+  "outerWidth": 412,
+  "outerHeight": 660,
+  "devicePixelRatio": 2.625
+}
 
 
 accesskeys: notApplicable
diff --git a/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run.js b/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run.js
index 926bb73..9a8930f0 100644
--- a/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run.js
+++ b/third_party/blink/web_tests/http/tests/devtools/audits/audits-successful-run.js
@@ -50,6 +50,7 @@
   TestRunner.addResult(`URL: ${lhr.finalUrl}`);
   TestRunner.addResult(`Version: ${lhr.lighthouseVersion}`);
   TestRunner.addResult(`TestedAsMobileDevice: ${artifacts.TestedAsMobileDevice}`);
+  TestRunner.addResult(`ViewportDimensions: ${JSON.stringify(artifacts.ViewportDimensions, null, 2)}`);
   TestRunner.addResult('\n');
 
   Object.keys(lhr.audits).sort().forEach(auditName => {
diff --git a/third_party/closure_compiler/externs/resources_private.js b/third_party/closure_compiler/externs/resources_private.js
new file mode 100644
index 0000000..5da390a7
--- /dev/null
+++ b/third_party/closure_compiler/externs/resources_private.js
@@ -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.
+
+/**
+ * @const
+ */
+chrome.resourcesPrivate = {};
+
+/**
+ * Records a value than can range from 1 to 1,000,000.
+ * @param {string} component
+ * @param {!function(Object)} callback Callback to handle the dictionary of
+ *     localized strings for |component|.
+ */
+chrome.resourcesPrivate.getStrings = function(component, callback) {};
diff --git a/third_party/webxr_test_pages/webxr-samples/360-photos.html b/third_party/webxr_test_pages/webxr-samples/360-photos.html
index db7fdfe..b05a644 100644
--- a/third_party/webxr_test_pages/webxr-samples/360-photos.html
+++ b/third_party/webxr_test_pages/webxr-samples/360-photos.html
@@ -89,7 +89,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -129,9 +136,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -158,6 +171,8 @@
           }
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
index 344aea0..261d99e 100644
--- a/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
+++ b/third_party/webxr_test_pages/webxr-samples/fallback-rendering.html
@@ -89,7 +89,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local'] });
+              }, { once: true });
+            })
+          });
         } else {
           // If navigator.xr isn't present in the browser then we need to use
           // the fallback rendering path.
@@ -148,9 +155,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -177,6 +190,8 @@
           }
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/input-tracking.html b/third_party/webxr_test_pages/webxr-samples/input-tracking.html
index bf36518bb..40fbdd6 100644
--- a/third_party/webxr_test_pages/webxr-samples/input-tracking.html
+++ b/third_party/webxr_test_pages/webxr-samples/input-tracking.html
@@ -89,7 +89,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline').then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -136,9 +143,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -171,6 +184,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/positional-audio.html b/third_party/webxr_test_pages/webxr-samples/positional-audio.html
index bc39c8f..441485ba 100644
--- a/third_party/webxr_test_pages/webxr-samples/positional-audio.html
+++ b/third_party/webxr_test_pages/webxr-samples/positional-audio.html
@@ -307,7 +307,14 @@
             scene.addNode(playButton);
           });
 
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              })
+            }, { once: true });
+          });
         } else {
           initFallback();
         }
@@ -349,10 +356,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode) {
-          session.mode = 'inline';
-        }
         session.addEventListener('end', onSessionEnded);
 
         session.addEventListener('selectstart', onSelectStart);
@@ -394,6 +406,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
index 97b24e6..8ca7017 100644
--- a/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
+++ b/third_party/webxr_test_pages/webxr-samples/reduced-bind-rendering.html
@@ -85,7 +85,7 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline').then(onSessionStarted);
+          requestInlineSession();
         } else {
           initFallback();
         }
@@ -133,9 +133,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -162,6 +168,8 @@
           }
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/room-scale.html b/third_party/webxr_test_pages/webxr-samples/room-scale.html
index 6d2a958..a903ccc0 100644
--- a/third_party/webxr_test_pages/webxr-samples/room-scale.html
+++ b/third_party/webxr_test_pages/webxr-samples/room-scale.html
@@ -90,7 +90,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              })
+            }, { once: true });
+          });
         } else {
           initFallback();
         }
@@ -111,6 +118,14 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function initGL() {
         if (gl)
           return;
@@ -144,8 +159,6 @@
       }
 
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.ended = false;
         session.addEventListener('end', onSessionEnded);
 
@@ -197,6 +210,8 @@
             pollBounds(session);
           }
         });
+
+        return session;
       }
 
       function sleep(ms) {
diff --git a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html
index 1c37b5b..ac4752d 100644
--- a/third_party/webxr_test_pages/webxr-samples/spectator-mode.html
+++ b/third_party/webxr_test_pages/webxr-samples/spectator-mode.html
@@ -99,11 +99,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']})
-              .then((session) => {
-                session.mode = 'inline';
-                onSessionStarted(session);
-              });
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              })
+            }, { once: true });
+          });
         } else {
           initFallback();
         }
@@ -159,6 +162,14 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
         session.addEventListener('end', onSessionEnded);
 
@@ -187,6 +198,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/stereo-video.html b/third_party/webxr_test_pages/webxr-samples/stereo-video.html
index c6fd575..1dbbedc 100644
--- a/third_party/webxr_test_pages/webxr-samples/stereo-video.html
+++ b/third_party/webxr_test_pages/webxr-samples/stereo-video.html
@@ -140,7 +140,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -180,10 +187,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode) {
-          session.mode = 'inline';
-        }
         session.addEventListener('end', onSessionEnded);
         session.addEventListener('select', (ev) => {
           let refSpace = ev.frame.session.mode.startsWith('immersive') ?
@@ -221,6 +233,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/teleportation.html b/third_party/webxr_test_pages/webxr-samples/teleportation.html
index b0407eb1..37ff7318 100644
--- a/third_party/webxr_test_pages/webxr-samples/teleportation.html
+++ b/third_party/webxr_test_pages/webxr-samples/teleportation.html
@@ -113,11 +113,13 @@
         xrButton.addToHeader();
 
         if (navigator.xr) {
-          const mode = 'inline';
-          navigator.xr.requestSession(mode, {optionalFeatures: ['local-floor']})
+          requestInlineSession()
           .then((session) => {
-            session.mode = mode;
-            onSessionStarted(session);
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              }, { once: true });
+            })
           });
         } else {
           // Still render the initial scene if WebXR is not available.
@@ -209,10 +211,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode) {
-          session.mode = 'inline';
-        }
 
         session.addEventListener('end', onSessionEnded);
 
@@ -260,6 +267,8 @@
             session.requestAnimationFrame(onXRFrame);
           });
         });
+
+        return session;
       }
 
       // Used for updating the origin offset.
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html
index 0645c76f..c853738 100644
--- a/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html
+++ b/third_party/webxr_test_pages/webxr-samples/tests/cube-sea.html
@@ -267,7 +267,14 @@
         if (navigator.xr) {
           // Set up "magic window" mode.
           if (appSettings.magicWindow) {
-            navigator.xr.requestSession('inline', {optionalFeatures: ['local']}).then(onSessionStarted);
+            requestInlineSession()
+            .then((session) => {
+              gl.canvas.addEventListener('touchend', () => {
+                session.end().then(() => {
+                  requestInlineSession({ optionalFeatures: ['local'] });
+                }, { once: true });
+              })
+            });
           }
         } else {
           initFallback();
@@ -303,6 +310,14 @@
         scene.inputRenderer.setControllerMesh(new Gltf2Node({url: '../media/gltf/controller/controller.gltf'}));
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onRequestSession() {
         let xrMode = appSettings.arMode ? 'immersive-ar' : 'immersive-vr';
         navigator.xr.requestSession(xrMode).then((session) => {
@@ -313,8 +328,6 @@
       }
 
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -342,6 +355,8 @@
           }
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html
index 27791fb..f3c0fce 100644
--- a/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html
+++ b/third_party/webxr_test_pages/webxr-samples/tests/offscreen-canvas.html
@@ -87,7 +87,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local'] });
+              }, { once: true });
+            })
+          });
         }
       }
 
@@ -113,9 +120,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         initGL();
@@ -142,6 +155,8 @@
           }
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html
index bf84820..f391460 100644
--- a/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html
+++ b/third_party/webxr_test_pages/webxr-samples/tests/permission-request.html
@@ -98,7 +98,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -231,10 +238,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode) {
-          session.mode = 'inline';
-        }
         session.addEventListener('end', onSessionEnded);
 
         session.addEventListener('select', (ev) => {
@@ -274,6 +286,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onEndSession(session) {
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html
index 7896e46..ed4aca47 100644
--- a/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html
+++ b/third_party/webxr_test_pages/webxr-samples/tests/pointer-painter.html
@@ -87,7 +87,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -129,9 +136,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode)
-          session.mode = 'inline';
         session.addEventListener('end', onSessionEnded);
 
         session.addEventListener('selectstart', onSelectStart);
@@ -168,6 +181,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       let selecting = false;
diff --git a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html
index abed34e1..f676309 100644
--- a/third_party/webxr_test_pages/webxr-samples/tests/sponza.html
+++ b/third_party/webxr_test_pages/webxr-samples/tests/sponza.html
@@ -96,7 +96,14 @@
         document.querySelector('header').appendChild(xrButton.domElement);
 
         if (navigator.xr) {
-          navigator.xr.requestSession('inline', {optionalFeatures: ['local-floor']}).then(onSessionStarted);
+          requestInlineSession()
+          .then((session) => {
+            gl.canvas.addEventListener('touchend', () => {
+              session.end().then(() => {
+                requestInlineSession({ optionalFeatures: ['local-floor'] });
+              }, { once: true });
+            })
+          });
         } else {
           initFallback();
         }
@@ -141,10 +148,15 @@
         });
       }
 
+      function requestInlineSession(options) {
+        return navigator.xr.requestSession('inline', options)
+          .then((session) => {
+            session.mode = 'inline';
+            return onSessionStarted(session);
+          });
+      }
+
       function onSessionStarted(session) {
-        if (!session.mode) {
-          session.mode = 'inline';
-        }
 
         session.addEventListener('end', onSessionEnded);
 
@@ -177,6 +189,8 @@
 
           session.requestAnimationFrame(onXRFrame);
         });
+
+        return session;
       }
 
       function onSelect(ev) {
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index 17f6778..3a980d9 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -33,9 +33,6 @@
     <classpathentry kind="src" path="chrome/android/java/src"/>
     <classpathentry kind="src" path="chrome/android/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/junit/src"/>
-    <classpathentry kind="src" path="chrome/android/touchless/fallback/java/src"/>
-    <classpathentry kind="src" path="chrome/android/touchless/java/src"/>
-    <classpathentry kind="src" path="chrome/android/touchless/javatests/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/client/junit/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/client/src"/>
     <classpathentry kind="src" path="chrome/android/webapk/libs/common/src"/>
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index e612679..6d2784a 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -399,34 +399,32 @@
       return self._RunLocallyIsolated(self.args.path, self.args.target)
 
   def CmdZip(self):
-      ret = self.CmdIsolate()
-      if ret:
-          return ret
+    ret = self.CmdIsolate()
+    if ret:
+      return ret
 
-      zip_dir = None
-      try:
-          zip_dir = self.TempDir()
-          remap_cmd = [
-            self.executable,
-            self.PathJoin(self.chromium_src_dir, 'tools', 'swarming_client',
-                          'isolate.py'),
-            'remap',
-            '--collapse_symlinks',
-            '-s', self.PathJoin(self.args.path, self.args.target + '.isolated'),
-            '-o', zip_dir
-          ]
-          self.Run(remap_cmd)
+    zip_dir = None
+    try:
+      zip_dir = self.TempDir()
+      remap_cmd = [
+          self.executable,
+          self.PathJoin(self.chromium_src_dir, 'tools', 'swarming_client',
+                        'isolate.py'), 'remap', '--collapse_symlinks', '-s',
+          self.PathJoin(self.args.path, self.args.target + '.isolated'), '-o',
+          zip_dir
+      ]
+      self.Run(remap_cmd)
 
-          zip_path = self.args.zip_path
-          with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED,
-                               allowZip64=True) as fp:
-              for root, _, files in os.walk(zip_dir):
-                  for filename in files:
-                      path = self.PathJoin(root, filename)
-                      fp.write(path, self.RelPath(path, zip_dir))
-      finally:
-          if zip_dir:
-              self.RemoveDirectory(zip_dir)
+      zip_path = self.args.zip_path
+      with zipfile.ZipFile(
+          zip_path, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) as fp:
+        for root, _, files in os.walk(zip_dir):
+          for filename in files:
+            path = self.PathJoin(root, filename)
+            fp.write(path, self.RelPath(path, zip_dir))
+    finally:
+      if zip_dir:
+        self.RemoveDirectory(zip_dir)
 
   @staticmethod
   def _AddBaseSoftware(cmd):
@@ -806,8 +804,8 @@
         vals['cros_passthrough'] = mixin_vals['cros_passthrough']
       if 'args_file' in mixin_vals:
         if vals['args_file']:
-            raise MBErr('args_file specified multiple times in mixins '
-                        'for %s on %s' % (self.args.builder, self.args.master))
+          raise MBErr('args_file specified multiple times in mixins '
+                      'for %s on %s' % (self.args.builder, self.args.master))
         vals['args_file'] = mixin_vals['args_file']
       if 'gn_args' in mixin_vals:
         if vals['gn_args']:
@@ -888,10 +886,10 @@
     ret, output, _ = self.Run(self.GNCmd('ls', build_dir),
                               force_verbose=False)
     if ret:
-        # If `gn ls` failed, we should exit early rather than trying to
-        # generate isolates.
-        self.Print('GN ls failed: %d' % ret)
-        return ret
+      # If `gn ls` failed, we should exit early rather than trying to
+      # generate isolates.
+      self.Print('GN ls failed: %d' % ret)
+      return ret
 
     # Create a reverse map from isolate label to isolate dict.
     isolate_map = self.ReadIsolateMap()
@@ -1307,7 +1305,7 @@
     msan = 'is_msan=true' in vals['gn_args']
     tsan = 'is_tsan=true' in vals['gn_args']
     cfi_diag = 'use_cfi_diag=true' in vals['gn_args']
-    java_coverage = 'jacoco_coverage=true' in vals['gn_args']
+    java_coverage = 'use_jacoco_coverage=true' in vals['gn_args']
 
     test_type = isolate_map[target]['type']
     use_python3 = isolate_map[target].get('use_python3', False)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 8a6040f..c6d27e7 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -2260,7 +2260,7 @@
     },
 
     'java_coverage': {
-      'gn_args': 'jacoco_coverage=true',
+      'gn_args': 'use_jacoco_coverage=true',
     },
 
     'jumbo': {
@@ -2350,6 +2350,8 @@
     # https://cs.chromium.org/chromium/build/scripts/slave/recipe_modules/code_coverage/api.py
     # and
     # https://cs.chromium.org/chromium/src/docs/clang_code_coverage_wrapper.md
+    # For Java, see:
+    # https://cs.chromium.org/chromium/src/build/android/gyp/jacoco_instr.py
     'partial_code_coverage_instrumentation': {
       'gn_args': 'coverage_instrumentation_input_file="//.code-coverage/files_to_instrument.txt"'
     },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 2acac49..e0cb79f 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -2319,6 +2319,22 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="ApplicationShortcut.NewIncognitoSearchPressed">
+  <owner>pschaffner@chromium.com</owner>
+  <description>
+    Force pressed on a springboard shortcut and tapped Incognito Search in
+    Chrome for iOS.
+  </description>
+</action>
+
+<action name="ApplicationShortcut.NewSearchPressed">
+  <owner>pschaffner@chromium.com</owner>
+  <description>
+    Force pressed on a springboard shortcut and tapped New Search in Chrome for
+    iOS.
+  </description>
+</action>
+
 <action name="AppList_AutoLaunchCanceled">
   <obsolete>Voice search in Launcher is not supported anymore.</obsolete>
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c374781d..051dc23 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -34877,6 +34877,7 @@
       label="OmniboxUIExperimentHideSteadyStateUrlTrivialSubdomains:enabled"/>
   <int value="-1930720286" label="nacl-debug-mask"/>
   <int value="-1928198763" label="enable-async-dns"/>
+  <int value="-1927080237" label="Vulkan:enabled"/>
   <int value="-1925117279" label="disable-quic-https"/>
   <int value="-1925106340" label="CameraSystemWebApp:disabled"/>
   <int value="-1919199528"
@@ -37109,6 +37110,7 @@
   <int value="1090377940" label="enable-quic-https"/>
   <int value="1091631619" label="disable-accelerated-video-encode"/>
   <int value="1092896354" label="EnableFullscreenAppList:disabled"/>
+  <int value="1094095931" label="enable-vulkan"/>
   <int value="1094506652" label="UseGoogleLocalNtp:enabled"/>
   <int value="1095061640" label="enable-prominent-url-app-flow"/>
   <int value="1096477444" label="AssistantVoiceMatch:enabled"/>
@@ -37185,6 +37187,7 @@
   <int value="1198839129" label="OfflinePagesLivePageSharing:enabled"/>
   <int value="1201008500"
       label="EnableAmbientAuthenticationInIncognito:enabled"/>
+  <int value="1203821857" label="Vulkan:disabled"/>
   <int value="1205849612" label="enable-sync-synced-notifications"/>
   <int value="1209221384" label="enable-experimental-accessibility-features"/>
   <int value="1210343926" label="enable-drop-sync-credential"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 1c4f816..bdd322e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -24853,7 +24853,8 @@
   </summary>
 </histogram>
 
-<histogram name="Cookie.TimeKeyLoadTotalWait" units="ms" expires_after="M77">
+<histogram name="Cookie.TimeKeyLoadTotalWait" units="ms"
+    expires_after="2020-03-15">
   <owner>erikchen@chromium.org</owner>
   <summary>
     This histogram records the the total amount of time spent fetching the
@@ -26083,7 +26084,7 @@
 </histogram>
 
 <histogram name="CryptAuth.ClientAppMetadataInstanceIdTokenFetch.Result"
-    enum="InstanceIDResult" expires_after="2019-11-01">
+    enum="InstanceIDResult" expires_after="2020-03-15">
   <owner>jlklein@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <summary>
@@ -37429,7 +37430,7 @@
 </histogram>
 
 <histogram name="Event.FrameEventRouting.TouchEventAckQueueSize" units="units"
-    expires_after="2019-12-31">
+    expires_after="2020-03-15">
   <owner>wjmaclean@chromium.org</owner>
   <owner>kenrb@chromium.org</owner>
   <summary>
@@ -120906,7 +120907,7 @@
 </histogram>
 
 <histogram name="SB2.NoUserActionResourceLoadingDelay" units="ms"
-    expires_after="M77">
+    expires_after="2020-03-15">
   <obsolete>
     Removed in M77 since it is fairly flat and not really useful.
   </obsolete>
@@ -148529,7 +148530,7 @@
 </histogram>
 
 <histogram name="UMA.ClientIdBackupRecoveredWithAge" units="hours"
-    expires_after="M77">
+    expires_after="2020-03-15">
   <owner>gab@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -149511,7 +149512,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2020-03-08">
+    expires_after="2020-03-15">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/review_guidelines.md b/tools/metrics/histograms/review_guidelines.md
new file mode 100644
index 0000000..237443c
--- /dev/null
+++ b/tools/metrics/histograms/review_guidelines.md
@@ -0,0 +1,140 @@
+# Things to note when doing metrics code review.
+
+[TOC]
+
+This covers how to review metrics code in the Chromium codebase.
+
+## Reviewing UMA Histograms
+
+### What is covered under review?
+
+During code review ensure the following -
+
+#### XML metadata in histograms.xml is correct and descriptive.
+
+*   Verify the histogram is created under the right histogram 'namespace'.
+    (i.e if the histogram name is A.B.C, then A is the histogram namespace).
+    If this is a new one, check if there a similar one that already exists?
+
+*   Histogram owners match the [histogram owners guidelines]
+    (https://chromium.googlesource.com/chromium/src/+/HEAD/tools/metrics/histograms/README.md#owners).
+
+*   If generating multiple histograms programmatically or defining common set of
+    histogram, guide them to use [histogram-suffixes]
+    (https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/master/metrics/histograms/README.md#Histogram-Suffixes).
+
+*   Verify that expires_after is reasonable. CL author should be able to justify
+    it. See our guidance at on [histogram-expiry]
+    (https://chromium.googlesource.com/chromium/src/+/HEAD/tools/metrics/histograms/README.md#Histogram-Expiry).
+
+*   Summary section should describe what is measured, when is it recorded and
+    when not. The summary should generally describe a single emission of sample
+    and not the statistics in aggregate.
+
+*   If the histogram is recorded only for some platforms, then it should be
+    included in the summary (Unless part of name).
+
+*   Histogram and enum names don't include special characters besides dot,
+    underscores or slashes.
+
+#### Histogram is designed correctly.
+
+*   Verify that the histogram follows the
+    [UMA histogram design recommendation](https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md).
+    If issues are found please link to docs in your review comments to
+    increase their visibility.
+
+#### Histogram is setup correctly.
+
+*   If modifying an existing histogram, request that the histogram be
+    renamed if its meaning has changed significantly. Common practices are to
+    add suffix such as 2 to the name. When doing so the existing entry for the
+    histogram should also be kept but with `<obsolete>` tag.
+
+*   Don't allow deleting histograms or enum buckets unless there is a *very*
+    compelling reason to do so (e.g. never logged). Instead they should be
+    marked as obsolete with `<obsolete>` tag.
+
+*   Re-naming enum bucket values is not allowed as these break backward
+    compatibility wrt the data stored. When modifying enums it is better to add
+    new values to the enum instead of re-purposing existing enum values.
+
+    *   Modifying labels / summary is safe and allowed without review. However,
+        if reviewing these changes make sure the semantic meaning of the bucket
+        remain unchanged. e.g re-labeling 'Has Error' to 'Has Warning' should
+        not be allowed, while re-labeling 'Has Error' to 'Has Error (e.g this
+        and that error)' is okay.
+
+*   Verify that histogram buckets are not a privacy risk. Some of the types
+    forbidden are if the buckets are encoding page contents, URL or is including
+    any other type of PII or sensitive information. If during review you are
+    unsure then please loop in Chrome Privacy Team in the review.
+
+*   Check that the histogram bucket space of all possible values for all clients
+    will be limited to 50 generally. It should not exceed 100 unless the CL
+    author has a justification for having extra buckets.
+
+    *   If the lower bucket counts prove insufficient (e.g after reviewing
+        the data for 50 buckets proves to be unhelpful, more buckets can be
+        requested in a separate review).
+
+    *   When logging hashes in a sparse histogram make sure the global space
+        meet this criterion (not just a client). Another valid case is when
+        logging API error codes which in theory could be potentially large,
+        but on a particular day it is not the case.
+
+*   Check that recorded samples will be within 0 and 2^31-1.
+
+*   If you expect majority of values to be under a certain value, say X,
+    then it's good practice to pick the next order of magnitude - e.g. 10X for
+    the max. This ensures that even outliers will not overflow the distribution.
+
+*   Verify that for an enum histogram, the enum described in enums.xml and the
+    enum defined in the client code matches. And the enum in the code should
+    have a comment mentioning to keep in-sync with enums.xml.
+
+    *   See the sample comment [here]
+        (https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h?rcl=2c99f35f64380ba63c928787834661fbc1fa4234&l=46)
+        . The comment should be similar.
+
+
+*   If the histogram is logged via a macro (rather than a call to the function),
+    check that the names will be constant at runtime.
+
+### What is not covered under review?
+
+*   Metrics team members need not be versed with code where histogram is
+    recorded and are not reviewing all the corner cases associated with
+    collecting the histogram.
+
+*   enums.xml changes don't need our review. But it is still useful to verify
+    that the changes match our guidelines mentioned above.
+
+### User actions specific
+
+*   Verify that the user action logged is actually user triggered. If they
+    are not then advise cl author to convert them to a histogram. However if
+    ordering of actions is the interesting part of their analysis then maybe
+    see if each order combination can become a histogram bucket instead of
+    user action.
+
+*   Don't allow logging of noisy user actions (like scroll events). Typical
+    allowed frequency is to be less frequent than PageLoad or MobilePageLoaded
+    event.
+
+## UKM
+
+*   UKM metrics are to be reviewed by UKM [data privacy owners]
+(https://cs.chromium.org/chromium/src/tools/metrics/ukm/PRIVACY_OWNERS).
+
+*   The metrics must follow the
+    [data collection guideline](/analysis/uma/g3doc/ukm/ukm.md#adding-ukms).
+
+<!--TODO(ukm-team): Add other guidelines for reviewing UKM metrics changes. -->
+
+## Other specialized metrics
+
+ChromeUserMetricsExtension proto include variety of other metrics like -
+Omnibox, Profiler, Stability, etc. These are specialized reviews and should
+be routed to relevant owner. The guidelines here don't cover these cases
+and typically require a server-side review first to change the proto.
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 7046e0d..dd34b26 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -127,10 +127,8 @@
 }
 
 void DelegatedFrameHostAndroid::EvictDelegatedFrame() {
-  if (content_layer_) {
-    content_layer_->SetSurfaceId(viz::SurfaceId(),
-                                 cc::DeadlinePolicy::UseDefaultDeadline());
-  }
+  content_layer_->SetSurfaceId(viz::SurfaceId(),
+                               cc::DeadlinePolicy::UseDefaultDeadline());
   if (!HasSavedFrame() || frame_evictor_->visible())
     return;
   std::vector<viz::SurfaceId> surface_ids = {
@@ -146,8 +144,6 @@
 }
 
 void DelegatedFrameHostAndroid::ResetFallbackToFirstNavigationSurface() {
-  if (!content_layer_)
-    return;
   // Don't update the fallback if it's already newer than the first id after
   // navigation.
   if (content_layer_->oldest_acceptable_fallback() &&
@@ -163,7 +159,7 @@
 }
 
 bool DelegatedFrameHostAndroid::HasDelegatedContent() const {
-  return content_layer_ && content_layer_->surface_id().is_valid();
+  return content_layer_->surface_id().is_valid();
 }
 
 void DelegatedFrameHostAndroid::CompositorFrameSinkChanged() {
@@ -188,7 +184,7 @@
 }
 
 bool DelegatedFrameHostAndroid::IsPrimarySurfaceEvicted() const {
-  return !content_layer_ || !content_layer_->surface_id().is_valid();
+  return !content_layer_->surface_id().is_valid();
 }
 
 bool DelegatedFrameHostAndroid::HasSavedFrame() const {
@@ -277,11 +273,11 @@
 }
 
 bool DelegatedFrameHostAndroid::HasPrimarySurface() const {
-  return content_layer_ && content_layer_->surface_id().is_valid();
+  return content_layer_->surface_id().is_valid();
 }
 
 bool DelegatedFrameHostAndroid::HasFallbackSurface() const {
-  return content_layer_ && content_layer_->oldest_acceptable_fallback() &&
+  return content_layer_->oldest_acceptable_fallback() &&
          content_layer_->oldest_acceptable_fallback()->is_valid();
 }
 
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java
index 10b5805..356f54e 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java
@@ -73,7 +73,10 @@
                 return implContext.getResources();
             }
         };
-        mWindowAndroid = new ActivityWindowAndroid(context);
+        // Use false to disable listening to activity state.
+        // TODO: this should *not* use ActivityWindowAndroid as that relies on Activity, and this
+        // code should not assume it is supplied an Activity.
+        mWindowAndroid = new ActivityWindowAndroid(context, false);
         mContentViewRenderView = new ContentViewRenderView(context);
 
         mContentViewRenderView.onNativeLibraryLoaded(
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
index 7f6069e..ec1e2e5b 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -11,7 +11,6 @@
 import android.os.IBinder;
 import android.util.AndroidRuntimeException;
 
-import org.chromium.base.ApplicationStatus;
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -52,7 +51,6 @@
         });
         ResourceBundle.setNoAvailableLocalePaks();
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
-        ApplicationStatus.initialize(application);
 
         ChildProcessCreationParams.set(implContext.getPackageName(), true /* isExternalService */,
                 LibraryProcessType.PROCESS_CHILD, true /* bindToCaller */,
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
index 39fd147..beec8a0 100644
--- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
+++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/WebLayerShellActivity.java
@@ -64,11 +64,11 @@
 
     @Override
     protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
         // Only call init for main process.
         WebLayer.getInstance().init(getApplication());
 
-        super.onCreate(savedInstanceState);
-
         LinearLayout mainView = new LinearLayout(this);
         int viewId = View.generateViewId();
         mainView.setId(viewId);