diff --git a/DEPS b/DEPS
index ec488d5..f7d91ab 100644
--- a/DEPS
+++ b/DEPS
@@ -142,7 +142,7 @@
   # 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': '8063f6cca02538ef152c2b7afc29d06cb750f034',
+  'skia_revision': '1d105080c423e6c8bbb15da5544a4ff28a8b8570',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -154,15 +154,15 @@
   # 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': 'ecaebd0fc645453384d953187d35ae16b0008b33',
+  'angle_revision': 'c26b7914f03fc3c0f5e2fe2aff9c461acbb3f14e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '45d34d25a7331cf74541f4dbdd4811c026243fde',
+  'swiftshader_revision': '49f7037663275f2d537c0bd53cf455d3e605946a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '73bd37c824051aac631abaf567bab7dcd02093df',
+  'pdfium_revision': '5cf6e209650c59fc779e0019b7e6fac39a6ce9f8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -205,7 +205,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'b0d8876c9c6a18c1bd2e0351bb362fffb5d4ab9f',
+  'catapult_revision': '43030745c1c6d42347a4c09d4665ca04b0cdf865',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -261,7 +261,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': 'a6bfc26e5f3510f9ba31046dc64a9b59ad68ea6d',
+  'spv_tools_revision': '37e8f7994644151f425efa5b408d105713d2cd21',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -277,7 +277,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'c9b9290cc8be17e517961cd6974b713f483fdf28',
+  'dawn_revision': '378985847958236708ac72cd7f86b97ed41ba381',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -806,7 +806,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e30471d9785ac39d5dc1da605eac676ad941c6d0',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '28f766851ebb223e99ea2b45e8abe795923b1046',
       'condition': 'checkout_linux',
   },
 
@@ -1255,7 +1255,7 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '7faea1d762fb772875ab6f6635d4bcbe35d27595',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'a7d27d62330bfe35d82430fa8942feb6f5cddbaf',
 
   'src/third_party/r8': {
       'packages': [
@@ -1359,7 +1359,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '91350f8ecf9ab2922ee062c114e4a759f24bd8d0',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '9d96209240f72bf0effcf19b98eda1e21c1538b1',
+    Var('webrtc_git') + '/src.git' + '@' + '656590dabce079db46a7c6676a55cd81268ea786',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1400,7 +1400,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8b0e988a1e4dde2ab8652bbc118e7c4f94476e1a',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7918ff202300f0995085149a3e295ba56fa8a2a3',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 5c64506a..6df39c48 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2639,7 +2639,8 @@
                    'jhawkins+watch@chromium.org',
                    'jordynass+watch@chromium.org',
                    'maybelle+watch@chromium.org'],
-    'web_applications': ['dominickn+watch-web_applications@chromium.org',
+    'web_applications': ['alancutter+chrome-cls@chromium.org',
+                         'dominickn+watch-web_applications@chromium.org',
                          'ericwilligers+watch-bmo@chromium.org',
                          'loyso+watch@chromium.org',
                          'mgiuca+watch@chromium.org',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index f55dd7d..eb30009 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2523,6 +2523,7 @@
     "json/json_writer_unittest.cc",
     "json/string_escape_unittest.cc",
     "lazy_instance_unittest.cc",
+    "location_unittest.cc",
     "logging_unittest.cc",
     "mac/bind_objc_block_unittest.mm",
     "mac/call_with_eh_frame_unittest.mm",
diff --git a/base/location.cc b/base/location.cc
index ed55f09..cf189341 100644
--- a/base/location.cc
+++ b/base/location.cc
@@ -69,6 +69,25 @@
   return Location(function_name, file_name, line_number, RETURN_ADDRESS());
 }
 
+#if SUPPORTS_LOCATION_BUILTINS && BUILDFLAG(ENABLE_LOCATION_SOURCE)
+// static
+NOINLINE Location Location::Current(const char* function_name,
+                                    const char* file_name,
+                                    int line_number) {
+  return Location(function_name, file_name, line_number, RETURN_ADDRESS());
+}
+#elif SUPPORTS_LOCATION_BUILTINS
+// static
+NOINLINE Location Location::Current(const char* file_name) {
+  return Location(file_name, RETURN_ADDRESS());
+}
+#else
+// static
+NOINLINE Location Location::Current() {
+  return Location(nullptr, RETURN_ADDRESS());
+}
+#endif
+
 //------------------------------------------------------------------------------
 NOINLINE const void* GetProgramCounter() {
   return RETURN_ADDRESS();
diff --git a/base/location.h b/base/location.h
index 491cdda..c07e747f 100644
--- a/base/location.h
+++ b/base/location.h
@@ -14,9 +14,23 @@
 #include "base/base_export.h"
 #include "base/debug/debugging_buildflags.h"
 #include "base/hash/hash.h"
+#include "build/build_config.h"
 
 namespace base {
 
+#if defined(__has_builtin)
+// Clang allows detection of these builtins.
+#define SUPPORTS_LOCATION_BUILTINS                                       \
+  (__has_builtin(__builtin_FUNCTION) && __has_builtin(__builtin_FILE) && \
+   __has_builtin(__builtin_LINE))
+#elif defined(COMPILER_GCC) && __GNUC__ >= 7
+// GCC has supported these for a long time, but they point at the function
+// declaration in the case of default arguments, rather than at the call site.
+#define SUPPORTS_LOCATION_BUILTINS 1
+#else
+#define SUPPORTS_LOCATION_BUILTINS 0
+#endif
+
 // Location provides basic info where of an object was constructed, or was
 // significantly brought to life.
 class BASE_EXPORT Location {
@@ -74,6 +88,16 @@
                                  const char* file_name,
                                  int line_number);
 
+#if SUPPORTS_LOCATION_BUILTINS && BUILDFLAG(ENABLE_LOCATION_SOURCE)
+  static Location Current(const char* function_name = __builtin_FUNCTION(),
+                          const char* file_name = __builtin_FILE(),
+                          int line_number = __builtin_LINE());
+#elif SUPPORTS_LOCATION_BUILTINS
+  static Location Current(const char* file_name = __builtin_FILE());
+#else
+  static Location Current();
+#endif
+
  private:
   const char* function_name_ = nullptr;
   const char* file_name_ = nullptr;
diff --git a/base/location_unittest.cc b/base/location_unittest.cc
new file mode 100644
index 0000000..154920b2
--- /dev/null
+++ b/base/location_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/location.h"
+
+#include "base/compiler_specific.h"
+#include "base/debug/debugging_buildflags.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+// This is a typical use: taking Location::Current as a default parameter.
+// So even though this looks contrived, it confirms that such usage works as
+// expected.
+Location WhereAmI(const Location& location = Location::Current()) {
+  return location;
+}
+
+}  // namespace
+
+TEST(LocationTest, CurrentYieldsCorrectValue) {
+  int previous_line = __LINE__;
+  Location here = WhereAmI();
+  EXPECT_NE(here.program_counter(), WhereAmI().program_counter());
+#if SUPPORTS_LOCATION_BUILTINS
+  EXPECT_THAT(here.file_name(), ::testing::EndsWith("location_unittest.cc"));
+#if BUILDFLAG(ENABLE_LOCATION_SOURCE)
+  EXPECT_EQ(here.line_number(), previous_line + 1);
+  EXPECT_STREQ("TestBody", here.function_name());
+#endif
+#endif
+  ALLOW_UNUSED_LOCAL(previous_line);
+}
+
+}  // namespace base
diff --git a/base/memory/platform_shared_memory_region_android.cc b/base/memory/platform_shared_memory_region_android.cc
index 8869847..538b18b 100644
--- a/base/memory/platform_shared_memory_region_android.cc
+++ b/base/memory/platform_shared_memory_region_android.cc
@@ -8,6 +8,7 @@
 
 #include "base/bits.h"
 #include "base/memory/shared_memory_tracker.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/process_metrics.h"
 #include "third_party/ashmem/ashmem.h"
@@ -22,7 +23,12 @@
 
 namespace {
 
-static int GetAshmemRegionProtectionMask(int fd) {
+// Emits UMA metrics about encountered errors.
+void LogCreateError(PlatformSharedMemoryRegion::CreateError error) {
+  UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error);
+}
+
+int GetAshmemRegionProtectionMask(int fd) {
   int prot = ashmem_get_prot_region(fd);
   if (prot < 0) {
     // TODO(crbug.com/838365): convert to DLOG when bug fixed.
@@ -149,13 +155,17 @@
 // static
 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
                                                               size_t size) {
-  if (size == 0)
+  if (size == 0) {
+    LogCreateError(PlatformSharedMemoryRegion::CreateError::SIZE_ZERO);
     return {};
+  }
 
   // Align size as required by ashmem_create_region() API documentation.
   size_t rounded_size = bits::Align(size, GetPageSize());
-  if (rounded_size > static_cast<size_t>(std::numeric_limits<int>::max()))
+  if (rounded_size > static_cast<size_t>(std::numeric_limits<int>::max())) {
+    LogCreateError(PlatformSharedMemoryRegion::CreateError::SIZE_TOO_LARGE);
     return {};
+  }
 
   CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will "
                                      "lead to this region being non-modifiable";
@@ -165,16 +175,21 @@
   ScopedFD fd(ashmem_create_region(
       SharedMemoryTracker::GetDumpNameForTracing(guid).c_str(), rounded_size));
   if (!fd.is_valid()) {
+    LogCreateError(
+        PlatformSharedMemoryRegion::CreateError::CREATE_FILE_MAPPING_FAILURE);
     DPLOG(ERROR) << "ashmem_create_region failed";
     return {};
   }
 
   int err = ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE);
   if (err < 0) {
+    LogCreateError(
+        PlatformSharedMemoryRegion::CreateError::REDUCE_PERMISSIONS_FAILURE);
     DPLOG(ERROR) << "ashmem_set_prot_region failed";
     return {};
   }
 
+  LogCreateError(PlatformSharedMemoryRegion::CreateError::SUCCESS);
   return PlatformSharedMemoryRegion(std::move(fd), mode, size, guid);
 }
 
diff --git a/base/task/post_task.h b/base/task/post_task.h
index a60c243..09bd82c 100644
--- a/base/task/post_task.h
+++ b/base/task/post_task.h
@@ -80,6 +80,10 @@
 
 // Equivalent to calling PostTask with default TaskTraits.
 BASE_EXPORT bool PostTask(const Location& from_here, OnceClosure task);
+inline bool PostTask(OnceClosure task,
+                     const Location& from_here = Location::Current()) {
+  return PostTask(from_here, std::move(task));
+}
 
 // Equivalent to calling PostDelayedTask with default TaskTraits.
 //
diff --git a/base/threading/sequenced_task_runner_handle_unittest.cc b/base/threading/sequenced_task_runner_handle_unittest.cc
index 35e26d3..f88e6e4 100644
--- a/base/threading/sequenced_task_runner_handle_unittest.cc
+++ b/base/threading/sequenced_task_runner_handle_unittest.cc
@@ -66,9 +66,8 @@
 }
 
 TEST_F(SequencedTaskRunnerHandleTest, NoHandleFromUnsequencedTask) {
-  base::PostTask(FROM_HERE, base::BindOnce([]() {
-                   EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
-                 }));
+  base::PostTask(base::BindOnce(
+      []() { EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet()); }));
   scoped_task_environment_.RunUntilIdle();
 }
 
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 7b5fcea..08be3e99 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -35,7 +35,7 @@
     host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gradle',
     'AndroidManifest.xml')
 _FILE_DIR = os.path.dirname(__file__)
-_SRCJARS_SUBDIR = 'extracted-srcjars'
+_GENERATED_JAVA_SUBDIR = 'generated_java'
 _JNI_LIBS_SUBDIR = 'symlinked-libs'
 _ARMEABI_SUBDIR = 'armeabi'
 _RES_SUBDIR = 'extracted-res'
@@ -213,6 +213,10 @@
       ninja_target = ninja_target[1:]
     return ninja_target.replace(':', os.path.sep)
 
+  def GeneratedJavaSubdir(self):
+    return _RebasePath(
+        os.path.join('gen', self.GradleSubdir(), _GENERATED_JAVA_SUBDIR))
+
   def ProjectName(self):
     """Returns the Gradle project name."""
     return self.GradleSubdir().replace(os.path.sep, '.')
@@ -264,9 +268,6 @@
       self._java_files = java_files
     return self._java_files
 
-  def GeneratedJavaFiles(self):
-    return [p for p in self.JavaFiles() if not p.startswith('..')]
-
   def PrebuiltJars(self):
     all_jars = self.Gradle().get('dependent_prebuilt_jars', [])
     return [i for i in all_jars if i not in _EXCLUDED_PREBUILT_JARS]
@@ -348,12 +349,6 @@
   def _Relativize(self, entry, paths):
     return _RebasePath(paths, self.EntryOutputDir(entry))
 
-  def _Srcjars(self, entry):
-    srcjars = _RebasePath(entry.Gradle().get('bundled_srcjars', []))
-    if not self.use_gradle_process_resources:
-      srcjars += _RebasePath(entry.DepsInfo().get('owned_resource_srcjars', []))
-    return srcjars
-
   def _GetEntries(self, entry):
     if self.split_projects:
       return [entry]
@@ -362,37 +357,23 @@
   def EntryOutputDir(self, entry):
     return os.path.join(self.project_dir, entry.GradleSubdir())
 
-  def AllSrcjars(self, root_entry):
-    srcjars = []
-    for entry in self._GetEntries(root_entry):
-      srcjars += self._Srcjars(entry)
-    return set(srcjars)
-
   def AllResZips(self, root_entry):
     res_zips = []
     for entry in self._GetEntries(root_entry):
       res_zips += entry.ResZips()
     return set(_RebasePath(res_zips))
 
-  def GeneratedInputs(self, root_entry, fast=None):
+  def GeneratedInputs(self, root_entry):
     generated_inputs = set()
-    if not fast:
-      generated_inputs.update(self.AllResZips(root_entry))
-      generated_inputs.update(self.AllSrcjars(root_entry))
+    generated_inputs.update(self.AllResZips(root_entry))
     for entry in self._GetEntries(root_entry):
-      generated_inputs.update(entry.GeneratedJavaFiles())
       generated_inputs.update(entry.PrebuiltJars())
     return generated_inputs
 
-  def GeneratedZips(self, root_entry, fast=None):
+  def GeneratedZips(self, root_entry):
     entry_output_dir = self.EntryOutputDir(root_entry)
-    tuples = []
-    if not fast:
-      tuples.extend((s, os.path.join(entry_output_dir, _SRCJARS_SUBDIR))
-                    for s in self.AllSrcjars(root_entry))
-      tuples.extend((s, os.path.join(entry_output_dir, _RES_SUBDIR))
-                    for s in self.AllResZips(root_entry))
-    return tuples
+    return [(s, os.path.join(entry_output_dir, _RES_SUBDIR))
+            for s in self.AllResZips(root_entry)]
 
   def GenerateManifest(self, root_entry):
     android_manifest = root_entry.DepsInfo().get('android_manifest')
@@ -405,8 +386,8 @@
     # things up at all.
     variables = {}
     java_dirs, excludes = self._GenJavaDirs(root_entry)
-    java_dirs.append(
-        os.path.join(self.EntryOutputDir(root_entry), _SRCJARS_SUBDIR))
+    java_dirs.extend(
+        e.GeneratedJavaSubdir() for e in self._GetEntries(root_entry))
     self.processed_java_dirs.update(java_dirs)
     java_dirs.sort()
     variables['java_dirs'] = self._Relativize(root_entry, java_dirs)
@@ -715,7 +696,7 @@
 
 
 def _ExtractZips(entry_output_dir, zip_tuples):
-  """Extracts all srcjars to the directory given by the tuples."""
+  """Extracts all zips to the directory given in the tuples."""
   extracted_paths = set(s[1] for s in zip_tuples)
   for extracted_path in extracted_paths:
     assert _IsSubpathOf(extracted_path, entry_output_dir)
@@ -804,9 +785,6 @@
                       action='store_true',
                       help='Split projects by their gn deps rather than '
                            'combining all the dependencies of each target')
-  parser.add_argument('--fast',
-                      action='store_true',
-                      help='Skip generating R.java and other generated files.')
   parser.add_argument('--native-target',
                       dest='native_targets',
                       action='append',
@@ -955,16 +933,16 @@
     entries_to_gen.extend(entry.android_test_entries)
     for entry_to_gen in entries_to_gen:
       # Build all paths references by .gradle that exist within output_dir.
-      generated_inputs.update(
-          generator.GeneratedInputs(entry_to_gen, args.fast))
-      zip_tuples.extend(generator.GeneratedZips(entry_to_gen, args.fast))
+      generated_inputs.update(generator.GeneratedInputs(entry_to_gen))
+      zip_tuples.extend(generator.GeneratedZips(entry_to_gen))
   if generated_inputs:
-    logging.warning('Building generated source files...')
     targets = _RebasePath(generated_inputs, output_dir)
     _RunNinja(output_dir, targets)
   if zip_tuples:
+    # This extracts generated xml files (e.g. strings).
     _ExtractZips(generator.project_dir, zip_tuples)
 
+  logging.warning('Generated files will only appear once you\'ve built them.')
   logging.warning('Generated projects for Android Studio %s', channel)
   logging.warning('For more tips: https://chromium.googlesource.com/chromium'
                   '/src.git/+/master/docs/android_studio.md')
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 91e1eb1..a238ecde 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8908966217427053472
\ No newline at end of file
+8908803685201779008
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 8d608c8..b072669 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8908965079969835680
\ No newline at end of file
+8908803680395747664
\ No newline at end of file
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 850fbc4..f98f342 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -187,7 +187,7 @@
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_,
-                                internal_contents_scale_, contents_opaque());
+                                contents_opaque());
 
   // Appends a dummy quad here, which will be updated later once the resource
   // is ready in UpdateHudTexture(). We don't add a TextureDrawQuad directly
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 5acf62e..acdbecbc 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -151,22 +151,32 @@
 }
 
 void LayerImpl::PopulateScaledSharedQuadState(viz::SharedQuadState* state,
-                                              float layer_to_content_scale_x,
-                                              float layer_to_content_scale_y,
+                                              float layer_to_content_scale,
                                               bool contents_opaque) const {
-  gfx::Transform scaled_draw_transform =
-      draw_properties_.target_space_transform;
-  scaled_draw_transform.Scale(SK_MScalar1 / layer_to_content_scale_x,
-                              SK_MScalar1 / layer_to_content_scale_y);
-  gfx::Size scaled_bounds = gfx::ScaleToCeiledSize(
-      bounds(), layer_to_content_scale_x, layer_to_content_scale_y);
-  gfx::Rect scaled_visible_layer_rect = gfx::ScaleToEnclosingRect(
-      visible_layer_rect(), layer_to_content_scale_x, layer_to_content_scale_y);
+  gfx::Size scaled_bounds =
+      gfx::ScaleToCeiledSize(bounds(), layer_to_content_scale);
+  gfx::Rect scaled_visible_layer_rect =
+      gfx::ScaleToEnclosingRect(visible_layer_rect(), layer_to_content_scale);
   scaled_visible_layer_rect.Intersect(gfx::Rect(scaled_bounds));
 
+  PopulateScaledSharedQuadStateWithContentRects(
+      state, layer_to_content_scale, gfx::Rect(scaled_bounds),
+      scaled_visible_layer_rect, contents_opaque);
+}
+
+void LayerImpl::PopulateScaledSharedQuadStateWithContentRects(
+    viz::SharedQuadState* state,
+    float layer_to_content_scale,
+    const gfx::Rect& content_rect,
+    const gfx::Rect& visible_content_rect,
+    bool contents_opaque) const {
+  gfx::Transform scaled_draw_transform =
+      draw_properties_.target_space_transform;
+  scaled_draw_transform.Scale(SK_MScalar1 / layer_to_content_scale,
+                              SK_MScalar1 / layer_to_content_scale);
+
   EffectNode* effect_node = GetEffectTree().Node(effect_tree_index_);
-  state->SetAll(scaled_draw_transform, gfx::Rect(scaled_bounds),
-                scaled_visible_layer_rect,
+  state->SetAll(scaled_draw_transform, content_rect, visible_content_rect,
                 draw_properties().rounded_corner_bounds,
                 draw_properties().clip_rect, draw_properties().is_clipped,
                 contents_opaque, draw_properties().opacity,
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 423eb7b..9b9d883 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -129,13 +129,19 @@
   void PopulateSharedQuadState(viz::SharedQuadState* state,
                                bool contents_opaque) const;
 
-  // If using this, you need to override GetEnclosingRectInTargetSpace() to
+  // If using these two, you need to override GetEnclosingRectInTargetSpace() to
   // use GetScaledEnclosingRectInTargetSpace(). To do otherwise may result in
   // inconsistent values, and drawing/clipping problems.
   void PopulateScaledSharedQuadState(viz::SharedQuadState* state,
-                                     float layer_to_content_scale_x,
-                                     float layer_to_content_scale_y,
+                                     float layer_to_content_scale,
                                      bool contents_opaque) const;
+  void PopulateScaledSharedQuadStateWithContentRects(
+      viz::SharedQuadState* state,
+      float layer_to_content_scale,
+      const gfx::Rect& content_rect,
+      const gfx::Rect& content_visible_rect,
+      bool contents_opaque) const;
+
   // WillDraw must be called before AppendQuads. If WillDraw returns false,
   // AppendQuads and DidDraw will not be called. If WillDraw returns true,
   // DidDraw is guaranteed to be called before another WillDraw or before
diff --git a/cc/layers/mirror_layer_impl.cc b/cc/layers/mirror_layer_impl.cc
index 00de04dc..b36f293 100644
--- a/cc/layers/mirror_layer_impl.cc
+++ b/cc/layers/mirror_layer_impl.cc
@@ -37,19 +37,12 @@
   if (unoccluded_content_rect.IsEmpty())
     return;
 
+  const bool contents_opaque = false;
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
-  bool contents_opaque = false;
-  auto* effect_node = GetEffectTree().Node(effect_tree_index());
-  shared_quad_state->SetAll(
-      draw_properties().target_space_transform, content_rect, content_rect,
-      draw_properties().rounded_corner_bounds, draw_properties().clip_rect,
-      draw_properties().is_clipped, contents_opaque, draw_properties().opacity,
-      effect_node->HasRenderSurface() ? SkBlendMode::kSrcOver
-                                      : effect_node->blend_mode,
-      GetSortingContextId());
-  shared_quad_state->is_fast_rounded_corner =
-      draw_properties().is_fast_rounded_corner;
+  PopulateScaledSharedQuadStateWithContentRects(
+      shared_quad_state, GetIdealContentsScale(), content_rect, content_rect,
+      contents_opaque);
 
   AppendDebugBorderQuad(render_pass, content_rect, shared_quad_state,
                         append_quads_data);
@@ -81,6 +74,10 @@
   return gfx::Rect(bounds());
 }
 
+gfx::Rect MirrorLayerImpl::GetEnclosingRectInTargetSpace() const {
+  return GetScaledEnclosingRectInTargetSpace(GetIdealContentsScale());
+}
+
 const char* MirrorLayerImpl::LayerTypeAsString() const {
   return "cc::MirrorLayerImpl";
 }
diff --git a/cc/layers/mirror_layer_impl.h b/cc/layers/mirror_layer_impl.h
index 0ab1a270..b2e6204 100644
--- a/cc/layers/mirror_layer_impl.h
+++ b/cc/layers/mirror_layer_impl.h
@@ -47,6 +47,7 @@
                    AppendQuadsData* append_quads_data) override;
   void PushPropertiesTo(LayerImpl* layer) override;
   gfx::Rect GetDamageRect() const override;
+  gfx::Rect GetEnclosingRectInTargetSpace() const override;
 
  protected:
   MirrorLayerImpl(LayerTreeImpl* tree_impl, int id);
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc
index dc0653c..c6426b6 100644
--- a/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -100,7 +100,7 @@
   viz::SharedQuadState* shared_quad_state =
       render_pass->CreateAndAppendSharedQuadState();
   PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_,
-                                internal_contents_scale_, contents_opaque());
+                                contents_opaque());
 
   AppendDebugBorderQuad(render_pass, gfx::Rect(internal_content_bounds_),
                         shared_quad_state, append_quads_data);
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 07afe94..0000c0b 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -205,7 +205,7 @@
     // The downstream CA layers use shared_quad_state to generate resources of
     // the right size even if it is a solid color picture layer.
     PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
-                                  max_contents_scale, contents_opaque());
+                                  contents_opaque());
 
     AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                           append_quads_data);
@@ -230,7 +230,7 @@
   float device_scale_factor = layer_tree_impl()->device_scale_factor();
   float max_contents_scale = MaximumTilingContentsScale();
   PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
-                                max_contents_scale, contents_opaque());
+                                contents_opaque());
   Occlusion scaled_occlusion;
   if (mask_type_ == Layer::LayerMaskType::NOT_MASK) {
     scaled_occlusion =
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 0b242606..21f0fa23 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -722,8 +722,7 @@
       gfx::Rect(layer_bounds);
   viz::SharedQuadState state;
   active_layer()->PopulateScaledSharedQuadState(
-      &state, adjusted_scale, adjusted_scale,
-      active_layer()->contents_opaque());
+      &state, adjusted_scale, active_layer()->contents_opaque());
 }
 
 TEST_F(PictureLayerImplTest, PinchGestureTilings) {
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index 8e5ca03..5eac17c 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -65,7 +65,7 @@
         render_pass->CreateAndAppendSharedQuadState();
     float max_contents_scale = 1.f;
     PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
-                                  max_contents_scale, contents_opaque());
+                                  contents_opaque());
     bool needs_blending = false;
     for (const auto& rect : quad_rects_) {
       auto* quad = render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index 9d4a37a..6ef4249 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -143,7 +143,7 @@
       render_pass->CreateAndAppendSharedQuadState();
 
   PopulateScaledSharedQuadState(shared_quad_state, device_scale_factor,
-                                device_scale_factor, contents_opaque());
+                                contents_opaque());
 
   if (surface_range_.IsValid()) {
     auto* quad = render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 3fb99bd..ff2912a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -3324,9 +3324,17 @@
   // If gpu compositing, then any resources created with the gpu context in the
   // LayerTreeFrameSink were exported to the display compositor may be modified
   // by it, and thus we would be unable to determine what state they are in, in
-  // order to reuse them, so they must be lost. In software compositing, the
-  // resources are not modified by the display compositor (there is no stateful
-  // metadata for shared memory), so we do not need to consider them lost.
+  // order to reuse them, so they must be lost. Note that this includes resources
+  // created using the gpu context associated with |layer_tree_frame_sink_|
+  // internally by the compositor and any resources received from an external
+  // source (for instance, TextureLayers). This is because the API contract
+  // for releasing these external resources requires that the compositor return
+  // them with a valid sync token and no modifications to their GL state. Since
+  // that can not be guaranteed, these must also be marked lost.
+  //
+  // In software compositing, the resources are not modified by the display
+  // compositor (there is no stateful metadata for shared memory), so we do not
+  // need to consider them lost.
   //
   // In both cases, the resources that are exported to the display compositor
   // will have no means of being returned to this client without the
diff --git a/cc/trees/layer_tree_host_pixeltest_mirror.cc b/cc/trees/layer_tree_host_pixeltest_mirror.cc
index ed011f43..cbd67e31 100644
--- a/cc/trees/layer_tree_host_pixeltest_mirror.cc
+++ b/cc/trees/layer_tree_host_pixeltest_mirror.cc
@@ -20,6 +20,12 @@
       public ::testing::WithParamInterface<LayerTreeTest::RendererType> {
  protected:
   RendererType renderer_type() { return GetParam(); }
+
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    // MirrorLayer is only used by UI compositor; so, match its behavior by
+    // setting layer_transforms_should_scale_layer_contents to false.
+    settings->layer_transforms_should_scale_layer_contents = false;
+  }
 };
 
 const LayerTreeTest::RendererType kRendererTypes[] = {
diff --git a/chrome/VERSION b/chrome/VERSION
index 2cc594a5..d49a780 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=77
 MINOR=0
-BUILD=3844
+BUILD=3845
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 0331fdbd..28c9e8e06 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -814,6 +814,7 @@
   "java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java",
   "java/src/org/chromium/chrome/browser/init/ChromeLifetimeController.java",
   "java/src/org/chromium/chrome/browser/init/EmptyBrowserParts.java",
+  "java/src/org/chromium/chrome/browser/init/FirstDrawDetector.java",
   "java/src/org/chromium/chrome/browser/init/InvalidStartupDialog.java",
   "java/src/org/chromium/chrome/browser/init/NativeInitializationController.java",
   "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java",
@@ -1255,9 +1256,10 @@
   "java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java",
   "java/src/org/chromium/chrome/browser/preferences/SearchUtils.java",
   "java/src/org/chromium/chrome/browser/preferences/SeekBarPreference.java",
-  "java/src/org/chromium/chrome/browser/preferences/SignInPreference.java",
   "java/src/org/chromium/chrome/browser/preferences/SpinnerPreference.java",
+  "java/src/org/chromium/chrome/browser/preferences/sync/AccountManagementFragment.java",
   "java/src/org/chromium/chrome/browser/preferences/sync/ManageSyncPreferences.java",
+  "java/src/org/chromium/chrome/browser/preferences/sync/SignInPreference.java",
   "java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java",
   "java/src/org/chromium/chrome/browser/preferences/sync/SyncErrorCardPreference.java",
   "java/src/org/chromium/chrome/browser/preferences/sync/SyncPreference.java",
@@ -1411,7 +1413,6 @@
   "java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java",
   "java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java",
   "java/src/org/chromium/chrome/browser/signin/AccountAdder.java",
-  "java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java",
   "java/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragment.java",
   "java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java",
   "java/src/org/chromium/chrome/browser/signin/AccountSigninChooseView.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 30b0632..5524320 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -196,6 +196,7 @@
   "javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java",
   "javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java",
   "javatests/src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java",
+  "javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java",
   "javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java",
   "javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java",
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java
index 7054f724..b92c130 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java
@@ -252,6 +252,7 @@
     @Test
     @MediumTest
     @Features.EnableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
+    @DisabledTest(message = "crbug.com/981409")
     public void testGridToTabToCurrentLiveWithAnimation() throws InterruptedException {
         prepareTabs(1, mUrl);
         testGridToTab(false, false);
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml
index 3be8d13..a5c50e6 100644
--- a/chrome/android/java/res/xml/main_preferences.xml
+++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -10,7 +10,7 @@
         android:key="account_section"
         android:order="0"
         android:title="@string/prefs_section_account"/>
-    <org.chromium.chrome.browser.preferences.SignInPreference
+    <org.chromium.chrome.browser.preferences.sync.SignInPreference
         android:key="sign_in"
         android:order="1"
         android:title="@string/sign_in_to_chrome"/>
diff --git a/chrome/android/java/res/xml/sync_and_services_preferences.xml b/chrome/android/java/res/xml/sync_and_services_preferences.xml
index fd596892..8dd1fd32 100644
--- a/chrome/android/java/res/xml/sync_and_services_preferences.xml
+++ b/chrome/android/java/res/xml/sync_and_services_preferences.xml
@@ -11,7 +11,7 @@
     <PreferenceCategory
         android:key="user_category"
         android:title="@string/user"/>
-    <org.chromium.chrome.browser.preferences.SignInPreference
+    <org.chromium.chrome.browser.preferences.sync.SignInPreference
         android:key="sign_in"
         android:title="@string/sign_in_to_chrome"/>
 
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 49a032ef..15343d48 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -273,6 +273,10 @@
         String id = shortcutIntent.getStringExtra(ShortcutHelper.EXTRA_ID);
         Context context = ContextUtils.getApplicationContext();
 
+        if (bitmap == null) {
+            Log.e(TAG, "Failed to find an icon for " + title + ", not adding.");
+            return;
+        }
         Icon icon = isMaskableIcon ? Icon.createWithAdaptiveBitmap(bitmap)
                                    : Icon.createWithBitmap(bitmap);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
index ce17caf..1ad903e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ForcedSigninProcessor.java
@@ -10,8 +10,8 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.externalauth.UserRecoverableErrorHandler;
+import org.chromium.chrome.browser.preferences.sync.AccountManagementFragment;
 import org.chromium.chrome.browser.services.AndroidEduAndChildAccountHelper;
-import org.chromium.chrome.browser.signin.AccountManagementFragment;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.util.FeatureUtilities;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
index 5cd4aa1..2949c83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -31,7 +31,6 @@
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LoaderErrors;
 import org.chromium.base.library_loader.ProcessInitException;
-import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeBaseAppCompatActivity;
@@ -42,7 +41,6 @@
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.base.ActivityWindowAndroid;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.WindowAndroid;
@@ -190,21 +188,14 @@
      */
     @CallSuper
     protected void performPostInflationStartup() {
-        final View firstDrawView = getViewToBeDrawnBeforeInitializingNative();
+        View firstDrawView = getViewToBeDrawnBeforeInitializingNative();
         assert firstDrawView != null;
-        ViewTreeObserver.OnPreDrawListener firstDrawListener =
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        firstDrawView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        mFirstDrawComplete = true;
-                        if (!mStartupDelayed) {
-                            onFirstDrawComplete();
-                        }
-                        return true;
-                    }
-                };
-        firstDrawView.getViewTreeObserver().addOnPreDrawListener(firstDrawListener);
+        FirstDrawDetector.waitForFirstDraw(firstDrawView, () -> {
+            mFirstDrawComplete = true;
+            if (!mStartupDelayed) {
+                onFirstDrawComplete();
+            }
+        });
     }
 
     /**
@@ -559,13 +550,8 @@
     private void onFirstDrawComplete() {
         assert mFirstDrawComplete;
         assert !mStartupDelayed;
-
-        PostTask.postTask(UiThreadTaskTraits.BOOTSTRAP, new Runnable() {
-            @Override
-            public void run() {
-                mNativeInitializationController.firstDrawComplete();
-            }
-        });
+        TraceEvent.instant("onFirstDrawComplete");
+        mNativeInitializationController.firstDrawComplete();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/FirstDrawDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/init/FirstDrawDetector.java
new file mode 100644
index 0000000..e79b4d1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/FirstDrawDetector.java
@@ -0,0 +1,77 @@
+// 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.init;
+
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
+import org.chromium.content_public.browser.UiThreadTaskTraits;
+
+/**
+ * A utility for observing when a view gets drawn for the first time.
+ */
+class FirstDrawDetector {
+    View mView;
+    Runnable mCallback;
+
+    private FirstDrawDetector(View view, Runnable callback) {
+        mView = view;
+        mCallback = callback;
+    }
+
+    /**
+     * Waits for a view to be drawn on the screen for the first time.
+     * @param view View whose drawing to observe.
+     * @param callback Callback to trigger on first draw. Will be called on the UI thread.
+     */
+    public static void waitForFirstDraw(View view, Runnable callback) {
+        new FirstDrawDetector(view, callback).startWaiting();
+    }
+
+    private void startWaiting() {
+        // We use a draw listener to detect when a view is first drawn. However, if the view
+        // doesn't get drawn for some reason (e.g. the screen is off), our listener will never
+        // get called. To work around this, we also schedule a callback for the next frame from
+        // a pre-draw listener (which will always get called). Whichever callback runs first
+        // will declare the view to have been drawn.
+        //
+        // Note that we cannot just use a pre-draw listener here, because it does not guarantee
+        // that the view has actually been drawn.
+        ViewTreeObserver.OnPreDrawListener firstPreDrawListener =
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        // The pre-draw listener will run both when the screen is on or off, but the
+                        // view might not have been drawn yet at this point. Trigger the first paint
+                        // at the next frame.
+                        PostTask.postTask(TaskTraits.CHOREOGRAPHER_FRAME, () -> onFirstDraw());
+                        mView.getViewTreeObserver().removeOnPreDrawListener(this);
+                        return true;
+                    }
+                };
+        ViewTreeObserver.OnDrawListener firstDrawListener = new ViewTreeObserver.OnDrawListener() {
+            @Override
+            public void onDraw() {
+                // This callback will be run in the normal case (e.g., screen is on).
+                onFirstDraw();
+                // The draw listener can't be removed from within the callback, so remove it
+                // asynchronously.
+                PostTask.postTask(UiThreadTaskTraits.BEST_EFFORT,
+                        () -> mView.getViewTreeObserver().removeOnDrawListener(this));
+            }
+        };
+        mView.getViewTreeObserver().addOnPreDrawListener(firstPreDrawListener);
+        mView.getViewTreeObserver().addOnDrawListener(firstDrawListener);
+    }
+
+    private void onFirstDraw() {
+        if (mCallback != null) {
+            mCallback.run();
+            mCallback = null;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/NativeInitializationController.java b/chrome/android/java/src/org/chromium/chrome/browser/init/NativeInitializationController.java
index ebbb5c2..be7bbf3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/NativeInitializationController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/NativeInitializationController.java
@@ -9,9 +9,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -106,12 +104,8 @@
             assert !mHasSignaledLibraryLoaded;
             mHasSignaledLibraryLoaded = true;
 
-            // Allow the UI thread to continue its initialization - so that this call back
-            // doesn't block priority work on the UI thread until it's idle.
-            PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
-                if (mActivityDelegate.isActivityFinishingOrDestroyed()) return;
-                mActivityDelegate.onCreateWithNative();
-            });
+            if (mActivityDelegate.isActivityFinishingOrDestroyed()) return;
+            mActivityDelegate.onCreateWithNative();
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
index 2cd130c2..3893986 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.preferences.autofill_assistant.AutofillAssistantPreferences;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferenceFragment;
 import org.chromium.chrome.browser.preferences.developer.DeveloperPreferences;
+import org.chromium.chrome.browser.preferences.sync.SignInPreference;
 import org.chromium.chrome.browser.preferences.sync.SyncPreferenceUtils;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/AccountManagementFragment.java
similarity index 94%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
rename to chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/AccountManagementFragment.java
index 6d88f13..20d1d5ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/AccountManagementFragment.java
@@ -2,7 +2,7 @@
 // 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.signin;
+package org.chromium.chrome.browser.preferences.sync;
 
 import android.accounts.Account;
 import android.annotation.TargetApi;
@@ -37,8 +37,16 @@
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
+import org.chromium.chrome.browser.signin.AccountAdder;
+import org.chromium.chrome.browser.signin.ConfirmManagedSyncDataDialog;
+import org.chromium.chrome.browser.signin.IdentityServicesProvider;
+import org.chromium.chrome.browser.signin.ProfileDataCache;
+import org.chromium.chrome.browser.signin.SignOutDialogFragment;
 import org.chromium.chrome.browser.signin.SignOutDialogFragment.SignOutDialogListener;
+import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
+import org.chromium.chrome.browser.signin.SigninUtils;
+import org.chromium.chrome.browser.signin.SignoutReason;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
@@ -187,8 +195,8 @@
     private boolean canAddAccounts() {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return true;
 
-        UserManager userManager = (UserManager) getActivity()
-                .getSystemService(Context.USER_SERVICE);
+        UserManager userManager =
+                (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
         return !userManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS);
     }
 
@@ -250,11 +258,11 @@
             String parentText;
 
             if (!secondParent.isEmpty()) {
-                parentText = res.getString(R.string.account_management_two_parent_names,
-                        firstParent, secondParent);
+                parentText = res.getString(
+                        R.string.account_management_two_parent_names, firstParent, secondParent);
             } else if (!firstParent.isEmpty()) {
-                parentText = res.getString(R.string.account_management_one_parent_name,
-                        firstParent);
+                parentText =
+                        res.getString(R.string.account_management_one_parent_name, firstParent);
             } else {
                 parentText = res.getString(R.string.account_management_no_parental_data);
             }
@@ -439,8 +447,7 @@
      * @return Whether the sign out is not disabled due to a child/EDU account.
      */
     private static boolean getSignOutAllowedPreferenceValue() {
-        return ContextUtils.getAppSharedPreferences()
-                .getBoolean(SIGN_OUT_ALLOWED, true);
+        return ContextUtils.getAppSharedPreferences().getBoolean(SIGN_OUT_ALLOWED, true);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SignInPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SignInPreference.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/preferences/SignInPreference.java
rename to chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SignInPreference.java
index efc0bcd4..af06866 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SignInPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SignInPreference.java
@@ -2,7 +2,7 @@
 // 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.preferences;
+package org.chromium.chrome.browser.preferences.sync;
 
 import android.content.Context;
 import android.preference.Preference;
@@ -16,7 +16,8 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
-import org.chromium.chrome.browser.signin.AccountManagementFragment;
+import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
 import org.chromium.chrome.browser.signin.AccountSigninActivity;
 import org.chromium.chrome.browser.signin.DisplayableProfileData;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
@@ -119,7 +120,7 @@
      * Should be called when the {@link PreferenceFragment} which used {@link SignInPreference} gets
      * destroyed. Used to record "ImpressionsTilDismiss" histogram.
      */
-    void onPreferenceFragmentDestroyed() {
+    public void onPreferenceFragmentDestroyed() {
         if (mSigninPromoController != null) {
             mSigninPromoController.onPromoDestroyed();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
index 1f4de889..8363c9e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
@@ -46,7 +46,6 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.preferences.SignInPreference;
 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
index abf5df2..5a1f30e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountSigninActivity.java
@@ -17,6 +17,7 @@
 import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
+import org.chromium.chrome.browser.preferences.sync.AccountManagementFragment;
 import org.chromium.chrome.browser.signin.SigninManager.SignInCallback;
 import org.chromium.components.signin.ChildAccountStatus;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
index 3e5a5ceb..0c595480 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
@@ -15,6 +15,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.preferences.sync.AccountManagementFragment;
 import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.components.signin.AccountManagerFacade;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java
new file mode 100644
index 0000000..3b3139cd
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java
@@ -0,0 +1,42 @@
+// 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.init;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ui.DummyUiActivity;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import java.util.concurrent.CountDownLatch;
+
+/** Tests for {@link FirstDrawDetector}. */
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class FirstDrawDetectorTest {
+    @Rule
+    public ActivityTestRule<DummyUiActivity> mActivityTestRule =
+            new ActivityTestRule<>(DummyUiActivity.class);
+
+    @Test
+    @SmallTest
+    public void testFirstDraw() throws Exception {
+        final CountDownLatch firstDrawEvent = new CountDownLatch(1);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            DummyUiActivity activity = mActivityTestRule.getActivity();
+            View view = new FrameLayout(activity);
+            activity.setContentView(view);
+
+            FirstDrawDetector.waitForFirstDraw(view, () -> firstDrawEvent.countDown());
+        });
+        firstDrawEvent.await();
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
index b94f079d..00e7e70 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
@@ -32,7 +32,8 @@
 import org.chromium.chrome.browser.preferences.MainPreferences;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.preferences.SignInPreference;
+import org.chromium.chrome.browser.preferences.sync.AccountManagementFragment;
+import org.chromium.chrome.browser.preferences.sync.SignInPreference;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
index 1938d35..2b5383c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
@@ -31,7 +31,7 @@
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
 import org.chromium.chrome.browser.preferences.Preferences;
-import org.chromium.chrome.browser.signin.AccountManagementFragment;
+import org.chromium.chrome.browser.preferences.sync.AccountManagementFragment;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ActivityUtils;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
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
index 9d5d9f5..e2f0df1f1 100644
--- 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
@@ -4,8 +4,9 @@
 
 package org.chromium.chrome.browser.touchless;
 
-import android.app.Fragment;
 import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.RecyclerView;
 import android.view.Menu;
 import android.widget.ListView;
 
@@ -34,17 +35,46 @@
         }
     }
 
+    /**
+     * Adds paddings for the main list in the current android.app.Fragment.
+     * Support library fragments are handled in {@link #onAttachedToWindowCompat()}.
+     * TODO(crbug.com/967022): Once all fragments are migrated to the support library, this should
+     * be deleted.
+     */
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
+        android.app.Fragment fragment = getMainFragment();
+        if (fragment == null || fragment.getView() == null
+                || fragment.getView().findViewById(android.R.id.list) == null) {
+            return;
+        }
+
         int padding = getResources().getDimensionPixelSize(
                 org.chromium.chrome.touchless.R.dimen.touchless_preferences_highlight_padding);
-        Fragment fragment = getFragmentManager().findFragmentById(android.R.id.content);
         ListView listView = fragment.getView().findViewById(android.R.id.list);
         listView.setPadding(padding, 0, padding, 0);
         listView.setDividerHeight(padding);
     }
 
+    /**
+     * Adds paddings for the main list in the current support library Fragment.
+     */
+    @Override
+    public void onAttachedToWindowCompat() {
+        super.onAttachedToWindowCompat();
+        Fragment fragment = getMainFragmentCompat();
+        if (fragment == null || fragment.getView() == null
+                || fragment.getView().findViewById(R.id.list) == null) {
+            return;
+        }
+
+        int padding = getResources().getDimensionPixelSize(
+                org.chromium.chrome.touchless.R.dimen.touchless_preferences_highlight_padding);
+        RecyclerView recyclerView = fragment.getView().findViewById(R.id.list);
+        recyclerView.setPadding(padding, 0, padding, 0);
+    }
+
     @Override
     protected void onResume() {
         super.onResume();
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6b5b12c..3cc43fc4 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4965,7 +4965,7 @@
       allow_circular_includes_from += [ "android/vr:vr_android" ]
     }
 
-    if (!is_android) {
+    if (is_win) {
       sources += [
         "vr/service/xr_session_request_consent_manager_impl.cc",
         "vr/service/xr_session_request_consent_manager_impl.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 688591c..d59ef407f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1034,18 +1034,6 @@
 };
 #endif  // OS_ANDROID
 
-const FeatureEntry::FeatureParam kVizHitTestDrawQuadEnabled[] = {
-    {"provider", "draw_quad"}};
-
-const FeatureEntry::FeatureParam kVizHitTestSurfaceLayerEnabled[] = {
-    {"provider", "surface_layer"}};
-
-const FeatureEntry::FeatureVariation kVizHitTestVariations[] = {
-    {"DrawQuad", kVizHitTestDrawQuadEnabled,
-     base::size(kVizHitTestDrawQuadEnabled), nullptr},
-    {"SurfaceLayer", kVizHitTestSurfaceLayerEnabled,
-     base::size(kVizHitTestSurfaceLayerEnabled), nullptr}};
-
 #if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam
     kAutofillUseMobileLabelDisambiguationShowAll[] = {
@@ -2961,11 +2949,9 @@
      flag_descriptions::kQueryInOmniboxDescription, kOsAll,
      FEATURE_VALUE_TYPE(omnibox::kQueryInOmnibox)},
 
-    {"enable-viz-hit-test", flag_descriptions::kVizHitTestName,
+    {"enable-viz-hit-test-surface-layer", flag_descriptions::kVizHitTestName,
      flag_descriptions::kVizHitTestDescription, kOsAll,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kEnableVizHitTest,
-                                    kVizHitTestVariations,
-                                    "VizHitTestDataSource")},
+     FEATURE_VALUE_TYPE(features::kEnableVizHitTestSurfaceLayer)},
 
 #if BUILDFLAG(ENABLE_PDF)
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/android/vr/gvr_consent_helper_impl.cc b/chrome/browser/android/vr/gvr_consent_helper_impl.cc
index e0b99d7..16855b0 100644
--- a/chrome/browser/android/vr/gvr_consent_helper_impl.cc
+++ b/chrome/browser/android/vr/gvr_consent_helper_impl.cc
@@ -44,7 +44,7 @@
 
 }  // namespace
 
-GvrConsentHelperImpl::GvrConsentHelperImpl() = default;
+GvrConsentHelperImpl::GvrConsentHelperImpl() : weak_ptr_(this) {}
 
 GvrConsentHelperImpl::~GvrConsentHelperImpl() = default;
 
@@ -54,11 +54,13 @@
     OnUserConsentCallback on_user_consent_callback) {
   DCHECK(!on_user_consent_callback_);
   on_user_consent_callback_ = std::move(on_user_consent_callback);
+  render_process_id_ = render_process_id;
+  render_frame_id_ = render_frame_id;
 
   JNIEnv* env = AttachCurrentThread();
   jdelegate_ = Java_VrConsentDialog_promptForUserConsent(
       env, reinterpret_cast<jlong>(this),
-      GetTabFromRenderer(render_process_id, render_frame_id));
+      GetTabFromRenderer(render_process_id_, render_frame_id_));
   if (jdelegate_.is_null()) {
     std::move(on_user_consent_callback_).Run(false);
     return;
@@ -69,9 +71,45 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& j_caller,
     jboolean is_granted) {
-  if (on_user_consent_callback_)
-    std::move(on_user_consent_callback_).Run(!!is_granted);
   jdelegate_.Reset();
+  if (!on_user_consent_callback_)
+    return;
+
+  if (!is_granted) {
+    std::move(on_user_consent_callback_).Run(false);
+    return;
+  }
+
+  InitModule();
+}
+
+void GvrConsentHelperImpl::InitModule() {
+  if (!module_delegate_) {
+    module_delegate_ = VrModuleProviderFactory::CreateModuleProvider(
+        render_process_id_, render_frame_id_);
+  }
+
+  if (!module_delegate_) {
+    std::move(on_user_consent_callback_).Run(false);
+    return;
+  }
+
+  if (!module_delegate_->ModuleInstalled()) {
+    module_delegate_->InstallModule(base::BindOnce(
+        &GvrConsentHelperImpl::OnModuleInstalled, weak_ptr_.GetWeakPtr()));
+    return;
+  }
+
+  std::move(on_user_consent_callback_).Run(true);
+}
+
+void GvrConsentHelperImpl::OnModuleInstalled(bool success) {
+  if (!success) {
+    std::move(on_user_consent_callback_).Run(false);
+    return;
+  }
+
+  std::move(on_user_consent_callback_).Run(true);
 }
 
 }  // namespace vr
diff --git a/chrome/browser/android/vr/gvr_consent_helper_impl.h b/chrome/browser/android/vr/gvr_consent_helper_impl.h
index 2fb028d..508073f0 100644
--- a/chrome/browser/android/vr/gvr_consent_helper_impl.h
+++ b/chrome/browser/android/vr/gvr_consent_helper_impl.h
@@ -6,9 +6,12 @@
 #define CHROME_BROWSER_ANDROID_VR_GVR_CONSENT_HELPER_IMPL_H_
 
 #include <jni.h>
+#include <memory>
 
 #include "base/android/jni_android.h"
 #include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/android/vr/vr_module_provider.h"
 #include "chrome/browser/vr/service/gvr_consent_helper.h"
 
 namespace vr {
@@ -28,9 +31,18 @@
                            jboolean is_granted);
 
  private:
+  void InitModule();
+  void OnModuleInstalled(bool success);
+
+  std::unique_ptr<VrModuleProvider> module_delegate_;
+  int render_process_id_;
+  int render_frame_id_;
+
   OnUserConsentCallback on_user_consent_callback_;
   base::android::ScopedJavaGlobalRef<jobject> jdelegate_;
 
+  base::WeakPtrFactory<GvrConsentHelperImpl> weak_ptr_;
+
   DISALLOW_COPY_AND_ASSIGN(GvrConsentHelperImpl);
 };
 }  // namespace vr
diff --git a/chrome/browser/android/vr/vr_module_provider.cc b/chrome/browser/android/vr/vr_module_provider.cc
index 0eda650b..1004ae4 100644
--- a/chrome/browser/android/vr/vr_module_provider.cc
+++ b/chrome/browser/android/vr/vr_module_provider.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/android/vr/register_jni.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
 #include "device/vr/buildflags/buildflags.h"
 
 #if BUILDFLAG(ENABLE_ARCORE)
@@ -68,9 +67,10 @@
   }
 }
 
-std::unique_ptr<device::VrModuleDelegate>
-VrModuleProviderFactory::CreateDelegate(int render_process_id,
-                                        int render_frame_id) {
+// static
+std::unique_ptr<VrModuleProvider> VrModuleProviderFactory::CreateModuleProvider(
+    int render_process_id,
+    int render_frame_id) {
   content::RenderFrameHost* render_frame_host =
       content::RenderFrameHost::FromID(render_process_id, render_frame_id);
   DCHECK(render_frame_host);
@@ -86,8 +86,6 @@
 }
 
 static void JNI_VrModuleProvider_Init(JNIEnv* env) {
-  device::VrModuleDelegateFactory::Set(
-      std::make_unique<VrModuleProviderFactory>());
   GvrConsentHelper::SetInstance(std::make_unique<vr::GvrConsentHelperImpl>());
 #if BUILDFLAG(ENABLE_ARCORE)
   ArcoreConsentPromptInterface::SetInstance(new ArcoreConsentPrompt());
diff --git a/chrome/browser/android/vr/vr_module_provider.h b/chrome/browser/android/vr/vr_module_provider.h
index a43787e..232e5fe 100644
--- a/chrome/browser/android/vr/vr_module_provider.h
+++ b/chrome/browser/android/vr/vr_module_provider.h
@@ -6,21 +6,22 @@
 #define CHROME_BROWSER_ANDROID_VR_VR_MODULE_PROVIDER_H_
 
 #include <jni.h>
+#include <memory>
 #include <queue>
 
 #include "base/android/jni_android.h"
 #include "chrome/browser/android/tab_android.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
 
 namespace vr {
 
 // Installs the VR module.
-class VrModuleProvider : public device::VrModuleDelegate {
+class VrModuleProvider {
  public:
   explicit VrModuleProvider(TabAndroid* tab);
-  ~VrModuleProvider() override;
-  bool ModuleInstalled() override;
-  void InstallModule(base::OnceCallback<void(bool)> on_finished) override;
+  ~VrModuleProvider();
+
+  bool ModuleInstalled();
+  void InstallModule(base::OnceCallback<void(bool)> on_finished);
 
   // Called by Java.
   void OnInstalledModule(JNIEnv* env,
@@ -35,11 +36,11 @@
 };
 
 // Creates a VR module provider.
-class VrModuleProviderFactory : public device::VrModuleDelegateFactory {
+class VrModuleProviderFactory {
  public:
-  std::unique_ptr<device::VrModuleDelegate> CreateDelegate(
+  static std::unique_ptr<VrModuleProvider> CreateModuleProvider(
       int render_process_id,
-      int render_frame_id) override;
+      int render_frame_id);
 };
 
 }  // namespace vr
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index 12ce010..a5584ec 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/extensions/api/file_manager_private_internal.h"
+#include "chromeos/components/drivefs/drivefs_util.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/network/network_handler.h"
 #include "chromeos/network/network_state_handler.h"
@@ -659,8 +660,8 @@
     properties_->size = std::make_unique<double>(metadata->size);
     properties_->present = std::make_unique<bool>(metadata->available_offline);
     properties_->dirty = std::make_unique<bool>(metadata->dirty);
-    properties_->hosted = std::make_unique<bool>(
-        metadata->type == drivefs::mojom::FileMetadata::Type::kHosted);
+    properties_->hosted =
+        std::make_unique<bool>(drivefs::IsHosted(metadata->type));
     properties_->available_offline = std::make_unique<bool>(
         metadata->available_offline || *properties_->hosted);
     properties_->available_when_metered = std::make_unique<bool>(
@@ -720,7 +721,7 @@
     properties_->can_share =
         std::make_unique<bool>(metadata->capabilities->can_share);
 
-    if (metadata->type != drivefs::mojom::FileMetadata::Type::kDirectory) {
+    if (drivefs::IsAFile(metadata->type)) {
       properties_->thumbnail_url = std::make_unique<std::string>(
           base::StrCat({"drivefs:", file_system_url_.ToGURL().spec()}));
       properties_->cropped_thumbnail_url =
@@ -897,8 +898,7 @@
     entry.SetKey("fileSystemName", base::Value(fs_name));
     entry.SetKey("fileSystemRoot", base::Value(fs_root));
     entry.SetKey("fileFullPath", base::Value(item->path.AsUTF8Unsafe()));
-    bool is_dir =
-        item->metadata->type == drivefs::mojom::FileMetadata::Type::kDirectory;
+    bool is_dir = drivefs::IsADirectory(item->metadata->type);
     entry.SetKey("fileIsDirectory", base::Value(is_dir));
     entry.SetKey(kAvailableOfflinePropertyName,
                  base::Value(item->metadata->available_offline));
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
index a614e6bc..c71ffdb 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/file_manager_private.h"
+#include "chromeos/components/drivefs/drivefs_util.h"
 #include "components/drive/chromeos/file_system_interface.h"
 #include "components/drive/drive.pb.h"
 #include "components/drive/drive_api_util.h"
@@ -212,8 +213,7 @@
   const int index = params->selected_files.size();
   const auto& path = params->file_paths[index];
   params->selected_files.emplace_back(path, path);
-  if (metadata &&
-      metadata->type == drivefs::mojom::FileMetadata::Type::kHosted &&
+  if (metadata && drivefs::IsHosted(metadata->type) &&
       !metadata->alternate_url.empty()) {
     params->selected_files.back().url.emplace(
         std::move(metadata->alternate_url));
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_screen_apitest_base.h b/chrome/browser/chromeos/extensions/login_screen/login_screen_apitest_base.h
index 757d564..985794c1 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login_screen_apitest_base.h
+++ b/chrome/browser/chromeos/extensions/login_screen/login_screen_apitest_base.h
@@ -16,6 +16,7 @@
 // login screen. The extension is whitelisted to run as a force-installed "login
 // screen extension" and is also whitelisted for the following APIs:
 // * loginScreenUi
+// * storage
 // The extension's code can be found in
 // chrome/test/data/extensions/api_test/login_screen_apis/
 class LoginScreenApitestBase
diff --git a/chrome/browser/chromeos/extensions/login_screen/storage_apitest.cc b/chrome/browser/chromeos/extensions/login_screen/storage_apitest.cc
new file mode 100644
index 0000000..4239ff2
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/login_screen/storage_apitest.cc
@@ -0,0 +1,42 @@
+// 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 <memory>
+#include <string>
+
+#include "chrome/browser/chromeos/extensions/login_screen/login_screen_apitest_base.h"
+#include "components/version_info/version_info.h"
+
+namespace {
+
+const char kCannotAccessLocalStorage[] = "StorageCannotAccessLocalStorage";
+const char kCannotAccessSyncStorage[] = "StorageCannotAccessSyncStorage";
+const char kCanAccessManagedStorage[] = "StorageCanAccessManagedStorage";
+
+}  // namespace
+
+namespace chromeos {
+
+class StorageApitest : public LoginScreenApitestBase {
+ public:
+  StorageApitest() : LoginScreenApitestBase(version_info::Channel::DEV) {}
+  ~StorageApitest() override = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StorageApitest);
+};
+
+IN_PROC_BROWSER_TEST_F(StorageApitest, CannotAccessLocalStorage) {
+  SetUpExtensionAndRunTest(kCannotAccessLocalStorage);
+}
+
+IN_PROC_BROWSER_TEST_F(StorageApitest, CannotAccessSyncStorage) {
+  SetUpExtensionAndRunTest(kCannotAccessSyncStorage);
+}
+
+IN_PROC_BROWSER_TEST_F(StorageApitest, CanAccessManagedStorage) {
+  SetUpExtensionAndRunTest(kCanAccessManagedStorage);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_manager/open_with_browser.cc b/chrome/browser/chromeos/file_manager/open_with_browser.cc
index 37deb3f..0e1d3bb 100644
--- a/chrome/browser/chromeos/file_manager/open_with_browser.cc
+++ b/chrome/browser/chromeos/file_manager/open_with_browser.cc
@@ -27,6 +27,7 @@
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chromeos/components/drivefs/drivefs_util.h"
 #include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
 #include "components/drive/drive_api_util.h"
 #include "components/drive/file_system_core_util.h"
@@ -144,7 +145,7 @@
                            drivefs::mojom::FileMetadataPtr metadata) {
   if (error != drive::FILE_ERROR_OK)
     return;
-  if (metadata->type != drivefs::mojom::FileMetadata::Type::kHosted) {
+  if (drivefs::IsLocal(metadata->type)) {
     OpenGDocUrlFromFile(file_path, profile);
     return;
   }
diff --git a/chrome/browser/chromeos/fileapi/recent_drive_source.cc b/chrome/browser/chromeos/fileapi/recent_drive_source.cc
index 68843372..74f4441 100644
--- a/chrome/browser/chromeos/fileapi/recent_drive_source.cc
+++ b/chrome/browser/chromeos/fileapi/recent_drive_source.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/fileapi/recent_file.h"
+#include "chromeos/components/drivefs/drivefs_util.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "storage/browser/fileapi/file_system_operation.h"
@@ -198,8 +199,7 @@
 
   files_.reserve(results->size());
   for (auto& result : *results) {
-    if (result->metadata->type ==
-        drivefs::mojom::FileMetadata::Type::kDirectory) {
+    if (!drivefs::IsAFile(result->metadata->type)) {
       continue;
     }
     base::FilePath path = integration_service->GetMountPointPath().BaseName();
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index 15ef7e3..a3a8b1f6 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -49,6 +49,7 @@
 #include "ui/base/ime/ime_bridge.h"
 #include "ui/chromeos/ime/input_method_menu_item.h"
 #include "ui/chromeos/ime/input_method_menu_manager.h"
+#include "ui/ozone/public/ozone_platform.h"
 
 namespace chromeos {
 namespace input_method {
@@ -920,10 +921,12 @@
       component_extension_ime_manager_(new ComponentExtensionIMEManager()),
       enable_extension_loading_(enable_extension_loading),
       features_enabled_state_(InputMethodManager::FEATURE_ALL) {
-  if (IsRunningAsSystemCompositor())
-    keyboard_ = std::make_unique<ImeKeyboardImpl>();
-  else
+  if (IsRunningAsSystemCompositor()) {
+    keyboard_ = std::make_unique<ImeKeyboardImpl>(
+        ui::OzonePlatform::GetInstance()->GetInputController());
+  } else {
     keyboard_ = std::make_unique<FakeImeKeyboard>();
+  }
   // Initializes the system IME list.
   std::unique_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate(
       new ComponentExtensionIMEManagerImpl());
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index 2ffa891..1c321a1 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -102,7 +102,7 @@
     on_refresh_token_revoked_callback_.Run(account_id);
 }
 
-void DeviceOAuth2TokenService::FetchOAuth2Token(
+bool DeviceOAuth2TokenService::HandleAccessTokenFetch(
     OAuth2AccessTokenManager::RequestImpl* request,
     const CoreAccountId& account_id,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
@@ -120,22 +120,20 @@
       pending_requests_.push_back(new PendingRequest(
           request->AsWeakPtr(), client_id, client_secret, scopes));
       GetDeviceDelegate()->RequestValidation();
-      return;
+      return true;
     case DeviceOAuth2TokenServiceDelegate::STATE_NO_TOKEN:
       FailRequest(request, GoogleServiceAuthError::USER_NOT_SIGNED_UP);
-      return;
+      return true;
     case DeviceOAuth2TokenServiceDelegate::STATE_TOKEN_INVALID:
       FailRequest(request, GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-      return;
+      return true;
     case DeviceOAuth2TokenServiceDelegate::STATE_TOKEN_VALID:
-      // Pass through to OAuth2TokenService to satisfy the request.
-      OAuth2TokenService::FetchOAuth2Token(request, account_id,
-                                           url_loader_factory, client_id,
-                                           client_secret, scopes);
-      return;
+      // Let OAuth2AccessTokenManager handle the request.
+      return false;
   }
 
   NOTREACHED() << "Unexpected state " << GetDeviceDelegate()->state_;
+  return false;
 }
 
 void DeviceOAuth2TokenService::FlushPendingRequests(
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.h b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
index 2dc57f21..f0ac3dd 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
@@ -69,8 +69,8 @@
   void OnRefreshTokenRevoked(const CoreAccountId& account_id) override;
 
  protected:
-  // Implementation of OAuth2TokenService.
-  void FetchOAuth2Token(
+  // Implementation of OAuth2AccessTokenManager::Delegate
+  bool HandleAccessTokenFetch(
       OAuth2AccessTokenManager::RequestImpl* request,
       const CoreAccountId& account_id,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc b/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc
index c80afec..48ab25ef 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_launch_from_native_unittest.cc
@@ -11,12 +11,14 @@
 #include "base/test/values_test_util.h"
 #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/version_info/version_info.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/event_router_factory.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension_paths.h"
+#include "extensions/common/features/feature_channel.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/value_builder.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -52,6 +54,9 @@
 
 class ExtensionSupportsConnectionFromNativeAppTest : public ::testing::Test {
  public:
+  ExtensionSupportsConnectionFromNativeAppTest()
+      : channel_(version_info::Channel::DEV) {}
+
   void SetUp() override {
     EventRouterFactory::GetInstance()->SetTestingFactory(
         &profile_,
@@ -109,6 +114,7 @@
     extension_id_ = extension->id();
   }
 
+  ScopedCurrentChannel channel_;
   content::TestBrowserThreadBundle thread_bundle_;
   bool has_listener_result_ = true;
   TestingProfile profile_;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 80a2ac8..e8aedf9 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1776,9 +1776,9 @@
     "expiry_milestone": 76
   },
   {
-    "name": "enable-viz-hit-test",
-    "owners": [ "riajiang", "sunxd", "rjkroege" ],
-    "expiry_milestone": 76
+    "name": "enable-viz-hit-test-surface-layer",
+    "owners": [ "yigu", "rjkroege", "kylechar" ],
+    "expiry_milestone": 78
   },
   {
     "name": "enable-web-authentication-ble-support",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8173a1a..3cad9f99 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -777,10 +777,10 @@
     "If enabled, the display compositor runs as part of the viz service in the"
     "GPU process.";
 
-const char kVizHitTestName[] = "Viz Hit-test";
+const char kVizHitTestName[] = "Viz Hit-test SurfaceLayer";
 const char kVizHitTestDescription[] =
-    "If enabled, event targeting uses the new viz-assisted hit-testing logic, "
-    "with hit-test data computed from the CompositorFrame or the SurfaceLayer.";
+    "If enabled, event targeting uses hit-test data computed from the "
+    "SurfaceLayer.";
 
 const char kCompositorThreadedScrollbarScrollingName[] =
     "Compositor threaded scrollbar scrolling";
diff --git a/chrome/browser/performance_manager/graph/graph_impl.cc b/chrome/browser/performance_manager/graph/graph_impl.cc
index 20aa307..69ed4d0 100644
--- a/chrome/browser/performance_manager/graph/graph_impl.cc
+++ b/chrome/browser/performance_manager/graph/graph_impl.cc
@@ -146,6 +146,7 @@
 }
 
 void GraphImpl::PassToGraph(std::unique_ptr<GraphOwned> graph_owned) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto* raw = graph_owned.get();
   DCHECK(!base::Contains(graph_owned_, raw));
   graph_owned_.insert(std::make_pair(raw, std::move(graph_owned)));
@@ -153,6 +154,7 @@
 }
 
 std::unique_ptr<GraphOwned> GraphImpl::TakeFromGraph(GraphOwned* graph_owned) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::unique_ptr<GraphOwned> object;
   auto it = graph_owned_.find(graph_owned);
   if (it != graph_owned_.end()) {
@@ -166,18 +168,22 @@
 }
 
 const SystemNode* GraphImpl::FindOrCreateSystemNode() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return FindOrCreateSystemNodeImpl();
 }
 
 std::vector<const ProcessNode*> GraphImpl::GetAllProcessNodes() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return GetAllNodesOfType<ProcessNodeImpl, const ProcessNode*>();
 }
 
 std::vector<const FrameNode*> GraphImpl::GetAllFrameNodes() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return GetAllNodesOfType<FrameNodeImpl, const FrameNode*>();
 }
 
 std::vector<const PageNode*> GraphImpl::GetAllPageNodes() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return GetAllNodesOfType<PageNodeImpl, const PageNode*>();
 }
 
@@ -195,6 +201,11 @@
   observer->SetGraph(nullptr);
 }
 
+ukm::UkmRecorder* GraphImpl::GetUkmRecorder() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return ukm_recorder();
+}
+
 uintptr_t GraphImpl::GetImplType() const {
   return kGraphImplType;
 }
diff --git a/chrome/browser/performance_manager/graph/graph_impl.h b/chrome/browser/performance_manager/graph/graph_impl.h
index b62d704..393fe3f 100644
--- a/chrome/browser/performance_manager/graph/graph_impl.h
+++ b/chrome/browser/performance_manager/graph/graph_impl.h
@@ -64,6 +64,7 @@
   std::vector<const FrameNode*> GetAllFrameNodes() const override;
   std::vector<const PageNode*> GetAllPageNodes() const override;
   std::vector<const ProcessNode*> GetAllProcessNodes() const override;
+  ukm::UkmRecorder* GetUkmRecorder() const override;
   uintptr_t GetImplType() const override;
   const void* GetImpl() const override;
 
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.cc b/chrome/browser/performance_manager/graph/page_node_impl.cc
index 25cadb3..2cad178 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/page_node_impl.cc
@@ -332,6 +332,11 @@
   return is_visible();
 }
 
+base::TimeDelta PageNodeImpl::GetTimeSinceLastVisibilityChange() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return TimeSinceLastVisibilityChange();
+}
+
 bool PageNodeImpl::IsAudible() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return is_audible();
@@ -357,6 +362,11 @@
   return navigation_id();
 }
 
+base::TimeDelta PageNodeImpl::GetTimeSinceLastNavigation() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return TimeSinceLastNavigation();
+}
+
 const FrameNode* PageNodeImpl::GetMainFrameNode() const {
   return GetMainFrameNodeImpl();
 }
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.h b/chrome/browser/performance_manager/graph/page_node_impl.h
index 90bd490..417c9caf3 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl.h
+++ b/chrome/browser/performance_manager/graph/page_node_impl.h
@@ -137,11 +137,13 @@
   // PageNode implementation:
   bool IsPageAlmostIdle() const override;
   bool IsVisible() const override;
+  base::TimeDelta GetTimeSinceLastVisibilityChange() const override;
   bool IsAudible() const override;
   bool IsLoading() const override;
   ukm::SourceId GetUkmSourceID() const override;
   LifecycleState GetLifecycleState() const override;
   int64_t GetNavigationID() const override;
+  base::TimeDelta GetTimeSinceLastNavigation() const override;
   const FrameNode* GetMainFrameNode() const override;
   const GURL& GetMainFrameUrl() const override;
 
diff --git a/chrome/browser/performance_manager/observers/isolation_context_metrics.h b/chrome/browser/performance_manager/observers/isolation_context_metrics.h
index 930f0ec8..0b1d80b 100644
--- a/chrome/browser/performance_manager/observers/isolation_context_metrics.h
+++ b/chrome/browser/performance_manager/observers/isolation_context_metrics.h
@@ -157,7 +157,7 @@
   void OnBeforeProcessNodeRemoved(const ProcessNode* process_node) override;
 
   // (Un)registers the various node observer flavors of this object with the
-  // graph. These are invoked by OnPassedIntoGraph and OnTakenFromGraph, but
+  // graph. These are invoked by OnPassedToGraph and OnTakenFromGraph, but
   // hoisted to their own functions for testing.
   void RegisterObservers(Graph* graph);
   void UnregisterObservers(Graph* graph);
diff --git a/chrome/browser/performance_manager/observers/metrics_collector.cc b/chrome/browser/performance_manager/observers/metrics_collector.cc
index 4f40cee..3204c70 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector.cc
+++ b/chrome/browser/performance_manager/observers/metrics_collector.cc
@@ -8,18 +8,30 @@
 
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
-#include "chrome/browser/performance_manager/graph/frame_node_impl.h"
-#include "chrome/browser/performance_manager/graph/graph_impl.h"
-#include "chrome/browser/performance_manager/graph/graph_impl_operations.h"
-#include "chrome/browser/performance_manager/graph/page_node_impl.h"
-#include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager_clock.h"
+#include "chrome/browser/performance_manager/public/graph/graph_operations.h"
+#include "chrome/browser/performance_manager/public/graph/node_attached_data.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 
 namespace performance_manager {
 
-// Delay the metrics report from GRC to UMA/UKM for 5 minutes from when the main
-// frame navigation is committed.
+class MetricsReportRecordHolder
+    : public ExternalNodeAttachedDataImpl<MetricsReportRecordHolder> {
+ public:
+  explicit MetricsReportRecordHolder(const PageNode* unused_page_node) {}
+  ~MetricsReportRecordHolder() override = default;
+  MetricsCollector::MetricsReportRecord metrics_report_record;
+};
+
+class UkmCollectionStateHolder
+    : public ExternalNodeAttachedDataImpl<UkmCollectionStateHolder> {
+ public:
+  explicit UkmCollectionStateHolder(const PageNode* unused_page_node) {}
+  ~UkmCollectionStateHolder() override = default;
+  MetricsCollector::UkmCollectionState ukm_collection_state;
+};
+
+// Delay the metrics report from for 5 minutes from when the main frame
+// navigation is committed.
 const base::TimeDelta kMetricsReportDelayTimeout =
     base::TimeDelta::FromMinutes(5);
 
@@ -33,144 +45,139 @@
 
 const int kDefaultFrequencyUkmEQTReported = 5u;
 
-// Gets the number of tabs that are co-resident in all of the render processes
-// associated with a PageNode.
-size_t GetNumCoresidentTabs(const PageNodeImpl* page_node) {
-  std::set<NodeBase*> coresident_tabs;
-  auto process_nodes =
-      GraphImplOperations::GetAssociatedProcessNodes(page_node);
-  for (auto* process_node : process_nodes) {
-    auto page_nodes = GraphImplOperations::GetAssociatedPageNodes(process_node);
-    for (auto* associated_page_node : page_nodes) {
-      coresident_tabs.insert(associated_page_node);
-    }
-  }
-  // A tab cannot be co-resident with itself.
-  return coresident_tabs.size() - 1;
-}
-
 MetricsCollector::MetricsCollector() {
   UpdateWithFieldTrialParams();
 }
 
 MetricsCollector::~MetricsCollector() = default;
 
-bool MetricsCollector::ShouldObserve(const NodeBase* node) {
-  return node->type() == FrameNodeImpl::Type() ||
-         node->type() == PageNodeImpl::Type() ||
-         node->type() == ProcessNodeImpl::Type();
-}
-
-void MetricsCollector::OnNodeAdded(NodeBase* node) {
-  if (node->type() == PageNodeImpl::Type()) {
-    PageNodeImpl* page_node = PageNodeImpl::FromNodeBase(node);
-    metrics_report_record_map_.emplace(page_node, MetricsReportRecord());
-  }
-}
-
-void MetricsCollector::OnBeforeNodeRemoved(NodeBase* node) {
-  if (node->type() == PageNodeImpl::Type()) {
-    PageNodeImpl* page_node = PageNodeImpl::FromNodeBase(node);
-    metrics_report_record_map_.erase(page_node);
-    ukm_collection_state_map_.erase(page_node);
-  }
-}
-
 void MetricsCollector::OnNonPersistentNotificationCreated(
-    FrameNodeImpl* frame_node) {
+    const FrameNode* frame_node) {
   // Only record metrics while a page is backgrounded.
-  auto* page_node = frame_node->page_node();
-  if (page_node->is_visible() || !ShouldReportMetrics(page_node))
+  auto* page_node = frame_node->GetPageNode();
+  if (page_node->IsVisible() || !ShouldReportMetrics(page_node))
     return;
 
-  MetricsReportRecord& record =
-      metrics_report_record_map_.find(page_node)->second;
-  record.first_non_persistent_notification_created.OnSignalReceived(
-      frame_node->IsMainFrame(), page_node->TimeSinceLastVisibilityChange(),
-      graph()->ukm_recorder());
+  auto* record = GetMetricsReportRecord(page_node);
+  record->first_non_persistent_notification_created.OnSignalReceived(
+      frame_node->IsMainFrame(), page_node->GetTimeSinceLastVisibilityChange(),
+      graph_->GetUkmRecorder());
 }
 
-void MetricsCollector::OnIsVisibleChanged(PageNodeImpl* page_node) {
+void MetricsCollector::OnPassedToGraph(Graph* graph) {
+  graph_ = graph;
+  RegisterObservers(graph);
+}
+
+void MetricsCollector::OnTakenFromGraph(Graph* graph) {
+  UnregisterObservers(graph);
+  graph_ = nullptr;
+}
+
+void MetricsCollector::OnIsVisibleChanged(const PageNode* page_node) {
   // The page becomes visible again, clear all records in order to
   // report metrics when page becomes invisible next time.
-  if (page_node->is_visible())
+  if (page_node->IsVisible())
     ResetMetricsReportRecord(page_node);
 }
 
-void MetricsCollector::OnUkmSourceIdChanged(PageNodeImpl* page_node) {
-  ukm::SourceId ukm_source_id = page_node->ukm_source_id();
+void MetricsCollector::OnUkmSourceIdChanged(const PageNode* page_node) {
+  ukm::SourceId ukm_source_id = page_node->GetUkmSourceID();
   UpdateUkmSourceIdForPage(page_node, ukm_source_id);
-  MetricsReportRecord& record =
-      metrics_report_record_map_.find(page_node)->second;
-  record.UpdateUkmSourceID(ukm_source_id);
+  auto* record = GetMetricsReportRecord(page_node);
+  record->UpdateUkmSourceID(ukm_source_id);
 }
 
-void MetricsCollector::OnFaviconUpdated(PageNodeImpl* page_node) {
+void MetricsCollector::OnFaviconUpdated(const PageNode* page_node) {
   // Only record metrics while it is backgrounded.
-  if (page_node->is_visible() || !ShouldReportMetrics(page_node))
+  if (page_node->IsVisible() || !ShouldReportMetrics(page_node))
     return;
-  MetricsReportRecord& record =
-      metrics_report_record_map_.find(page_node)->second;
-  record.first_favicon_updated.OnSignalReceived(
-      true, page_node->TimeSinceLastVisibilityChange(),
-      graph()->ukm_recorder());
+  auto* record = GetMetricsReportRecord(page_node);
+  record->first_favicon_updated.OnSignalReceived(
+      true, page_node->GetTimeSinceLastVisibilityChange(),
+      graph_->GetUkmRecorder());
 }
 
-void MetricsCollector::OnTitleUpdated(PageNodeImpl* page_node) {
+void MetricsCollector::OnTitleUpdated(const PageNode* page_node) {
   // Only record metrics while it is backgrounded.
-  if (page_node->is_visible() || !ShouldReportMetrics(page_node))
+  if (page_node->IsVisible() || !ShouldReportMetrics(page_node))
     return;
-  MetricsReportRecord& record =
-      metrics_report_record_map_.find(page_node)->second;
-  record.first_title_updated.OnSignalReceived(
-      true, page_node->TimeSinceLastVisibilityChange(),
-      graph()->ukm_recorder());
+  auto* record = GetMetricsReportRecord(page_node);
+  record->first_title_updated.OnSignalReceived(
+      true, page_node->GetTimeSinceLastVisibilityChange(),
+      graph_->GetUkmRecorder());
 }
 
 void MetricsCollector::OnExpectedTaskQueueingDurationSample(
-    ProcessNodeImpl* process_node) {
+    const ProcessNode* process_node) {
   // Report this measurement to all pages that are hosting a main frame in
   // the process that was sampled.
   const base::TimeDelta& sample =
-      process_node->expected_task_queueing_duration();
-  for (auto* frame_node : process_node->frame_nodes()) {
+      process_node->GetExpectedTaskQueueingDuration();
+  for (const auto* frame_node : process_node->GetFrameNodes()) {
     if (!frame_node->IsMainFrame())
       continue;
-    auto* page_node = frame_node->page_node();
+    auto* page_node = frame_node->GetPageNode();
     if (!IsCollectingExpectedQueueingTimeForUkm(page_node))
       continue;
     RecordExpectedQueueingTimeForUkm(page_node, sample);
   }
 }
 
-bool MetricsCollector::ShouldReportMetrics(const PageNodeImpl* page_node) {
-  return page_node->TimeSinceLastNavigation() > kMetricsReportDelayTimeout;
+// static
+MetricsCollector::MetricsReportRecord* MetricsCollector::GetMetricsReportRecord(
+    const PageNode* page_node) {
+  auto* holder = MetricsReportRecordHolder::GetOrCreate(page_node);
+  return &holder->metrics_report_record;
+}
+
+// static
+MetricsCollector::UkmCollectionState* MetricsCollector::GetUkmCollectionState(
+    const PageNode* page_node) {
+  auto* holder = UkmCollectionStateHolder::GetOrCreate(page_node);
+  return &holder->ukm_collection_state;
+}
+
+void MetricsCollector::RegisterObservers(Graph* graph) {
+  graph->AddFrameNodeObserver(this);
+  graph->AddPageNodeObserver(this);
+  graph->AddProcessNodeObserver(this);
+}
+
+void MetricsCollector::UnregisterObservers(Graph* graph) {
+  graph->RemoveFrameNodeObserver(this);
+  graph->RemovePageNodeObserver(this);
+  graph->RemoveProcessNodeObserver(this);
+}
+
+bool MetricsCollector::ShouldReportMetrics(const PageNode* page_node) {
+  return page_node->GetTimeSinceLastNavigation() > kMetricsReportDelayTimeout;
 }
 
 bool MetricsCollector::IsCollectingExpectedQueueingTimeForUkm(
-    PageNodeImpl* page_node) {
-  UkmCollectionState& state = ukm_collection_state_map_[page_node];
-  return state.ukm_source_id != ukm::kInvalidSourceId &&
-         ++state.num_unreported_eqt_measurements >= frequency_ukm_eqt_reported_;
+    const PageNode* page_node) {
+  auto* state = GetUkmCollectionState(page_node);
+  return state->ukm_source_id != ukm::kInvalidSourceId &&
+         ++state->num_unreported_eqt_measurements >=
+             frequency_ukm_eqt_reported_;
 }
 
 void MetricsCollector::RecordExpectedQueueingTimeForUkm(
-    PageNodeImpl* page_node,
+    const PageNode* page_node,
     const base::TimeDelta& expected_queueing_time) {
-  UkmCollectionState& state = ukm_collection_state_map_[page_node];
-  state.num_unreported_eqt_measurements = 0u;
-  ukm::builders::ResponsivenessMeasurement(state.ukm_source_id)
+  auto* state = GetUkmCollectionState(page_node);
+  state->num_unreported_eqt_measurements = 0u;
+  ukm::builders::ResponsivenessMeasurement(state->ukm_source_id)
       .SetExpectedTaskQueueingDuration(expected_queueing_time.InMilliseconds())
-      .Record(graph()->ukm_recorder());
+      .Record(graph_->GetUkmRecorder());
 }
 
-void MetricsCollector::UpdateUkmSourceIdForPage(PageNodeImpl* page_node,
+void MetricsCollector::UpdateUkmSourceIdForPage(const PageNode* page_node,
                                                 ukm::SourceId ukm_source_id) {
-  UkmCollectionState& state = ukm_collection_state_map_[page_node];
-
-  state.ukm_source_id = ukm_source_id;
+  auto* state = GetUkmCollectionState(page_node);
+  state->ukm_source_id = ukm_source_id;
   // Updating the |ukm_source_id| restarts usage collection.
-  state.num_unreported_eqt_measurements = 0u;
+  state->num_unreported_eqt_measurements = 0u;
 }
 
 void MetricsCollector::UpdateWithFieldTrialParams() {
@@ -179,10 +186,9 @@
       kDefaultFrequencyUkmEQTReported);
 }
 
-void MetricsCollector::ResetMetricsReportRecord(PageNodeImpl* page_node) {
-  DCHECK(metrics_report_record_map_.find(page_node) !=
-         metrics_report_record_map_.end());
-  metrics_report_record_map_.find(page_node)->second.Reset();
+void MetricsCollector::ResetMetricsReportRecord(const PageNode* page_node) {
+  auto* record = GetMetricsReportRecord(page_node);
+  record->Reset();
 }
 
 MetricsCollector::MetricsReportRecord::MetricsReportRecord() = default;
diff --git a/chrome/browser/performance_manager/observers/metrics_collector.h b/chrome/browser/performance_manager/observers/metrics_collector.h
index 11a5560f..08b5a72 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector.h
+++ b/chrome/browser/performance_manager/observers/metrics_collector.h
@@ -11,16 +11,15 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
 #include "chrome/browser/performance_manager/observers/background_metrics_reporter.h"
-#include "chrome/browser/performance_manager/observers/graph_observer.h"
+#include "chrome/browser/performance_manager/public/graph/frame_node.h"
+#include "chrome/browser/performance_manager/public/graph/graph.h"
+#include "chrome/browser/performance_manager/public/graph/page_node.h"
+#include "chrome/browser/performance_manager/public/graph/process_node.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 
 namespace performance_manager {
 
-class FrameNodeImpl;
-class NodeBase;
-class PageNodeImpl;
-
 extern const char kTabFromBackgroundedToFirstFaviconUpdatedUMA[];
 extern const char kTabFromBackgroundedToFirstTitleUpdatedUMA[];
 extern const char
@@ -29,24 +28,35 @@
 extern const int kDefaultFrequencyUkmEQTReported;
 
 // The MetricsCollector is a graph observer that reports UMA/UKM.
-class MetricsCollector : public GraphImplObserverDefaultImpl {
+class MetricsCollector : public FrameNode::ObserverDefaultImpl,
+                         public GraphOwned,
+                         public PageNode::ObserverDefaultImpl,
+                         public ProcessNode::ObserverDefaultImpl {
  public:
   MetricsCollector();
   ~MetricsCollector() override;
 
-  // GraphObserver implementation.
-  bool ShouldObserve(const NodeBase* node) override;
-  void OnNodeAdded(NodeBase* node) override;
-  void OnBeforeNodeRemoved(NodeBase* node) override;
-  void OnNonPersistentNotificationCreated(FrameNodeImpl* frame_node) override;
-  void OnIsVisibleChanged(PageNodeImpl* page_node) override;
-  void OnUkmSourceIdChanged(PageNodeImpl* page_node) override;
-  void OnFaviconUpdated(PageNodeImpl* page_node) override;
-  void OnTitleUpdated(PageNodeImpl* page_node) override;
-  void OnExpectedTaskQueueingDurationSample(
-      ProcessNodeImpl* process_node) override;
+  // FrameNodeObserver implementation:
+  void OnNonPersistentNotificationCreated(const FrameNode* frame_node) override;
 
- private:
+  // GraphOwned implementation:
+  void OnPassedToGraph(Graph* graph) override;
+  void OnTakenFromGraph(Graph* graph) override;
+
+  // PageNodeObserver implementation:
+  void OnIsVisibleChanged(const PageNode* page_node) override;
+  void OnUkmSourceIdChanged(const PageNode* page_node) override;
+  void OnFaviconUpdated(const PageNode* page_node) override;
+  void OnTitleUpdated(const PageNode* page_node) override;
+
+  // ProcessNodeObserver implementation:
+  void OnExpectedTaskQueueingDurationSample(
+      const ProcessNode* process_node) override;
+
+ protected:
+  friend class MetricsReportRecordHolder;
+  friend class UkmCollectionStateHolder;
+
   struct MetricsReportRecord {
     MetricsReportRecord();
     MetricsReportRecord(const MetricsReportRecord& other);
@@ -75,20 +85,29 @@
     ukm::SourceId ukm_source_id = ukm::kInvalidSourceId;
   };
 
-  bool ShouldReportMetrics(const PageNodeImpl* page_node);
-  bool IsCollectingExpectedQueueingTimeForUkm(PageNodeImpl* page_node);
+ private:
+  static MetricsReportRecord* GetMetricsReportRecord(const PageNode* page_node);
+  static UkmCollectionState* GetUkmCollectionState(const PageNode* page_node);
+
+  // (Un)registers the various node observer flavors of this object with the
+  // graph. These are invoked by OnPassedToGraph and OnTakenFromGraph, but
+  // hoisted to their own functions for testing.
+  void RegisterObservers(Graph* graph);
+  void UnregisterObservers(Graph* graph);
+
+  bool ShouldReportMetrics(const PageNode* page_node);
+  bool IsCollectingExpectedQueueingTimeForUkm(const PageNode* page_node);
   void RecordExpectedQueueingTimeForUkm(
-      PageNodeImpl* page_node,
+      const PageNode* page_node,
       const base::TimeDelta& expected_queueing_time);
-  void UpdateUkmSourceIdForPage(PageNodeImpl* page_node,
+  void UpdateUkmSourceIdForPage(const PageNode* page_node,
                                 ukm::SourceId ukm_source_id);
   void UpdateWithFieldTrialParams();
-  void ResetMetricsReportRecord(PageNodeImpl* page_nod);
+  void ResetMetricsReportRecord(const PageNode* page_nod);
 
-  // The metrics_report_record_map_ is used to record whether a metric was
-  // already reported to avoid reporting multiple metrics.
-  std::map<PageNodeImpl*, MetricsReportRecord> metrics_report_record_map_;
-  std::map<PageNodeImpl*, UkmCollectionState> ukm_collection_state_map_;
+  // The graph to which this object belongs.
+  Graph* graph_ = nullptr;
+
   // The number of reports to wait before reporting ExpectedQueueingTime. For
   // example, if |frequency_ukm_eqt_reported_| is 2, then the first value is not
   // reported, the second one is, the third one isn't, etc.
diff --git a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
index efde6cd8..2d7018e4 100644
--- a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
+++ b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
@@ -34,16 +34,16 @@
   MAYBE_MetricsCollectorTest() : GraphTestHarness() {}
 
   void SetUp() override {
-    metrics_collector_ = std::make_unique<MetricsCollector>();
+    metrics_collector_ = new MetricsCollector();
     PerformanceManagerClock::SetClockForTesting(&clock_);
-
     // Sets a valid starting time.
     clock_.SetNowTicks(base::TimeTicks::Now());
-    graph()->RegisterObserver(metrics_collector_.get());
+    graph()->PassToGraph(base::WrapUnique(metrics_collector_));
   }
 
   void TearDown() override {
-    graph()->UnregisterObserver(metrics_collector_.get());
+    graph()->TakeFromGraph(metrics_collector_);  // Destroy the observer.
+    metrics_collector_ = nullptr;
     PerformanceManagerClock::ResetClockForTesting();
   }
 
@@ -56,7 +56,7 @@
   base::SimpleTestTickClock clock_;
 
  private:
-  std::unique_ptr<MetricsCollector> metrics_collector_;
+  MetricsCollector* metrics_collector_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(MAYBE_MetricsCollectorTest);
 };
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index 08390210f..dde96f45 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -268,9 +268,7 @@
   graph_.PassToGraph(std::make_unique<FrozenFrameAggregator>());
   graph_.PassToGraph(std::make_unique<PageAlmostIdleDecorator>());
   graph_.PassToGraph(std::make_unique<IsolationContextMetrics>());
-
-  // Register new |GraphImplObserver| implementations here.
-  RegisterObserver(std::make_unique<MetricsCollector>());
+  graph_.PassToGraph(std::make_unique<MetricsCollector>());
 
 #if defined(OS_WIN)
   if (base::FeatureList::IsEnabled(features::kEmptyWorkingSet))
diff --git a/chrome/browser/performance_manager/public/graph/graph.h b/chrome/browser/performance_manager/public/graph/graph.h
index 39eac29..45afb4d 100644
--- a/chrome/browser/performance_manager/public/graph/graph.h
+++ b/chrome/browser/performance_manager/public/graph/graph.h
@@ -12,6 +12,10 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 
+namespace ukm {
+class UkmRecorder;
+}  // namespace ukm
+
 namespace performance_manager {
 
 class GraphObserver;
@@ -71,6 +75,9 @@
   virtual std::vector<const PageNode*> GetAllPageNodes() const = 0;
   virtual std::vector<const ProcessNode*> GetAllProcessNodes() const = 0;
 
+  // Returns the associated UKM recorder if it is defined.
+  virtual ukm::UkmRecorder* GetUkmRecorder() const = 0;
+
   // The following functions are implementation detail and should not need to be
   // used by external clients. They provide the ability to safely downcast to
   // the underlying implementation.
diff --git a/chrome/browser/performance_manager/public/graph/page_node.h b/chrome/browser/performance_manager/public/graph/page_node.h
index 63c3c46..21a32b3 100644
--- a/chrome/browser/performance_manager/public/graph/page_node.h
+++ b/chrome/browser/performance_manager/public/graph/page_node.h
@@ -37,6 +37,10 @@
   // See PageNodeObserver::OnIsVisibleChanged.
   virtual bool IsVisible() const = 0;
 
+  // Returns the time since the last visibility change. It is always well
+  // defined as the visibility property is set at node creation.
+  virtual base::TimeDelta GetTimeSinceLastVisibilityChange() const = 0;
+
   // Returns true if this page is currently audible, false otherwise.
   // See PageNodeObserver::OnIsAudibleChanged.
   virtual bool IsAudible() const = 0;
@@ -60,6 +64,10 @@
   // See PageNodeObserver::OnMainFrameNavigationCommitted.
   virtual int64_t GetNavigationID() const = 0;
 
+  // Returns "zero" if no navigation has happened, otherwise returns the time
+  // since the last navigation commit.
+  virtual base::TimeDelta GetTimeSinceLastNavigation() const = 0;
+
   // Returns the current main frame node (if there is one), otherwise returns
   // any of the potentially multiple main frames that currently exist. If there
   // are no main frames at the moment, returns nullptr.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 768d00ab..53cbd3e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2866,6 +2866,8 @@
       "views/page_info/page_info_bubble_view.h",
       "views/page_info/page_info_bubble_view_base.cc",
       "views/page_info/page_info_bubble_view_base.h",
+      "views/page_info/page_info_hover_button.cc",
+      "views/page_info/page_info_hover_button.h",
       "views/page_info/permission_selector_row.cc",
       "views/page_info/permission_selector_row.h",
       "views/page_info/permission_selector_row_observer.h",
diff --git a/chrome/browser/ui/app_list/app_launch_event_logger.cc b/chrome/browser/ui/app_list/app_launch_event_logger.cc
index f486fc9..40a7eba 100644
--- a/chrome/browser/ui/app_list/app_launch_event_logger.cc
+++ b/chrome/browser/ui/app_list/app_launch_event_logger.cc
@@ -346,28 +346,17 @@
 std::vector<std::string> AppLaunchEventLogger::ChooseAppsToLog(
     const std::string clicked_app_id) {
   bool has_clicked_app = false;
-  std::vector<std::string> clicked_apps;
-  std::vector<std::string> unclicked_apps;
-  // Group apps by whether they have been clicked on. Do not include the
-  // currently clicked app.
+  std::vector<std::string> apps_without_current;
+  // Do not include the currently clicked app.
   for (auto& app : app_features_map_) {
     if (app.first == clicked_app_id) {
       has_clicked_app = true;
       continue;
     }
-    if (app.second.has_most_recently_used_index()) {
-      clicked_apps.push_back(app.first);
-    } else {
-      unclicked_apps.push_back(app.first);
-    }
+    apps_without_current.push_back(app.first);
   }
-
-  std::vector<std::string> apps(Sample(clicked_apps, kNumRandomAppsToLog));
-  if (apps.size() < kNumRandomAppsToLog) {
-    std::vector<std::string> unclicked_sample(
-        Sample(unclicked_apps, kNumRandomAppsToLog - apps.size()));
-    apps.insert(apps.end(), unclicked_sample.begin(), unclicked_sample.end());
-  }
+  std::vector<std::string> apps(
+      Sample(apps_without_current, kNumRandomAppsToLog));
   if (has_clicked_app) {
     apps.push_back(clicked_app_id);
   }
diff --git a/chrome/browser/ui/app_list/app_launch_event_logger.h b/chrome/browser/ui/app_list/app_launch_event_logger.h
index c827155..a134e31 100644
--- a/chrome/browser/ui/app_list/app_launch_event_logger.h
+++ b/chrome/browser/ui/app_list/app_launch_event_logger.h
@@ -92,12 +92,9 @@
                             const std::string& app_id,
                             const std::string& arc_package_name,
                             const std::string& pwa_url);
-  // Chooses up to five apps to log, plus the app clicked on. Randomly chooses
-  // up to five apps that have previously been clicked on. These are preferred
-  // as they have metrics about past click behaviour. If there are fewer than
-  // five of these apps, then, in addition, randomly chooses from apps not
-  // clicked on, to get a total of five apps. If there are fewer than five apps
-  // that can be logged on the device, logs every app once.
+  // Chooses up to five random apps to log, plus the app clicked on.
+  // If there are fewer than five apps that can be logged on the device, logs
+  // every app once.
   std::vector<std::string> ChooseAppsToLog(const std::string clicked_app_id);
   // Records a UMA histogram of the app type clicked on.
   void RecordAppTypeClicked(AppLaunchEvent_AppType app_type);
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
index 15db2ed..36baf5ae 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.cc
@@ -4,12 +4,14 @@
 
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h"
 
+#include <cmath>
 #include <utility>
 
 #include "base/time/time.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/frecency_store.pb.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/histogram_util.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.pb.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.h"
 
 namespace app_list {
 namespace {
@@ -18,6 +20,12 @@
 
 }  // namespace
 
+FakePredictor::FakePredictor() {
+  // The fake predictor should only be used for testing, not in production.
+  // Record an error so we know if it is being used.
+  LogConfigurationError(ConfigurationError::kFakePredictorUsed);
+}
+
 FakePredictor::FakePredictor(const FakePredictorConfig& config) {
   // The fake predictor should only be used for testing, not in production.
   // Record an error so we know if it is being used.
@@ -443,4 +451,96 @@
   frequencies_.FromProto(proto.markov_predictor().frequencies());
 }
 
+ExponentialWeightsEnsemble::ExponentialWeightsEnsemble(
+    const ExponentialWeightsEnsembleConfig& config)
+    : learning_rate_(config.learning_rate()) {
+  for (int i = 0; i < config.predictors_size(); ++i) {
+    predictors_.push_back(
+        {MakePredictor(config.predictors(i)), 1.0f / config.predictors_size()});
+  }
+}
+
+ExponentialWeightsEnsemble::~ExponentialWeightsEnsemble() = default;
+
+const char ExponentialWeightsEnsemble::kPredictorName[] =
+    "ExponentialWeightsEnsemble";
+const char* ExponentialWeightsEnsemble::GetPredictorName() const {
+  return kPredictorName;
+}
+
+void ExponentialWeightsEnsemble::Train(unsigned int target,
+                                       unsigned int condition) {
+  for (auto& predictor_weight : predictors_)
+    predictor_weight.first->Train(target, condition);
+
+  for (auto& predictor_weight : predictors_) {
+    const auto& ranks = predictor_weight.first->Rank(condition);
+
+    // Find the normalized score associated with the ground-truth |target|.
+    // If the predictor didn't rank the ground truth target, consider that a
+    // score of 0.
+    float total_score = 0.0f;
+    for (const auto& target_score : ranks)
+      total_score += target_score.second;
+
+    float score = 0.0f;
+    const auto& it = ranks.find(target);
+    if (total_score > 0.0f && it != ranks.end())
+      score = it->second / total_score;
+
+    // Perform an exponential weights update.
+    predictor_weight.second *= std::exp(-learning_rate_ * (1 - score));
+  }
+
+  // Re-normalize weights.
+  float total_weight = 0.0f;
+  for (const auto& predictor_weight : predictors_)
+    total_weight += predictor_weight.second;
+  for (auto& predictor_weight : predictors_) {
+    predictor_weight.second /= total_weight;
+  }
+}
+
+std::map<unsigned int, float> ExponentialWeightsEnsemble::Rank(
+    unsigned int condition) {
+  std::map<unsigned int, float> result;
+  for (const auto& predictor_weight : predictors_) {
+    const auto& ranks = predictor_weight.first->Rank(condition);
+    for (const auto& target_score : ranks) {
+      // Weights are kept normalized by Train, so all scores remain in [0,1] if
+      // the predictors' scores are in [0,1].
+      result[target_score.first] +=
+          target_score.second * predictor_weight.second;
+    }
+  }
+  return result;
+}
+
+void ExponentialWeightsEnsemble::ToProto(
+    RecurrencePredictorProto* proto) const {
+  auto* ensemble = proto->mutable_exponential_weights_ensemble();
+
+  for (const auto& predictor_weight : predictors_) {
+    predictor_weight.first->ToProto(ensemble->add_predictors());
+    ensemble->add_weights(predictor_weight.second);
+  }
+}
+
+void ExponentialWeightsEnsemble::FromProto(
+    const RecurrencePredictorProto& proto) {
+  if (!proto.has_exponential_weights_ensemble()) {
+    // TODO(921444): Add error metrics for new predictors.
+    return;
+  }
+  const auto& ensemble = proto.exponential_weights_ensemble();
+  int num_predictors = static_cast<int>(predictors_.size());
+  DCHECK_EQ(num_predictors, ensemble.predictors_size());
+  DCHECK_EQ(num_predictors, ensemble.weights_size());
+
+  for (int i = 0; i < num_predictors; ++i) {
+    predictors_[i].first->FromProto(ensemble.predictors(i));
+    predictors_[i].second = ensemble.weights(i);
+  }
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
index 62d7a50..7486fe46 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h
@@ -7,6 +7,7 @@
 
 #include <map>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "base/gtest_prod_util.h"
@@ -28,6 +29,8 @@
     RecurrencePredictorConfigProto::HourBinPredictorConfig;
 using MarkovPredictorConfig =
     RecurrencePredictorConfigProto::MarkovPredictorConfig;
+using ExponentialWeightsEnsembleConfig =
+    RecurrencePredictorConfigProto::ExponentialWeightsEnsembleConfig;
 
 // |RecurrencePredictor| is the interface for all predictors used by
 // |RecurrenceRanker| to drive rankings. If a predictor has some form of
@@ -66,6 +69,7 @@
 // so should not be used for anything except testing.
 class FakePredictor : public RecurrencePredictor {
  public:
+  FakePredictor();
   explicit FakePredictor(const FakePredictorConfig& config);
   ~FakePredictor() override;
 
@@ -287,6 +291,47 @@
   DISALLOW_COPY_AND_ASSIGN(MarkovPredictor);
 };
 
+// A predictor that uses a weighted ensemble of other predictors' scores. Any
+// number of constituent predictors can be configured. On training, all
+// constituent predictors are trained, and the ensemble model itself learns
+// weights for each predictor. At inference, the ensemble ranks targets based on
+// a weighted average of its predictors.
+//
+// The weights for each predictor are trained with the exponential weights
+// algorithm. If |t'| is the correct target The weight w_i for predictor i is
+// updated according to:
+//   w_i' = w_i * exp(-learning_rate * p_i(t = t')),
+// where p_i(t) is probability (normalized score) of target t returned by
+// predictor i. Weights are kept normalized to sum to 1.
+class ExponentialWeightsEnsemble : public RecurrencePredictor {
+ public:
+  explicit ExponentialWeightsEnsemble(
+      const ExponentialWeightsEnsembleConfig& config);
+  ~ExponentialWeightsEnsemble() override;
+
+  // RecurrencePredictor:
+  void Train(unsigned int target, unsigned int condition) override;
+  std::map<unsigned int, float> Rank(unsigned int condition) override;
+  void ToProto(RecurrencePredictorProto* proto) const override;
+  void FromProto(const RecurrencePredictorProto& proto) override;
+  const char* GetPredictorName() const override;
+
+  static const char kPredictorName[];
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(ExponentialWeightsEnsembleTest,
+                           GoodModelAndBadModel);
+  FRIEND_TEST_ALL_PREFIXES(ExponentialWeightsEnsembleTest, TwoBalancedModels);
+
+  // Pairs of the constituent predictors, and their weights.
+  std::vector<std::pair<std::unique_ptr<RecurrencePredictor>, float>>
+      predictors_;
+
+  float learning_rate_ = 0.0f;
+
+  DISALLOW_COPY_AND_ASSIGN(ExponentialWeightsEnsemble);
+};
+
 }  // namespace app_list
 
 #endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RECURRENCE_PREDICTOR_H_
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
index 410086c0..45d586d 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.proto
@@ -64,6 +64,16 @@
   required RecurrencePredictorProto frequencies = 1;
 }
 
+// Simple ensemble predictor.
+message ExponentialWeightsEnsembleProto {
+  // The state of each component predictor.
+  repeated RecurrencePredictorProto predictors = 1;
+
+  // The weights assigned to each member predictor. The order of |weights|
+  // corresponds to the order of |predictors|.
+  repeated float weights = 2;
+}
+
 // Represents the serialisation of one particular predictor.
 message RecurrencePredictorProto {
   oneof predictor {
@@ -72,5 +82,6 @@
     HourBinPredictorProto hour_bin_predictor = 3;
     ConditionalFrequencyPredictorProto conditional_frequency_predictor = 4;
     MarkovPredictorProto markov_predictor = 5;
+    ExponentialWeightsEnsembleProto exponential_weights_ensemble = 6;
   }
 }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc
index 525c691b..94a7de9 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/app_list/search/search_result_ranker/recurrence_predictor.h"
 
 #include <exception>
+#include <map>
 #include <memory>
 #include <vector>
 
@@ -22,6 +23,7 @@
 
 using testing::_;
 using testing::FloatEq;
+using testing::FloatNear;
 using testing::Pair;
 using testing::UnorderedElementsAre;
 
@@ -502,4 +504,140 @@
   }
 }
 
+class ExponentialWeightsEnsembleTest : public testing::Test {
+ protected:
+  // Test ensemble config with a fake, a frecency, and a conditional frequency
+  // predictor.
+  ExponentialWeightsEnsembleConfig MakeConfig() {
+    ExponentialWeightsEnsembleConfig config;
+    config.set_learning_rate(1.0f);
+
+    config.add_predictors()->mutable_fake_predictor();
+    config.add_predictors()->mutable_frecency_predictor()->set_decay_coeff(
+        0.5f);
+    config.add_predictors()->mutable_conditional_frequency_predictor();
+
+    return config;
+  }
+
+  std::unique_ptr<ExponentialWeightsEnsemble> MakeEnsemble(
+      const ExponentialWeightsEnsembleConfig& config) {
+    return std::make_unique<ExponentialWeightsEnsemble>(config);
+  }
+
+  // A predictor that always returns the same prediction, whose weight is
+  // expected to decay in an ensemble.
+  class BadPredictor : public FakePredictor {
+   public:
+    // FakePredictor:
+    std::map<unsigned int, float> Rank(unsigned int condition) override {
+      return {{417u, 1.0f}};
+    }
+  };
+};
+
+TEST_F(ExponentialWeightsEnsembleTest, RankWithNoTargets) {
+  auto ensemble = MakeEnsemble(MakeConfig());
+  EXPECT_TRUE(ensemble->Rank(0u).empty());
+}
+
+TEST_F(ExponentialWeightsEnsembleTest, SimpleRecordAndRank) {
+  // Test a model with a single predictor. Because there is only one model, its
+  // weight should always be 1.0.
+  ExponentialWeightsEnsembleConfig config;
+  config.set_learning_rate(1.0f);
+  config.add_predictors()->mutable_conditional_frequency_predictor();
+  auto ewe = MakeEnsemble(config);
+
+  ewe->Train(0u, 0u);
+  ewe->Train(0u, 0u);
+  ewe->Train(0u, 0u);
+  ewe->Train(0u, 0u);
+  ewe->Train(2u, 1u);
+  ewe->Train(2u, 1u);
+  ewe->Train(2u, 1u);
+  ewe->Train(3u, 1u);
+
+  EXPECT_THAT(ewe->Rank(0u), UnorderedElementsAre(Pair(0u, FloatEq(1.0f))));
+  EXPECT_THAT(ewe->Rank(1u), UnorderedElementsAre(Pair(2u, FloatEq(0.75f)),
+                                                  Pair(3u, FloatEq(0.25f))));
+}
+
+TEST_F(ExponentialWeightsEnsembleTest, GoodModelAndBadModel) {
+  // Test with two predictors, one of which is always wrong and whose weight
+  // should go to zero.
+  ExponentialWeightsEnsembleConfig config;
+  config.set_learning_rate(1.0f);
+  config.add_predictors()->mutable_fake_predictor();
+  // Because the bad predictor isn't a real predictor, add a fake predictor and
+  // manually replace it after the ensemble is constructed.
+  config.add_predictors()->mutable_fake_predictor();
+
+  auto ewe = MakeEnsemble(config);
+  ewe->predictors_[1].first = std::make_unique<BadPredictor>();
+
+  for (int i = 0; i < 5; ++i)
+    ewe->Train(1u, 0u);
+  for (int i = 0; i < 5; ++i)
+    ewe->Train(2u, 0u);
+
+  // Expect the result scores from the ensemble to be approximately the scores
+  // from the predictor itself, as the weight should be near 1. Expect the
+  // result from the bad predictor to have a score near 0.
+  EXPECT_THAT(ewe->predictors_[0].second, FloatNear(1.0f, 0.05f));
+  EXPECT_THAT(ewe->predictors_[1].second, FloatNear(0.0f, 0.05f));
+  EXPECT_THAT(ewe->Rank(0u),
+              UnorderedElementsAre(Pair(1u, FloatNear(5.0f, 0.05f)),
+                                   Pair(2u, FloatNear(5.0f, 0.05f)),
+                                   Pair(417u, FloatNear(0.0f, 0.05f))));
+}
+
+TEST_F(ExponentialWeightsEnsembleTest, TwoBalancedModels) {
+  // Test with two identical predictors. Their weights should stay balanced over
+  // time.
+  ExponentialWeightsEnsembleConfig config;
+  config.set_learning_rate(1.0f);
+  config.add_predictors()->mutable_fake_predictor();
+  config.add_predictors()->mutable_fake_predictor();
+  auto ewe = MakeEnsemble(config);
+
+  for (int i = 0; i < 5; ++i)
+    ewe->Train(1u, 0u);
+  for (int i = 0; i < 5; ++i)
+    ewe->Train(2u, 0u);
+
+  // The scores should be exactly those from one fake predictor, and their
+  // weights should be 0.5 each.
+  EXPECT_THAT(ewe->predictors_[0].second, FloatEq(0.5f));
+  EXPECT_THAT(ewe->predictors_[1].second, FloatEq(0.5f));
+  EXPECT_THAT(ewe->Rank(0u), UnorderedElementsAre(Pair(1u, FloatEq(5.0f)),
+                                                  Pair(2u, FloatEq(5.0f))));
+}
+
+TEST_F(ExponentialWeightsEnsembleTest, ToAndFromProto) {
+  // Add in another predictor for completeness.
+  auto config = MakeConfig();
+  config.add_predictors()->mutable_markov_predictor();
+  auto ensemble_a = MakeEnsemble(config);
+
+  // Do some training.
+  for (int i = 0; i < 10; ++i)
+    for (int j = 0; j < i; ++j)
+      ensemble_a->Train(j, i);
+  for (int i = 0; i < 10; ++i)
+    for (int j = 0; j < i; ++j)
+      ensemble_a->Train(2 * j, 0u);
+
+  // Expect a new ensemble loaded from the old ensemble's state to have the same
+  // rankings.
+  RecurrencePredictorProto proto;
+  ensemble_a->ToProto(&proto);
+
+  auto ensemble_b = MakeEnsemble(config);
+  ensemble_b->FromProto(proto);
+
+  for (int i = 0; i < 10; ++i)
+    EXPECT_EQ(ensemble_a->Rank(i), ensemble_b->Rank(i));
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
index 0b1133e..0698e1a5 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_config.proto
@@ -49,6 +49,14 @@
   // A first-order Markov chain predictor.
   message MarkovPredictorConfig {}
 
+  message ExponentialWeightsEnsembleConfig {
+    // The learning rate to apply to the ensemble weights.
+    required float learning_rate = 1;
+
+    // The configuration of the component predictors in the ensemble.
+    repeated RecurrencePredictorConfigProto predictors = 2;
+  }
+
   // The choice of which kind of predictor to use, and its configuration.
   oneof predictor {
     FakePredictorConfig fake_predictor = 1;
@@ -57,6 +65,7 @@
     HourBinPredictorConfig hour_bin_predictor = 4;
     ConditionalFrequencyPredictorConfig conditional_frequency_predictor = 5;
     MarkovPredictorConfig markov_predictor = 6;
+    ExponentialWeightsEnsembleConfig exponential_weights_ensemble = 7;
   }
 }
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
index ec60128..569966e 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
@@ -27,6 +27,9 @@
     return std::make_unique<HourBinPredictor>(config.hour_bin_predictor());
   if (config.has_markov_predictor())
     return std::make_unique<MarkovPredictor>(config.markov_predictor());
+  if (config.has_exponential_weights_ensemble())
+    return std::make_unique<ExponentialWeightsEnsemble>(
+        config.exponential_weights_ensemble());
 
   LogConfigurationError(ConfigurationError::kInvalidPredictor);
   NOTREACHED();
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 072a05c..6850d89 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -320,6 +320,8 @@
   // coming up in Multi-Window mode, mark the source as unavailable.
   mf_controller->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                           /*has_suggestions=*/false);
+  mf_controller->UpdateSourceAvailability(FillingSource::TOUCH_TO_FILL,
+                                          /*has_suggestions=*/false);
   mf_controller->Hide();
 #endif
   delegate_->DidAcceptSuggestion(suggestion.value, suggestion.frontend_id,
@@ -565,9 +567,16 @@
 
 void AutofillPopupControllerImpl::HideViewAndDie() {
 #if defined(OS_ANDROID)
+  // Mark the popup-like filling sources as unavailable.
+  // Note: We don't invoke ManualFillingController::Hide() here, as we might
+  // switch between text input fields.
   ManualFillingController::GetOrCreate(web_contents_)
       ->UpdateSourceAvailability(FillingSource::AUTOFILL,
                                  /*has_suggestions=*/false);
+
+  ManualFillingController::GetOrCreate(web_contents_)
+      ->UpdateSourceAvailability(FillingSource::TOUCH_TO_FILL,
+                                 /*has_suggestions=*/false);
 #endif
 
   if (view_)
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index e4836b29..a752157 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -765,10 +765,8 @@
   EXPECT_EQ(PageInfo::SITE_IDENTITY_STATUS_EV_CERT,
             page_info()->site_identity_status());
   EXPECT_EQ(base::UTF8ToUTF16("Google Inc"), page_info()->organization_name());
-  EXPECT_EQ(
-      base::UTF8ToUTF16(
-          "This page has been identified as being owned by Google Inc [US]."),
-      page_info()->site_details_message());
+  EXPECT_EQ(base::UTF8ToUTF16("Issued to: Google Inc [US]"),
+            page_info()->site_details_message());
 }
 
 TEST_F(PageInfoTest, HTTPSRevocationError) {
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 51f5ba9e..2b43fc0 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "base/bind.h"
@@ -38,6 +39,7 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
 #include "chrome/browser/ui/views/page_info/chosen_object_view.h"
+#include "chrome/browser/ui/views/page_info/page_info_hover_button.h"
 #include "chrome/browser/ui/views/page_info/permission_selector_row.h"
 #include "chrome/browser/vr/vr_tab_helper.h"
 #include "chrome/common/url_constants.h"
@@ -58,8 +60,10 @@
 #include "ui/gfx/image/image.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/image_view.h"
@@ -108,55 +112,16 @@
   column_set->AddPaddingColumn(views::GridLayout::kFixedSize, margin);
 }
 
-// Formats strings and returns the |gfx::Range| of the newly inserted string.
-gfx::Range GetRangeForFormatString(int string_id,
-                                   const base::string16& insert_string,
-                                   base::string16* final_string) {
-  size_t offset;
-  *final_string = l10n_util::GetStringFUTF16(string_id, insert_string, &offset);
-  return gfx::Range(offset, offset + insert_string.length());
-}
-
-// Creates a button that formats the string given by |title_resource_id| with
-// |secondary_text| and displays the latter part in the secondary text color.
-std::unique_ptr<HoverButton> CreateMoreInfoButton(
-    views::ButtonListener* listener,
-    const gfx::ImageSkia& image_icon,
-    int title_resource_id,
-    const base::string16& secondary_text,
-    int click_target_id,
-    const base::string16& tooltip_text) {
-  auto icon = std::make_unique<NonAccessibleImageView>();
-  icon->SetImage(image_icon);
-  auto button = std::make_unique<HoverButton>(
-      listener, std::move(icon), base::string16(), base::string16());
-
-  if (secondary_text.empty()) {
-    button->SetTitleTextWithHintRange(
-        l10n_util::GetStringUTF16(title_resource_id),
-        gfx::Range::InvalidRange());
-  } else {
-    base::string16 title_text;
-    gfx::Range secondary_text_range =
-        GetRangeForFormatString(title_resource_id, secondary_text, &title_text);
-    button->SetTitleTextWithHintRange(title_text, secondary_text_range);
-  }
-
-  button->SetID(click_target_id);
-  button->SetTooltipText(tooltip_text);
-  return button;
-}
-
 std::unique_ptr<views::View> CreateSiteSettingsLink(
     const int side_margin,
     PageInfoBubbleView* listener) {
   const base::string16& tooltip =
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_TOOLTIP);
-  return CreateMoreInfoButton(
+  return std::make_unique<PageInfoHoverButton>(
       listener, PageInfoUI::GetSiteSettingsIcon(GetRelatedTextColor()),
       IDS_PAGE_INFO_SITE_SETTINGS_LINK, base::string16(),
       PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_SITE_SETTINGS,
-      tooltip);
+      tooltip, base::string16());
 }
 
 }  // namespace
@@ -258,15 +223,6 @@
                       views::GridLayout::FILL, views::GridLayout::LEADING);
 
   layout->StartRow(views::GridLayout::kFixedSize, label_column_status);
-  auto ev_certificate_label_container = std::make_unique<views::View>();
-  ev_certificate_label_container->SetLayoutManager(
-      std::make_unique<views::BoxLayout>(
-          views::BoxLayout::Orientation::kHorizontal));
-  ev_certificate_label_container_ =
-      layout->AddView(std::move(ev_certificate_label_container), 1.0, 1.0,
-                      views::GridLayout::FILL, views::GridLayout::LEADING);
-
-  layout->StartRow(views::GridLayout::kFixedSize, label_column_status);
   auto reset_decisions_label_container = std::make_unique<views::View>();
   reset_decisions_label_container->SetLayoutManager(
       std::make_unique<views::BoxLayout>(
@@ -302,32 +258,6 @@
   security_details_label_->AddStyleRange(details_range, link_style);
 }
 
-void BubbleHeaderView::AddEvCertificateDetailsLabel(
-    const PageInfoBubbleView::IdentityInfo& identity_info) {
-  DCHECK(identity_info.certificate);
-  DCHECK(ev_certificate_label_container_);
-  if (!ev_certificate_label_container_->children().empty()) {
-    // Ensure all old content is removed from the container before re-adding it.
-    ev_certificate_label_container_->RemoveAllChildViews(true);
-  }
-
-  auto ev_certificate_label = std::make_unique<views::Label>(
-      base::UTF8ToUTF16(identity_info.identity_status_description));
-  ev_certificate_label->SetID(
-      PageInfoBubbleView::VIEW_ID_PAGE_INFO_LABEL_EV_CERTIFICATE_DETAILS);
-  ev_certificate_label->SetMultiLine(true);
-  ev_certificate_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
-  ev_certificate_label->SizeToFit(0);  // Fit to occupy available width.
-  ev_certificate_label_container_->AddChildView(
-      std::move(ev_certificate_label));
-
-  // Now that it contains a label, the container needs padding at the top.
-  ev_certificate_label_container_->SetBorder(views::CreateEmptyBorder(
-      8, views::GridLayout::kFixedSize, views::GridLayout::kFixedSize, 0));
-
-  InvalidateLayout();
-}
-
 void BubbleHeaderView::AddResetDecisionsLabel() {
   if (!reset_decisions_label_container_->children().empty()) {
     // Ensure all old content is removed from the container before re-adding it.
@@ -696,18 +626,17 @@
         l10n_util::GetStringUTF16(IDS_PAGE_INFO_COOKIES_TOOLTIP);
 
     cookie_button_ =
-        CreateMoreInfoButton(
+        std::make_unique<PageInfoHoverButton>(
             this, icon, IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text,
-            VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_COOKIE_DIALOG, tooltip)
+            VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_COOKIE_DIALOG, tooltip,
+            base::string16())
             .release();
     site_settings_view_->AddChildView(cookie_button_);
   }
 
   // Update the text displaying the number of allowed cookies.
-  base::string16 button_text;
-  gfx::Range styled_range = GetRangeForFormatString(
-      IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text, &button_text);
-  cookie_button_->SetTitleTextWithHintRange(button_text, styled_range);
+  cookie_button_->SetTitleText(IDS_PAGE_INFO_COOKIES_BUTTON_TEXT,
+                               num_cookies_text);
 
   Layout();
   SizeToContents();
@@ -828,17 +757,6 @@
       header_->AddResetDecisionsLabel();
     }
 
-    if (base::FeatureList::IsEnabled(features::kEvDetailsInPageInfo)) {
-      // Only show the EV certificate details if there are no errors or mixed
-      // content.
-      if (identity_info.identity_status ==
-              PageInfo::SITE_IDENTITY_STATUS_EV_CERT &&
-          identity_info.connection_status ==
-              PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED) {
-        header_->AddEvCertificateDetailsLabel(identity_info);
-      }
-    }
-
     // Show information about the page's certificate.
     // The text of link to the Certificate Viewer varies depending on the
     // validity of the Certificate.
@@ -861,22 +779,33 @@
         valid_identity ? IDS_PAGE_INFO_CERTIFICATE_VALID_PARENTHESIZED
                        : IDS_PAGE_INFO_CERTIFICATE_INVALID_PARENTHESIZED);
 
+    base::string16 subtitle_text;
+    if (base::FeatureList::IsEnabled(features::kEvDetailsInPageInfo)) {
+      // Only show the EV certificate details if there are no errors or mixed
+      // content.
+      if (identity_info.identity_status ==
+              PageInfo::SITE_IDENTITY_STATUS_EV_CERT &&
+          identity_info.connection_status ==
+              PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED) {
+        subtitle_text =
+            base::UTF8ToUTF16(identity_info.identity_status_description);
+      }
+    }
+
     // If the certificate button has been added previously, remove the old one
     // before recreating it. Re-adding it bumps it to the bottom of the
     // container, but its unlikely that the user will notice, since other things
     // are changing too.
     if (certificate_button_) {
       site_settings_view_->RemoveChildView(certificate_button_);
-      auto to_delete = std::make_unique<HoverButton*>(certificate_button_);
+      auto to_delete = std::make_unique<views::View*>(certificate_button_);
     }
-
-    certificate_button_ =
-        CreateMoreInfoButton(
+    certificate_button_ = site_settings_view_->AddChildView(
+        std::make_unique<PageInfoHoverButton>(
             this, icon, IDS_PAGE_INFO_CERTIFICATE_BUTTON_TEXT, secondary_text,
-            VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_CERTIFICATE_VIEWER, tooltip)
-            .release();
-    certificate_button_->set_auto_compute_tooltip(false);
-    site_settings_view_->AddChildView(certificate_button_);
+            VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_CERTIFICATE_VIEWER, tooltip,
+            subtitle_text)
+            .release());
   }
 
   if (identity_info.show_change_password_buttons) {
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
index 1606724..1b90a9e3 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/views/hover_button.h"
 #include "chrome/browser/ui/views/page_info/chosen_object_view_observer.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view_base.h"
+#include "chrome/browser/ui/views/page_info/page_info_hover_button.h"
 #include "chrome/browser/ui/views/page_info/permission_selector_row.h"
 #include "chrome/browser/ui/views/page_info/permission_selector_row_observer.h"
 #include "components/security_state/core/security_state.h"
@@ -182,10 +183,10 @@
   views::View* site_settings_view_ = nullptr;
 
   // The button that opens the "Cookies" dialog.
-  HoverButton* cookie_button_ = nullptr;
+  PageInfoHoverButton* cookie_button_ = nullptr;
 
   // The button that opens the "Certificate" dialog.
-  HoverButton* certificate_button_ = nullptr;
+  PageInfoHoverButton* certificate_button_ = nullptr;
 
   // The view that contains the "Permissions" table of the bubble.
   views::View* permissions_view_ = nullptr;
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index 95e36086..e1bc75e 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -196,19 +196,16 @@
           net::GetTestCertsDirectory(), kGoodCertificateFile);
     } else if (name == kEvSecure) {
       // Generate a valid mock EV HTTPS identity, with an EV certificate. Must
-      // match conditions in PageInfoBubbleView::SetIdentityInfo() for calling
-      // AddEvCertificateDetailsLabel().
+      // match conditions in PageInfoBubbleView::SetIdentityInfo() for setting
+      // the certificate button subtitle.
       identity.identity_status = PageInfo::SITE_IDENTITY_STATUS_EV_CERT;
       identity.connection_status = PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED;
-      identity.identity_status_description =
-          "This page has been identified as being owned by Thawte Inc [US].";
+      identity.identity_status_description = "Issued to: Thawte Inc [US]";
       scoped_refptr<net::X509Certificate> ev_cert =
           net::X509Certificate::CreateFromBytes(
               reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
       ASSERT_TRUE(ev_cert);
       identity.certificate = ev_cert;
-      expected_identifiers_.push_back(
-          PageInfoBubbleView::VIEW_ID_PAGE_INFO_LABEL_EV_CERTIFICATE_DETAILS);
     } else if (name == kMalware) {
       identity.safe_browsing_status = PageInfo::SAFE_BROWSING_STATUS_MALWARE;
     } else if (name == kDeceptive) {
diff --git a/chrome/browser/ui/views/page_info/page_info_hover_button.cc b/chrome/browser/ui/views/page_info/page_info_hover_button.cc
new file mode 100644
index 0000000..21ae4b5b
--- /dev/null
+++ b/chrome/browser/ui/views/page_info/page_info_hover_button.cc
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/page_info/page_info_hover_button.h"
+
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/animation/ink_drop.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/styled_label.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/style/typography.h"
+
+namespace {
+
+std::unique_ptr<views::Border> CreateBorderWithVerticalSpacing(
+    int vert_spacing) {
+  const int horz_spacing = ChromeLayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_BUTTON_HORIZONTAL_PADDING);
+  return views::CreateEmptyBorder(vert_spacing, horz_spacing, vert_spacing,
+                                  horz_spacing);
+}
+
+}  // namespace
+
+PageInfoHoverButton::PageInfoHoverButton(views::ButtonListener* listener,
+                                         const gfx::ImageSkia& image_icon,
+                                         int title_resource_id,
+                                         const base::string16& secondary_text,
+                                         int click_target_id,
+                                         const base::string16& tooltip_text,
+                                         const base::string16& subtitle_text)
+    : HoverButton(listener, base::string16()) {
+  label()->SetHandlesTooltips(false);
+  auto icon = std::make_unique<NonAccessibleImageView>();
+  icon->SetImage(image_icon);
+
+  ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get();
+
+  views::GridLayout* grid_layout =
+      SetLayoutManager(std::make_unique<views::GridLayout>());
+  const int icon_label_spacing = layout_provider->GetDistanceMetric(
+      views::DISTANCE_RELATED_LABEL_HORIZONTAL);
+
+  constexpr int kColumnSetId = 0;
+  views::ColumnSet* columns = grid_layout->AddColumnSet(kColumnSetId);
+  columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
+                     views::GridLayout::kFixedSize, views::GridLayout::USE_PREF,
+                     0, 0);
+  columns->AddPaddingColumn(views::GridLayout::kFixedSize, icon_label_spacing);
+  columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1.0,
+                     views::GridLayout::USE_PREF, 0, 0);
+
+  // Make sure hovering over the icon also hovers the |PageInfoHoverButton|.
+  icon->set_can_process_events_within_subtree(false);
+  // Don't cover |icon_view| when the ink drops are being painted.
+  icon->SetPaintToLayer();
+  icon->layer()->SetFillsBoundsOpaquely(false);
+
+  // Force row to have sufficient height for full line-height of the title.
+  grid_layout->StartRow(
+      views::GridLayout::kFixedSize, kColumnSetId,
+      views::style::GetLineHeight(views::style::CONTEXT_LABEL,
+                                  views::style::STYLE_PRIMARY));
+
+  icon_view_ = grid_layout->AddView(std::move(icon));
+
+  auto title_label =
+      std::make_unique<views::StyledLabel>(base::string16(), nullptr);
+  title_label->SetTextContext(views::style::CONTEXT_LABEL);
+  // |views::StyledLabel|s are all multi-line. With a layout manager,
+  // |StyledLabel| will try use the available space to size itself, and long
+  // titles will wrap to the next line (for smaller |PageInfoHoverButton|s, this
+  // will also cover up |subtitle_|). Wrap it in a parent view with no layout
+  // manager to ensure it keeps its original size set by SizeToFit() above. Long
+  // titles will then be truncated.
+  auto title_wrapper = std::make_unique<views::View>();
+  title_ = title_wrapper->AddChildView(std::move(title_label));
+  SetTitleText(title_resource_id, secondary_text);
+
+  // Hover the whole button when hovering |title_|. This is OK because |title_|
+  // will never have a link in it.
+  title_wrapper->set_can_process_events_within_subtree(false);
+  grid_layout->AddView(std::move(title_wrapper));
+
+  if (!subtitle_text.empty()) {
+    grid_layout->StartRow(views::GridLayout::kFixedSize, kColumnSetId);
+    auto subtitle_label = std::make_unique<views::Label>(
+        subtitle_text, views::style::CONTEXT_LABEL, STYLE_SECONDARY);
+    subtitle_label->SetMultiLine(true);
+    subtitle_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    subtitle_label->SetAutoColorReadabilityEnabled(false);
+    grid_layout->SkipColumns(1);
+    subtitle_ = grid_layout->AddView(std::move(subtitle_label));
+  }
+
+  auto insets = layout_provider->GetInsetsMetric(
+      views::InsetsMetric::INSETS_LABEL_BUTTON);
+  const int vert_spacing = insets.height();
+  SetBorder(CreateBorderWithVerticalSpacing(vert_spacing));
+
+  SetID(click_target_id);
+  SetTooltipText(tooltip_text);
+  UpdateAccessibleName();
+
+  Layout();
+}
+
+void PageInfoHoverButton::SetTitleText(int title_resource_id,
+                                       const base::string16& secondary_text) {
+  DCHECK(title_);
+  if (secondary_text.empty()) {
+    title_->SetText(l10n_util::GetStringUTF16(title_resource_id));
+  } else {
+    size_t offset;
+    auto title_text =
+        l10n_util::GetStringFUTF16(title_resource_id, secondary_text, &offset);
+    title_->SetText(title_text);
+    views::StyledLabel::RangeStyleInfo style_info;
+    style_info.text_style = STYLE_SECONDARY;
+    title_->AddStyleRange(gfx::Range(offset, offset + secondary_text.length()),
+                          style_info);
+  }
+  title_->SizeToFit(0);
+  UpdateAccessibleName();
+}
+
+void PageInfoHoverButton::UpdateAccessibleName() {
+  const base::string16 accessible_name =
+      subtitle() == nullptr
+          ? title()->GetText()
+          : base::JoinString({title()->GetText(), subtitle()->GetText()},
+                             base::ASCIIToUTF16("\n"));
+  HoverButton::SetAccessibleName(accessible_name);
+}
+
+// The following methods of HoverButton are overridden to bypass the layout
+// logic implicit in the HoverButton class hierarchy.
+void PageInfoHoverButton::Layout() {
+  ink_drop_container()->SetBoundsRect(GetLocalBounds());
+  if (GetLayoutManager())
+    GetLayoutManager()->Layout(this);
+  Button::Layout();
+}
+
+gfx::Size PageInfoHoverButton::CalculatePreferredSize() const {
+  return Button::CalculatePreferredSize();
+}
+
+int PageInfoHoverButton::GetHeightForWidth(int w) const {
+  return Button::GetHeightForWidth(w);
+}
+
+void PageInfoHoverButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+  return Button::OnBoundsChanged(previous_bounds);
+}
+
+views::View* PageInfoHoverButton::GetTooltipHandlerForPoint(
+    const gfx::Point& point) {
+  return Button::GetTooltipHandlerForPoint(point);
+}
+
+BEGIN_METADATA(PageInfoHoverButton)
+METADATA_PARENT_CLASS(HoverButton)
+END_METADATA()
diff --git a/chrome/browser/ui/views/page_info/page_info_hover_button.h b/chrome/browser/ui/views/page_info/page_info_hover_button.h
new file mode 100644
index 0000000..03508824
--- /dev/null
+++ b/chrome/browser/ui/views/page_info/page_info_hover_button.h
@@ -0,0 +1,79 @@
+// 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_UI_VIEWS_PAGE_INFO_PAGE_INFO_HOVER_BUTTON_H_
+#define CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PAGE_INFO_HOVER_BUTTON_H_
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/views/hover_button.h"
+
+namespace gfx {
+class ImageSkia;
+}  // namespace gfx
+
+namespace views {
+class ButtonListener;
+class Label;
+class StyledLabel;
+class View;
+}  // namespace views
+
+class PageInfoBubbleViewBrowserTest;
+
+// Hoverable button containing icon, styled title, and (multi-line) subtitle.
+// PageInfoHoverButton inherits the interaction behavior from HoverButton but
+// sets up its own layout and content.
+class PageInfoHoverButton : public HoverButton {
+ public:
+  METADATA_HEADER(PageInfoHoverButton);
+
+  // Creates a hoverable button that formats the string given by
+  // |title_resource_id| with |secondary_text| and displays the latter part in
+  // the secondary text color. The |subtitle_text| is shown below the title text
+  // in secondary text color. |tooltip_text| is used for the tooltip shown on
+  // hovering over the button.
+  // *-----------------------------------------------------------------*
+  // | Icon | Title |title_resource_id| string + |secondary_text|      |
+  // |-----------------------------------------------------------------|
+  // |      | |subtitle_text|                                          |
+  // *-----------------------------------------------------------------*
+  PageInfoHoverButton(views::ButtonListener* listener,
+                      const gfx::ImageSkia& image_icon,
+                      int title_resource_id,
+                      const base::string16& secondary_text,
+                      int click_target_id,
+                      const base::string16& tooltip_text,
+                      const base::string16& subtitle_text);
+  ~PageInfoHoverButton() override {}
+
+  // Updates the title text, and applies the secondary style to the secondary
+  // text portion, if present.
+  void SetTitleText(int title_resource_id,
+                    const base::string16& secondary_text);
+
+ protected:
+  views::StyledLabel* title() const { return title_; }
+  views::Label* subtitle() const { return subtitle_; }
+  views::View* icon_view() const { return icon_view_; }
+  // HoverButton:
+  void Layout() override;
+  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+  views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
+  gfx::Size CalculatePreferredSize() const override;
+  int GetHeightForWidth(int w) const override;
+
+ private:
+  friend class PageInfoBubbleViewBrowserTest;
+
+  void UpdateAccessibleName();
+
+  views::StyledLabel* title_ = nullptr;
+  views::Label* subtitle_ = nullptr;
+  views::View* icon_view_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(PageInfoHoverButton);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PAGE_INFO_HOVER_BUTTON_H_
diff --git a/chrome/browser/vr/service/browser_xr_runtime.cc b/chrome/browser/vr/service/browser_xr_runtime.cc
index 3c680cb1..ec1dac3 100644
--- a/chrome/browser/vr/service/browser_xr_runtime.cc
+++ b/chrome/browser/vr/service/browser_xr_runtime.cc
@@ -333,13 +333,8 @@
     return;
   }
 
-  int render_process_id =
-      render_frame_host ? render_frame_host->GetProcess()->GetID() : -1;
-  int render_frame_id =
-      render_frame_host ? render_frame_host->GetRoutingID() : -1;
   pending_initialization_callbacks_.push_back(std::move(callback));
   runtime_->EnsureInitialized(
-      render_process_id, render_frame_id,
       base::BindOnce(&BrowserXRRuntime::OnInitialized, base::Unretained(this)));
 }
 
diff --git a/chrome/renderer/media/flash_embed_rewrite.cc b/chrome/renderer/media/flash_embed_rewrite.cc
index d990a0f3..b74b5d1e 100644
--- a/chrome/renderer/media/flash_embed_rewrite.cc
+++ b/chrome/renderer/media/flash_embed_rewrite.cc
@@ -7,18 +7,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "url/gurl.h"
 
-namespace {
-
-void RecordYouTubeRewriteUMA(FlashEmbedRewrite::YouTubeRewriteStatus status) {
-  UMA_HISTOGRAM_ENUMERATION(FlashEmbedRewrite::kFlashYouTubeRewriteUMA, status,
-                            FlashEmbedRewrite::YouTubeRewriteStatus::kLast);
-}
-
-}  // namespace
-
-const char FlashEmbedRewrite::kFlashYouTubeRewriteUMA[] =
-    "Plugin.Flash.YouTubeRewrite";
-
 GURL FlashEmbedRewrite::RewriteFlashEmbedURL(const GURL& url) {
   DCHECK(url.is_valid());
 
@@ -38,9 +26,8 @@
     return GURL();
 
   std::string url_str = url.spec();
-  YouTubeRewriteStatus result = YouTubeRewriteStatus::kLast;
 
-  // If the website is using an invalid YouTube URL, we'll try and
+  // If the website is using an invalid YouTube URL, we will try and
   // fix the URL by ensuring that if there are multiple parameters,
   // the parameter string begins with a "?" and then follows with a "&"
   // for each subsequent parameter. We do this because the Flash video player
@@ -50,10 +37,10 @@
   bool invalid_url = index != std::string::npos && url_str.at(index) == '&';
 
   if (invalid_url) {
-    // ? should appear first before all parameters
+    // ? should appear first before all parameters.
     url_str.replace(index, 1, "?");
 
-    // Replace all instances of ? (after the first) with &
+    // Replace all instances of ? (after the first) with &.
     for (size_t pos = index + 1;
          (pos = url_str.find("?", pos)) != std::string::npos; pos += 1) {
       url_str.replace(pos, 1, "&");
@@ -61,26 +48,14 @@
   }
 
   GURL corrected_url = GURL(url_str);
-  // Chrome used to only rewrite embeds with enablejsapi=1 on mobile for
-  // backward compatibility but with Flash embeds deprecated by YouTube, they
-  // are rewritten on all platforms. However, a different result is used in
-  // order to keep track of how popular they are.
-  if (corrected_url.query().find("enablejsapi=1") != std::string::npos)
-    result = YouTubeRewriteStatus::kSuccessEnableJSAPI;
 
-  // Change the path to use the YouTube HTML5 API
+  // Change the path to use the YouTube HTML5 API.
   std::string path = corrected_url.path();
   path.replace(path.find("/v/"), 3, "/embed/");
 
   url::Replacements<char> r;
   r.SetPath(path.c_str(), url::Component(0, path.length()));
 
-  if (result == YouTubeRewriteStatus::kLast) {
-    result = invalid_url ? YouTubeRewriteStatus::kSuccessParamsRewrite
-                         : YouTubeRewriteStatus::kSuccess;
-  }
-
-  RecordYouTubeRewriteUMA(result);
   return corrected_url.ReplaceComponents(r);
 }
 
diff --git a/chrome/renderer/media/flash_embed_rewrite.h b/chrome/renderer/media/flash_embed_rewrite.h
index f01f7a6..35b1f00 100644
--- a/chrome/renderer/media/flash_embed_rewrite.h
+++ b/chrome/renderer/media/flash_embed_rewrite.h
@@ -12,22 +12,6 @@
   // Entry point that will then call a private website-specific method.
   static GURL RewriteFlashEmbedURL(const GURL&);
 
-  // Used for UMA. Values should not be reorderer or reused.
-  // SUCCESS refers to an embed properly rewritten. SUCCESS_PARAMS_REWRITE
-  // refers to an embed rewritten with the params fixed. SUCCESS_ENABLEJSAPI
-  // refers to a rewritten embed even though the JS API was enabled (Chrome
-  // Android only). FAILURE_ENABLEJSAPI indicates the embed was not rewritten
-  // because the JS API was enabled.
-  enum class YouTubeRewriteStatus {
-    kSuccess = 0,
-    kSuccessParamsRewrite = 1,
-    kSuccessEnableJSAPI = 2,
-    kFailureEnableJSAPI = 3,
-    kLast = kFailureEnableJSAPI,
-  };
-
-  static const char kFlashYouTubeRewriteUMA[];
-
  private:
   // YouTube specific method.
   static GURL RewriteYouTubeFlashEmbedURL(const GURL&);
diff --git a/chrome/renderer/media/flash_embed_rewrite_unittest.cc b/chrome/renderer/media/flash_embed_rewrite_unittest.cc
index 72480be..48ef65a 100644
--- a/chrome/renderer/media/flash_embed_rewrite_unittest.cc
+++ b/chrome/renderer/media/flash_embed_rewrite_unittest.cc
@@ -4,29 +4,10 @@
 
 #include "chrome/renderer/media/flash_embed_rewrite.h"
 
-#include "base/metrics/histogram_samples.h"
-#include "base/test/metrics/histogram_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using YouTubeRewriteStatus = FlashEmbedRewrite::YouTubeRewriteStatus;
-
-class FlashEmbedRewriteTest : public testing::Test {
- public:
-  FlashEmbedRewriteTest() = default;
-
-  std::unique_ptr<base::HistogramSamples> GetHistogramSamples() {
-    return histogram_tester_.GetHistogramSamplesSinceCreation(
-        FlashEmbedRewrite::kFlashYouTubeRewriteUMA);
-  }
-
- private:
-  base::HistogramTester histogram_tester_;
-
-  DISALLOW_COPY_AND_ASSIGN(FlashEmbedRewriteTest);
-};
-
-TEST_F(FlashEmbedRewriteTest, YouTubeRewriteEmbed) {
+TEST(FlashEmbedRewriteTest, YouTubeRewriteEmbed) {
   struct TestData {
     std::string original;
     std::string expected;
@@ -108,9 +89,15 @@
       // youtube-nocookie.com, has JS API enabled
       {"http://www.youtube-nocookie.com/v/123?enablejsapi=1",
        "http://www.youtube-nocookie.com/embed/123?enablejsapi=1"},
+      // ... with multiple parameters.
+      {"http://www.youtube.com/v/deadbeef?enablejsapi=1&foo=2",
+       "http://www.youtube.com/embed/deadbeef?enablejsapi=1&foo=2"},
       // URL is using Flash, has JS API enabled, invalid parameter construct
       {"http://www.youtube.com/v/deadbeef&enablejsapi=1",
        "http://www.youtube.com/embed/deadbeef?enablejsapi=1"},
+      // ... with multiple parameters.
+      {"http://www.youtube.com/v/deadbeef&enablejsapi=1&foo=2",
+       "http://www.youtube.com/embed/deadbeef?enablejsapi=1&foo=2"},
       // URL is using Flash, has JS API enabled, invalid parameter construct,
       // has multiple parameters
       {"http://www.youtube.com/v/deadbeef&start=4&enablejsapi=1",
@@ -123,125 +110,7 @@
   }
 }
 
-TEST_F(FlashEmbedRewriteTest, YouTubeRewriteEmbedIneligibleURL) {
-  std::unique_ptr<base::HistogramSamples> samples = GetHistogramSamples();
-  EXPECT_EQ(0, samples->TotalCount());
-
-  const std::string test_data[] = {
-      // HTTP, www, no flash
-      "http://www.youtube.com",
-      // No flash, subdomain
-      "http://www.foo.youtube.com",
-      // Not youtube
-      "http://www.plus.google.com",
-      // Already using HTML5
-      "http://youtube.com/embed/deadbeef",
-      // Already using HTML5, enablejsapi=1
-      "http://www.youtube.com/embed/deadbeef?enablejsapi=1"};
-
-  for (const auto& data : test_data) {
-    FlashEmbedRewrite::RewriteFlashEmbedURL(GURL(data));
-    samples = GetHistogramSamples();
-    EXPECT_EQ(0, samples->GetCount((int)YouTubeRewriteStatus::kSuccess));
-    EXPECT_EQ(0, samples->TotalCount());
-  }
-}
-
-TEST_F(FlashEmbedRewriteTest, YouTubeRewriteEmbedSuccess) {
-  std::unique_ptr<base::HistogramSamples> samples = GetHistogramSamples();
-  auto total_count = 0;
-  EXPECT_EQ(total_count, samples->TotalCount());
-
-  const std::string test_data[] = {
-      // HTTP, www, flash
-      "http://www.youtube.com/v/deadbeef",
-      // HTTP, no www, flash
-      "http://youtube.com/v/deadbeef",
-      // HTTPS, www, flash
-      "https://www.youtube.com/v/deadbeef",
-      // HTTPS, no www, flash
-      "https://youtube.com/v/deadbeef",
-      // Invalid parameter construct
-      "http://www.youtube.com/v/abcd/",
-      // Invalid parameter construct
-      "http://www.youtube.com/v/1234/",
-  };
-
-  for (const auto& data : test_data) {
-    ++total_count;
-    FlashEmbedRewrite::RewriteFlashEmbedURL(GURL(data));
-    samples = GetHistogramSamples();
-    EXPECT_EQ(total_count,
-              samples->GetCount((int)YouTubeRewriteStatus::kSuccess));
-    EXPECT_EQ(total_count, samples->TotalCount());
-  }
-
-  // Invalid parameter construct
-  FlashEmbedRewrite::RewriteFlashEmbedURL(
-      GURL("http://www.youtube.com/abcd/v/deadbeef"));
-  samples = GetHistogramSamples();
-  EXPECT_EQ(total_count,
-            samples->GetCount((int)YouTubeRewriteStatus::kSuccess));
-  EXPECT_EQ(total_count, samples->TotalCount());
-}
-
-TEST_F(FlashEmbedRewriteTest, YouTubeRewriteEmbedSuccessRewrite) {
-  std::unique_ptr<base::HistogramSamples> samples = GetHistogramSamples();
-  auto total_count = 0;
-  EXPECT_EQ(total_count, samples->TotalCount());
-
-  const std::string test_data[] = {
-      // Invalid parameter construct, one parameter
-      "http://www.youtube.com/v/deadbeef&start=4",
-      // Invalid parameter construct, has multiple parameters
-      "http://www.youtube.com/v/deadbeef&start=4&fs=1?foo=bar",
-  };
-
-  for (const auto& data : test_data) {
-    ++total_count;
-    FlashEmbedRewrite::RewriteFlashEmbedURL(GURL(data));
-    samples = GetHistogramSamples();
-    EXPECT_EQ(
-        total_count,
-        samples->GetCount((int)YouTubeRewriteStatus::kSuccessParamsRewrite));
-    EXPECT_EQ(total_count, samples->TotalCount());
-  }
-
-  // Invalid parameter construct, not flash
-  FlashEmbedRewrite::RewriteFlashEmbedURL(
-      GURL("http://www.youtube.com/embed/deadbeef&start=4"));
-  samples = GetHistogramSamples();
-  EXPECT_EQ(total_count, samples->GetCount(
-                             (int)YouTubeRewriteStatus::kSuccessParamsRewrite));
-  EXPECT_EQ(total_count, samples->TotalCount());
-}
-
-TEST_F(FlashEmbedRewriteTest, YouTubeRewriteEmbedJSAPI) {
-  std::unique_ptr<base::HistogramSamples> samples = GetHistogramSamples();
-  auto total_count = 0;
-  EXPECT_EQ(total_count, samples->TotalCount());
-
-  const std::string test_data[] = {
-      // Valid parameter construct, one parameter
-      "http://www.youtube.com/v/deadbeef?enablejsapi=1",
-      // Valid parameter construct, has multiple parameters
-      "http://www.youtube.com/v/deadbeef?enablejsapi=1&foo=2",
-      // Invalid parameter construct, one parameter
-      "http://www.youtube.com/v/deadbeef&enablejsapi=1",
-      // Invalid parameter construct, has multiple parameters
-      "http://www.youtube.com/v/deadbeef&enablejsapi=1&foo=2"};
-
-  for (const auto& data : test_data) {
-    ++total_count;
-    FlashEmbedRewrite::RewriteFlashEmbedURL(GURL(data));
-    samples = GetHistogramSamples();
-    EXPECT_EQ(total_count, samples->GetCount(
-                               (int)YouTubeRewriteStatus::kSuccessEnableJSAPI));
-    EXPECT_EQ(total_count, samples->TotalCount());
-  }
-}
-
-TEST_F(FlashEmbedRewriteTest, DailymotionRewriteEmbed) {
+TEST(FlashEmbedRewriteTest, DailymotionRewriteEmbed) {
   struct TestData {
     std::string original;
     std::string expected;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 5ebe0cb..4abb3429 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1936,6 +1936,7 @@
         "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.cc",
         "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.h",
         "../browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_apitest.cc",
+        "../browser/chromeos/extensions/login_screen/storage_apitest.cc",
         "../browser/chromeos/extensions/users_private/users_private_apitest.cc",
         "../browser/chromeos/extensions/wallpaper_apitest.cc",
         "../browser/chromeos/extensions/wallpaper_manager_browsertest.cc",
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/extension.crx b/chrome/test/data/extensions/api_test/login_screen_apis/extension.crx
index b053f15..4ecf4eb 100644
--- a/chrome/test/data/extensions/api_test/login_screen_apis/extension.crx
+++ b/chrome/test/data/extensions/api_test/login_screen_apis/extension.crx
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/extension/background.js b/chrome/test/data/extensions/api_test/login_screen_apis/extension/background.js
index 09e6dd14..c2ed4f1 100644
--- a/chrome/test/data/extensions/api_test/login_screen_apis/extension/background.js
+++ b/chrome/test/data/extensions/api_test/login_screen_apis/extension/background.js
@@ -5,6 +5,10 @@
 const cannotCreateMultipleWindowsErrorMessage =
     'Can\'t create more than one window per extension.';
 const cannotCloseNoWindowErrorMessage = 'No open window to close.';
+const cannotAccessLocalStorageErrorMessage =
+    '"local" is not available for login screen extensions';
+const cannotAccessSyncStorageErrorMessage =
+    '"sync" is not available for login screen extensions';
 
 const tests = {
   /* LoginScreenUi ************************************************************/
@@ -38,6 +42,32 @@
       chrome.test.succeed();
     });
   },
+
+  /* Storage ******************************************************************/
+  'StorageCannotAccessLocalStorage': () => {
+    chrome.storage.local.get(() => {
+      chrome.test.assertLastError(cannotAccessLocalStorageErrorMessage);
+      chrome.storage.local.set({foo: 'bar'}, () => {
+        chrome.test.assertLastError(cannotAccessLocalStorageErrorMessage);
+        chrome.test.succeed();
+      });
+    });
+  },
+  'StorageCannotAccessSyncStorage': () => {
+    chrome.storage.sync.get(() => {
+      chrome.test.assertLastError(cannotAccessSyncStorageErrorMessage);
+      chrome.storage.sync.set({foo: 'bar'}, () => {
+        chrome.test.assertLastError(cannotAccessSyncStorageErrorMessage);
+        chrome.test.succeed();
+      });
+    });
+  },
+  'StorageCanAccessManagedStorage': () => {
+    chrome.storage.managed.get(() => {
+      chrome.test.assertNoLastError();
+      chrome.test.succeed();
+    });
+  },
 };
 
 // |waitForTestName()| waits for the browser test to reply with a test name and
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/extension/manifest.json b/chrome/test/data/extensions/api_test/login_screen_apis/extension/manifest.json
index 8d871f2..27856e5 100644
--- a/chrome/test/data/extensions/api_test/login_screen_apis/extension/manifest.json
+++ b/chrome/test/data/extensions/api_test/login_screen_apis/extension/manifest.json
@@ -1,6 +1,6 @@
 {
   "name": "Login screen APIs test extension",
-  "version": "1.16",
+  "version": "1.17",
   "manifest_version": 2,
   "description": "Login screen APIs test extension",
   "background": {
@@ -8,6 +8,7 @@
     "persistent": false
   },
   "permissions": [
-    "loginScreenUi"
+    "loginScreenUi",
+    "storage"
   ]
 }
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/update_manifest.xml b/chrome/test/data/extensions/api_test/login_screen_apis/update_manifest.xml
index 3730713..37aea5d8 100644
--- a/chrome/test/data/extensions/api_test/login_screen_apis/update_manifest.xml
+++ b/chrome/test/data/extensions/api_test/login_screen_apis/update_manifest.xml
@@ -7,6 +7,6 @@
   <app appid='oclffehlkdgibkainkilopaalpdobkan'>
     <updatecheck
         codebase='http://mock.http/extensions/api_test/login_screen_apis/extension.crx'
-        version='1.10' />
+        version='1.17' />
    </app>
 </gupdate>
diff --git a/chromeos/components/drivefs/BUILD.gn b/chromeos/components/drivefs/BUILD.gn
index 72bf524..1410789 100644
--- a/chromeos/components/drivefs/BUILD.gn
+++ b/chromeos/components/drivefs/BUILD.gn
@@ -17,6 +17,7 @@
     "drivefs_search.h",
     "drivefs_session.cc",
     "drivefs_session.h",
+    "drivefs_util.h",
     "fake_drivefs_launcher_client.cc",
     "fake_drivefs_launcher_client.h",
     "pending_connection_manager.cc",
diff --git a/chromeos/components/drivefs/drivefs_util.h b/chromeos/components/drivefs/drivefs_util.h
new file mode 100644
index 0000000..706eed1d
--- /dev/null
+++ b/chromeos/components/drivefs/drivefs_util.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_UTIL_H_
+#define CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_UTIL_H_
+
+#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
+
+namespace drivefs {
+
+// The type represents some sort of a file.
+inline bool IsAFile(mojom::FileMetadata::Type type) {
+  return type == mojom::FileMetadata::Type::kHosted ||
+         type == mojom::FileMetadata::Type::kFile;
+}
+
+// The type represents some sort of a directory.
+inline bool IsADirectory(mojom::FileMetadata::Type type) {
+  return type == mojom::FileMetadata::Type::kDirectory;
+}
+
+// The type represents a virtual cloud-hosted object.
+inline bool IsHosted(mojom::FileMetadata::Type type) {
+  return type == mojom::FileMetadata::Type::kHosted;
+}
+
+// The type represents a real local object.
+inline bool IsLocal(mojom::FileMetadata::Type type) {
+  return type != mojom::FileMetadata::Type::kHosted;
+}
+
+}  // namespace drivefs
+
+#endif  // CHROMEOS_COMPONENTS_DRIVEFS_DRIVEFS_UTIL_H_
diff --git a/chromeos/components/drivefs/fake_drivefs.cc b/chromeos/components/drivefs/fake_drivefs.cc
index d08cc14..e94cd0e 100644
--- a/chromeos/components/drivefs/fake_drivefs.cc
+++ b/chromeos/components/drivefs/fake_drivefs.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_restrictions.h"
+#include "chromeos/components/drivefs/drivefs_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_cros_disks_client.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -170,8 +171,7 @@
                  std::string::npos;
         }
         if (params_->available_offline) {
-          return !metadata->available_offline &&
-                 metadata->type != mojom::FileMetadata::Type::kHosted;
+          return !metadata->available_offline && IsLocal(metadata->type);
         }
         if (params_->shared_with_me) {
           return !metadata->shared;
diff --git a/chromeos/components/drivefs/mojom/drivefs.mojom b/chromeos/components/drivefs/mojom/drivefs.mojom
index 9477e535..ff32213 100644
--- a/chromeos/components/drivefs/mojom/drivefs.mojom
+++ b/chromeos/components/drivefs/mojom/drivefs.mojom
@@ -169,7 +169,7 @@
 
 // Next MinVersion: 2
 struct FileMetadata {
-  enum Type {
+  [Extensible] enum Type {
     // A regular file.
     kFile,
 
diff --git a/components/nacl/features.gni b/components/nacl/features.gni
index 1a09aaf..2b78c66 100644
--- a/components/nacl/features.gni
+++ b/components/nacl/features.gni
@@ -12,7 +12,7 @@
   enable_nacl =
       checkout_nacl && !is_ios && !is_android && !is_fuchsia &&
       !is_chromecast && current_cpu != "mipsel" && current_cpu != "mips64el" &&
-      !(is_linux && target_cpu == "arm64") && !(is_win && host_os != "win")
+      target_cpu != "arm64" && !(is_win && host_os != "win")
 
   # Non-SFI is not yet supported on mipsel
   enable_nacl_nonsfi = current_cpu != "mipsel" && current_cpu != "mips64el"
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index e2495f48..8244923 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -151,7 +151,7 @@
       <ph name="CITY">$1<ex>Mountain View</ex></ph>, <ph name="COUNTRY">$2<ex>US</ex></ph>
     </message>
     <message name="IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_VERIFIED" desc="The text of the identity section when the page is secured with a valid EV cert.">
-      This page has been identified as being owned by <ph name="ORGANIZATION">$1<ex>Google LLC</ex></ph> [<ph name="JURISDICTION">$2<ex>US</ex></ph>].
+      Issued to: <ph name="ORGANIZATION">$1<ex>Google LLC</ex></ph> [<ph name="JURISDICTION">$2<ex>US</ex></ph>]
     </message>
 
     <!-- Certificate Viewer link -->
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc
index 0ef33501..e9cd4ce 100644
--- a/components/sync/driver/sync_driver_switches.cc
+++ b/components/sync/driver/sync_driver_switches.cc
@@ -73,7 +73,7 @@
 
 // Enable USS implementation of autofill wallet metadata datatype.
 const base::Feature kSyncUSSAutofillWalletMetadata{
-    "SyncUSSAutofillWalletMetadata", base::FEATURE_DISABLED_BY_DEFAULT};
+    "SyncUSSAutofillWalletMetadata", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable USS implementation of Nigori datatype.
 const base::Feature kSyncUSSNigori{"SyncUSSNigori",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 9095d1a..07c852fd 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -5,7 +5,6 @@
 #include "components/viz/common/features.h"
 
 #include "base/command_line.h"
-#include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
 #include "components/viz/common/switches.h"
 
@@ -15,10 +14,6 @@
 
 namespace features {
 
-constexpr char kProvider[] = "provider";
-constexpr char kDrawQuad[] = "draw_quad";
-constexpr char kSurfaceLayer[] = "surface_layer";
-
 const base::Feature kEnableSurfaceSynchronization{
     "SurfaceSynchronization", base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -35,17 +30,9 @@
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
-// Enables running the Viz-assisted hit-test logic. We still need to keep the
-// VizHitTestDrawQuad and VizHitTestSurfaceLayer features for finch launch.
-const base::Feature kEnableVizHitTestDrawQuad{"VizHitTestDrawQuad",
-                                              base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kEnableVizHitTestSurfaceLayer{
     "VizHitTestSurfaceLayer", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kEnableVizHitTest{"VizHitTest",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Use Skia's readback API instead of GLRendererCopier.
 const base::Feature kUseSkiaForGLReadback{"UseSkiaForGLReadback",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
@@ -83,37 +70,19 @@
 }
 
 bool IsVizHitTestingDebugEnabled() {
-  return features::IsVizHitTestingEnabled() &&
-         base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kEnableVizHitTestDebug);
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableVizHitTestDebug);
 }
 
-// VizHitTest is considered enabled when any of its variant is turned on, or
-// when VizDisplayCompositor is turned on.
-bool IsVizHitTestingEnabled() {
-  return base::FeatureList::IsEnabled(features::kEnableVizHitTest) ||
-         base::FeatureList::IsEnabled(kVizDisplayCompositor);
-}
-
-// VizHitTestDrawQuad is enabled when this feature is explicitly enabled on
-// chrome://flags, or when VizHitTest is enabled but VizHitTestSurfaceLayer is
-// turned off.
 bool IsVizHitTestingDrawQuadEnabled() {
-  return GetFieldTrialParamValueByFeature(features::kEnableVizHitTest,
-                                          kProvider) == kDrawQuad ||
-         (IsVizHitTestingEnabled() && !IsVizHitTestingSurfaceLayerEnabled());
+  return !IsVizHitTestingSurfaceLayerEnabled();
 }
 
 // VizHitTestSurfaceLayer is enabled when this feature is explicitly enabled on
 // chrome://flags, or when it is enabled by finch and chrome://flags does not
 // conflict.
 bool IsVizHitTestingSurfaceLayerEnabled() {
-  return GetFieldTrialParamValueByFeature(features::kEnableVizHitTest,
-                                          kProvider) == kSurfaceLayer ||
-         (IsVizHitTestingEnabled() &&
-          GetFieldTrialParamValueByFeature(features::kEnableVizHitTest,
-                                           kProvider) != kDrawQuad &&
-          base::FeatureList::IsEnabled(kEnableVizHitTestSurfaceLayer));
+  return base::FeatureList::IsEnabled(kEnableVizHitTestSurfaceLayer);
 }
 
 bool IsUsingSkiaForGLReadback() {
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index e575fcf..c232bf45 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -12,8 +12,6 @@
 namespace features {
 
 VIZ_COMMON_EXPORT extern const base::Feature kEnableSurfaceSynchronization;
-VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTest;
-VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestDrawQuad;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestSurfaceLayer;
 VIZ_COMMON_EXPORT extern const base::Feature kUseSkiaForGLReadback;
 VIZ_COMMON_EXPORT extern const base::Feature kUseSkiaRenderer;
@@ -25,7 +23,6 @@
 VIZ_COMMON_EXPORT bool IsVizDisplayCompositorEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDrawQuadEnabled();
-VIZ_COMMON_EXPORT bool IsVizHitTestingEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingSurfaceLayerEnabled();
 VIZ_COMMON_EXPORT bool IsUsingSkiaForGLReadback();
 VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer();
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 27e957e9..f1754d4 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -169,9 +169,6 @@
     "surfaces/surface_client.h",
     "surfaces/surface_dependency_deadline.cc",
     "surfaces/surface_dependency_deadline.h",
-    "surfaces/surface_hittest.cc",
-    "surfaces/surface_hittest.h",
-    "surfaces/surface_hittest_delegate.h",
     "surfaces/surface_manager.cc",
     "surfaces/surface_manager.h",
     "surfaces/surface_manager_delegate.h",
@@ -417,7 +414,6 @@
     "gl/gpu_service_impl_unittest.cc",
     "hit_test/hit_test_aggregator_unittest.cc",
     "surfaces/referenced_surface_tracker_unittest.cc",
-    "surfaces/surface_hittest_unittest.cc",
     "surfaces/surface_unittest.cc",
   ]
 
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
index 1a42f8b..343e490b 100644
--- a/components/viz/service/display/output_surface.h
+++ b/components/viz/service/display/output_surface.h
@@ -57,6 +57,12 @@
     bool supports_post_sub_buffer = false;
     // Whether this OutputSurface supports gpu vsync callbacks.
     bool supports_gpu_vsync = false;
+    // Whether this OutputSurface supports pre transform. If it is supported,
+    // the chrome will set the output surface size in hardware natural
+    // orientation, and will render transformed content on back buffers based
+    // on the current system transform. So the OS presentation engine can
+    // present buffers onto the screen directly.
+    bool supports_pre_transform = false;
   };
 
   // Constructor for skia-based compositing.
diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc
index abc5488..a7915a85 100644
--- a/components/viz/service/display_embedder/output_surface_provider_impl.cc
+++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc
@@ -111,10 +111,8 @@
     return nullptr;
 #else
     if (renderer_settings.use_skia_renderer_non_ddl) {
-      bool is_gles2 =
-          (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) ||
-          (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE);
-      DCHECK(is_gles2) << "SkiaRendererNonDDL is only supported with GLES2.";
+      DCHECK_EQ(gl::GetGLImplementation(), gl::kGLImplementationEGLGLES2)
+          << "SkiaRendererNonDDL is only supported with GLES2.";
       auto gl_surface = gpu::ImageTransportSurface::CreateNativeSurface(
           nullptr, surface_handle, gl::GLSurfaceFormat());
       if (!shared_context_state_) {
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h
index 75c91d9..c8bcc7b 100644
--- a/components/viz/service/display_embedder/skia_output_device.h
+++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -64,7 +64,8 @@
   virtual void Reshape(const gfx::Size& size,
                        float device_scale_factor,
                        const gfx::ColorSpace& color_space,
-                       bool has_alpha) = 0;
+                       bool has_alpha,
+                       gfx::OverlayTransform transform) = 0;
 
   // Presents the back buffer.
   virtual gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) = 0;
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc
index d31721a8..9d98c3d 100644
--- a/components/viz/service/display_embedder/skia_output_device_gl.cc
+++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -74,7 +74,10 @@
 void SkiaOutputDeviceGL::Reshape(const gfx::Size& size,
                                  float device_scale_factor,
                                  const gfx::ColorSpace& color_space,
-                                 bool has_alpha) {
+                                 bool has_alpha,
+                                 gfx::OverlayTransform transform) {
+  DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
+
   gl::GLSurface::ColorSpace surface_color_space =
       gl::ColorSpaceUtils::GetGLSurfaceColorSpace(color_space);
   if (!gl_surface_->Resize(size, device_scale_factor, surface_color_space,
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.h b/components/viz/service/display_embedder/skia_output_device_gl.h
index e640e36..0972939 100644
--- a/components/viz/service/display_embedder/skia_output_device_gl.h
+++ b/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -52,7 +52,8 @@
   void Reshape(const gfx::Size& size,
                float device_scale_factor,
                const gfx::ColorSpace& color_space,
-               bool has_alpha) override;
+               bool has_alpha,
+               gfx::OverlayTransform transform) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
   gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                   BufferPresentedCallback feedback) override;
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
index 8cd89133..1717dfa3 100644
--- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc
+++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -28,7 +28,10 @@
 void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
                                         float device_scale_factor,
                                         const gfx::ColorSpace& color_space,
-                                        bool has_alpha) {
+                                        bool has_alpha,
+                                        gfx::OverlayTransform transform) {
+  DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
+
   // Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
   // kRGBA_8888_SkColorType instead and initialize surface to opaque alpha.
   image_info_ =
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h
index bebd366..4de6b8c 100644
--- a/components/viz/service/display_embedder/skia_output_device_offscreen.h
+++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -26,7 +26,8 @@
   void Reshape(const gfx::Size& size,
                float device_scale_factor,
                const gfx::ColorSpace& color_space,
-               bool has_alpha) override;
+               bool has_alpha,
+               gfx::OverlayTransform transform) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
   gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                   BufferPresentedCallback feedback) override;
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
index c9f1f1f..8c2b2ad 100644
--- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc
+++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -29,6 +29,7 @@
       surface_handle_(surface_handle) {
   capabilities_.flipped_output_surface = true;
   capabilities_.supports_post_sub_buffer = false;
+  capabilities_.supports_pre_transform = true;
 }
 
 SkiaOutputDeviceVulkan::~SkiaOutputDeviceVulkan() {
@@ -43,7 +44,8 @@
 void SkiaOutputDeviceVulkan::Reshape(const gfx::Size& size,
                                      float device_scale_factor,
                                      const gfx::ColorSpace& color_space,
-                                     bool has_alpha) {
+                                     bool has_alpha,
+                                     gfx::OverlayTransform transform) {
   DCHECK(!scoped_write_);
 
   uint32_t generation = 0;
@@ -53,12 +55,12 @@
     generation = vulkan_surface_->swap_chain_generation();
   }
 
-  vulkan_surface_->SetSize(size);
+  vulkan_surface_->Reshape(size, transform);
 
   if (vulkan_surface_->swap_chain_generation() != generation) {
     // swapchain is changed, we need recreate all cached sk surfaces.
     sk_surfaces_.clear();
-    sk_surfaces_.resize(vulkan_surface_->GetSwapChain()->num_images());
+    sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images());
   }
 }
 
@@ -69,8 +71,8 @@
   DCHECK(!scoped_write_);
 
   StartSwapBuffers(std::move(feedback));
-  auto size = vulkan_surface_->size();
-  auto response = FinishSwapBuffers(vulkan_surface_->SwapBuffers(), size);
+  auto image_size = vulkan_surface_->image_size();
+  auto response = FinishSwapBuffers(vulkan_surface_->SwapBuffers(), image_size);
   return response;
 }
 
@@ -78,7 +80,7 @@
   DCHECK(vulkan_surface_);
   DCHECK(!scoped_write_);
 
-  scoped_write_.emplace(vulkan_surface_->GetSwapChain());
+  scoped_write_.emplace(vulkan_surface_->swap_chain());
   if (!scoped_write_->success()) {
     scoped_write_.reset();
     return nullptr;
@@ -94,8 +96,9 @@
     GrVkImageInfo vk_image_info(
         scoped_write_->image(), GrVkAlloc(), VK_IMAGE_TILING_OPTIMAL,
         scoped_write_->image_layout(), surface_format, 1 /* level_count */);
-    GrBackendRenderTarget render_target(vulkan_surface_->size().width(),
-                                        vulkan_surface_->size().height(),
+    const auto& vk_image_size = vulkan_surface_->image_size();
+    GrBackendRenderTarget render_target(vk_image_size.width(),
+                                        vk_image_size.height(),
                                         0 /* sample_cnt */, vk_image_info);
     auto sk_color_type = surface_format == VK_FORMAT_B8G8R8A8_UNORM
                              ? kBGRA_8888_SkColorType
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.h b/components/viz/service/display_embedder/skia_output_device_vulkan.h
index 1c45ecb..f30bec9a 100644
--- a/components/viz/service/display_embedder/skia_output_device_vulkan.h
+++ b/components/viz/service/display_embedder/skia_output_device_vulkan.h
@@ -34,7 +34,8 @@
   void Reshape(const gfx::Size& size,
                float device_scale_factor,
                const gfx::ColorSpace& color_space,
-               bool has_alpha) override;
+               bool has_alpha,
+               gfx::OverlayTransform transform) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
   SkSurface* BeginPaint() override;
   void EndPaint(const GrBackendSemaphore& semaphore) override;
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.cc b/components/viz/service/display_embedder/skia_output_device_x11.cc
index 777348d1..b003ce8 100644
--- a/components/viz/service/display_embedder/skia_output_device_x11.cc
+++ b/components/viz/service/display_embedder/skia_output_device_x11.cc
@@ -44,9 +44,10 @@
 void SkiaOutputDeviceX11::Reshape(const gfx::Size& size,
                                   float device_scale_factor,
                                   const gfx::ColorSpace& color_space,
-                                  bool has_alpha) {
+                                  bool has_alpha,
+                                  gfx::OverlayTransform transform) {
   SkiaOutputDeviceOffscreen::Reshape(size, device_scale_factor, color_space,
-                                     has_alpha);
+                                     has_alpha, transform);
   auto ii =
       SkImageInfo::MakeN32(size.width(), size.height(), kOpaque_SkAlphaType);
   pixels_.reserve(ii.computeMinByteSize());
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.h b/components/viz/service/display_embedder/skia_output_device_x11.h
index a82d72e7..f1b3b40 100644
--- a/components/viz/service/display_embedder/skia_output_device_x11.h
+++ b/components/viz/service/display_embedder/skia_output_device_x11.h
@@ -26,7 +26,8 @@
   void Reshape(const gfx::Size& size,
                float device_scale_factor,
                const gfx::ColorSpace& color_space,
-               bool has_alpha) override;
+               bool has_alpha,
+               gfx::OverlayTransform transform) override;
   gfx::SwapResponse SwapBuffers(BufferPresentedCallback feedback) override;
   gfx::SwapResponse PostSubBuffer(const gfx::Rect& rect,
                                   BufferPresentedCallback feedback) override;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 6d373c6..eed9264 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -173,11 +173,11 @@
 
   // impl_on_gpu_ is released on the GPU thread by a posted task from
   // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
-  auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::Reshape,
-                                 base::Unretained(impl_on_gpu_.get()), size,
-                                 device_scale_factor, std::move(color_space),
-                                 has_alpha, use_stencil, characterization,
-                                 initialize_waitable_event_.get());
+  auto callback = base::BindOnce(
+      &SkiaOutputSurfaceImplOnGpu::Reshape,
+      base::Unretained(impl_on_gpu_.get()), size, device_scale_factor,
+      std::move(color_space), has_alpha, use_stencil, pre_transform_,
+      characterization, initialize_waitable_event_.get());
   ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>());
 }
 
@@ -186,6 +186,16 @@
   update_vsync_parameters_callback_ = std::move(callback);
 }
 
+void SkiaOutputSurfaceImpl::SetDisplayTransformHint(
+    gfx::OverlayTransform transform) {
+  if (capabilities_.supports_pre_transform)
+    pre_transform_ = transform;
+}
+
+gfx::OverlayTransform SkiaOutputSurfaceImpl::GetDisplayTransform() {
+  return pre_transform_;
+}
+
 SkCanvas* SkiaOutputSurfaceImpl::BeginPaintCurrentFrame() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   // Make sure there is no unsubmitted PaintFrame or PaintRenderPass.
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h
index 82153ff..aa83c34 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -58,6 +58,8 @@
                bool use_stencil) override;
   void SetUpdateVSyncParametersCallback(
       UpdateVSyncParametersCallback callback) override;
+  void SetDisplayTransformHint(gfx::OverlayTransform transform) override;
+  gfx::OverlayTransform GetDisplayTransform() override;
 
   // SkiaOutputSurface implementation:
   SkCanvas* BeginPaintCurrentFrame() override;
@@ -145,6 +147,11 @@
 
   const RendererSettings renderer_settings_;
 
+  // The display transform relative to the hardware natural orientation,
+  // applied to the frame content. The transform can be rotations in 90 degree
+  // increments or flips.
+  gfx::OverlayTransform pre_transform_ = gfx::OVERLAY_TRANSFORM_NONE;
+
   // |impl_on_gpu| is created and destroyed on the GPU thread.
   std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
 
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
index 6539529..66cdc3e 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -602,6 +602,7 @@
     const gfx::ColorSpace& color_space,
     bool has_alpha,
     bool use_stencil,
+    gfx::OverlayTransform transform,
     SkSurfaceCharacterization* characterization,
     base::WaitableEvent* event) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -618,7 +619,8 @@
 
   size_ = size;
   color_space_ = color_space;
-  output_device_->Reshape(size_, device_scale_factor, color_space, has_alpha);
+  output_device_->Reshape(size_, device_scale_factor, color_space, has_alpha,
+                          transform);
 
   if (characterization) {
     // Start a paint temporarily for getting sk surface characterization.
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
index f06fa850..4770e0d 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -102,6 +102,7 @@
                const gfx::ColorSpace& color_space,
                bool has_alpha,
                bool use_stencil,
+               gfx::OverlayTransform transform,
                SkSurfaceCharacterization* characterization,
                base::WaitableEvent* event);
   void FinishPaintCurrentFrame(
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 6c6d6a6..5770bfb 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -72,8 +72,7 @@
     scoped_refptr<ContextProvider> context_provider,
     scoped_refptr<RasterContextProvider> worker_context_provider,
     scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
-    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-    bool use_viz_hit_test)
+    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
     : LayerTreeFrameSink(std::move(context_provider),
                          std::move(worker_context_provider),
                          std::move(compositor_task_runner),
@@ -83,7 +82,6 @@
       frame_sink_manager_(frame_sink_manager),
       display_(display),
       display_client_(display_client),
-      use_viz_hit_test_(use_viz_hit_test),
       receive_begin_frame_histogram_(
           GetHistogramNamed("GraphicsPipeline.%s.ReceivedBeginFrame",
                             cc::GetClientNameForMetrics())),
@@ -115,8 +113,7 @@
   // Display's context.
   display_->Initialize(this, frame_sink_manager_->surface_manager());
 
-  if (use_viz_hit_test_)
-    support_->SetUpHitTest(display_);
+  support_->SetUpHitTest(display_);
 
   return true;
 }
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
index b1e69ef..3af8eb9 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -73,8 +73,7 @@
       scoped_refptr<ContextProvider> context_provider,
       scoped_refptr<RasterContextProvider> worker_context_provider,
       scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
-      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
-      bool use_viz_hit_test);
+      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
   ~DirectLayerTreeFrameSink() override;
 
   // LayerTreeFrameSink implementation.
@@ -132,7 +131,6 @@
   Display* display_;
   // |display_client_| may be nullptr on platforms that do not use it.
   mojom::DisplayClient* display_client_ = nullptr;
-  bool use_viz_hit_test_ = false;
   gfx::Size last_swap_frame_size_;
   float device_scale_factor_ = 1.f;
   bool is_lost_ = false;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 1b70c10..dd5529e 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -87,8 +87,7 @@
     layer_tree_frame_sink_ = std::make_unique<TestDirectLayerTreeFrameSink>(
         kArbitraryFrameSinkId, &support_manager_, &frame_sink_manager_,
         display_.get(), nullptr /* display_client */, context_provider_,
-        nullptr, task_runner_, &gpu_memory_buffer_manager_,
-        false /* use_viz_hit_test */);
+        nullptr, task_runner_, &gpu_memory_buffer_manager_);
     layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_);
     display_->Resize(display_size_);
     display_->SetVisible(true);
diff --git a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc
index 340cb3e9a..7e28a81a 100644
--- a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc
+++ b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.cc
@@ -29,6 +29,31 @@
       BeginFrameArgs::NORMAL));
 }
 
+BeginFrameArgs GpuVSyncBeginFrameSource::GetMissedBeginFrameArgs(
+    BeginFrameObserver* obs) {
+  auto frame_time = last_begin_frame_args_.frame_time;
+  auto interval = last_begin_frame_args_.interval;
+  auto now = base::TimeTicks::Now();
+
+  if (last_begin_frame_args_.IsValid()) {
+    frame_time = now.SnappedToNextTick(frame_time, interval) - interval;
+  } else {
+    // Create BeginFrameArgs for now so that we don't have to wait until vsync.
+    frame_time = now;
+    interval = BeginFrameArgs::DefaultInterval();
+  }
+
+  // Don't create new args unless we've actually moved past the previous frame.
+  if (!last_begin_frame_args_.IsValid() ||
+      frame_time > last_begin_frame_args_.frame_time) {
+    last_begin_frame_args_ = BeginFrameArgs::Create(
+        BEGINFRAME_FROM_HERE, source_id(), next_begin_frame_sequence_number_++,
+        frame_time, frame_time + interval, interval, BeginFrameArgs::NORMAL);
+  }
+
+  return ExternalBeginFrameSource::GetMissedBeginFrameArgs(obs);
+}
+
 void GpuVSyncBeginFrameSource::OnNeedsBeginFrames(bool needs_begin_frames) {
   output_surface_->SetGpuVSyncEnabled(needs_begin_frames);
 }
diff --git a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h
index ec91631..5ff9fdb 100644
--- a/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h
+++ b/components/viz/service/frame_sinks/gpu_vsync_begin_frame_source.h
@@ -24,6 +24,9 @@
   GpuVSyncBeginFrameSource(uint32_t restart_id, OutputSurface* output_surface);
   ~GpuVSyncBeginFrameSource() override;
 
+  // ExternalBeginFrameSource overrides.
+  BeginFrameArgs GetMissedBeginFrameArgs(BeginFrameObserver* obs) override;
+
   // ExternalBeginFrameSourceClient implementation.
   void OnNeedsBeginFrames(bool needs_begin_frames) override;
 
diff --git a/components/viz/service/surfaces/surface_hittest.cc b/components/viz/service/surfaces/surface_hittest.cc
deleted file mode 100644
index a884b3d..0000000
--- a/components/viz/service/surfaces/surface_hittest.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/service/surfaces/surface_hittest.h"
-
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/draw_quad.h"
-#include "components/viz/common/quads/render_pass_draw_quad.h"
-#include "components/viz/common/quads/surface_draw_quad.h"
-#include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_hittest_delegate.h"
-#include "components/viz/service/surfaces/surface_manager.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/transform.h"
-
-namespace viz {
-
-SurfaceHittest::SurfaceHittest(SurfaceHittestDelegate* delegate,
-                               SurfaceManager* manager)
-    : delegate_(delegate), manager_(manager) {}
-
-SurfaceHittest::~SurfaceHittest() {}
-
-SurfaceId SurfaceHittest::GetTargetSurfaceAtPoint(
-    const SurfaceId& root_surface_id,
-    const gfx::Point& point,
-    gfx::Transform* transform,
-    bool* out_query_renderer) {
-  SurfaceId out_surface_id = root_surface_id;
-
-  // Reset the output transform to identity.
-  if (transform)
-    *transform = gfx::Transform();
-
-  *out_query_renderer = false;
-
-  std::set<const RenderPass*> referenced_passes;
-  GetTargetSurfaceAtPointInternal(root_surface_id, 0, point, &referenced_passes,
-                                  &out_surface_id, transform,
-                                  out_query_renderer);
-  // Any point that hits an OOPIF can defer to renderer-based hit testing
-  // in order to check whether there might be transparent elements
-  // occluding it. Such elements would not have DrawQuads present here.
-  if (root_surface_id != out_surface_id)
-    *out_query_renderer = true;
-
-  return out_surface_id;
-}
-
-bool SurfaceHittest::GetTransformToTargetSurface(
-    const SurfaceId& root_surface_id,
-    const SurfaceId& target_surface_id,
-    gfx::Transform* transform) {
-  // Reset the output transform to identity.
-  if (transform)
-    *transform = gfx::Transform();
-
-  std::set<const RenderPass*> referenced_passes;
-  return GetTransformToTargetSurfaceInternal(root_surface_id, target_surface_id,
-                                             0, &referenced_passes, transform);
-}
-
-bool SurfaceHittest::TransformPointToTargetSurface(
-    const SurfaceId& original_surface_id,
-    const SurfaceId& target_surface_id,
-    gfx::PointF* point) {
-  gfx::Transform transform;
-  // Two possibilities need to be considered: original_surface_id can be
-  // embedded in target_surface_id, or vice versa.
-  if (GetTransformToTargetSurface(target_surface_id, original_surface_id,
-                                  &transform)) {
-    gfx::Transform inverse_transform;
-    if (transform.GetInverse(&inverse_transform))
-      inverse_transform.TransformPoint(point);
-    else
-      return false;
-  } else if (GetTransformToTargetSurface(original_surface_id, target_surface_id,
-                                         &transform)) {
-    // No need to invert the transform matrix in this case.
-    transform.TransformPoint(point);
-  } else {
-    return false;
-  }
-
-  return true;
-}
-
-bool SurfaceHittest::GetTargetSurfaceAtPointInternal(
-    const SurfaceId& surface_id,
-    RenderPassId render_pass_id,
-    const gfx::Point& point_in_root_target,
-    std::set<const RenderPass*>* referenced_passes,
-    SurfaceId* out_surface_id,
-    gfx::Transform* out_transform,
-    bool* out_query_renderer) {
-  const RenderPass* render_pass =
-      GetRenderPassForSurfaceById(surface_id, render_pass_id);
-  if (!render_pass)
-    return false;
-
-  // To avoid an infinite recursion, we need to skip the RenderPass if it's
-  // already been referenced.
-  if (referenced_passes->find(render_pass) != referenced_passes->end())
-    return false;
-
-  referenced_passes->insert(render_pass);
-
-  // The |transform_to_root_target| matrix may have no back-projection if the
-  // forward projection is degenerate.
-  // HasPerspective() is checked for the transform because the point will not
-  // be transformed correctly for a plane with a different normal.
-  // See https://crbug.com/854247.
-  gfx::Transform transform_from_root_target;
-  gfx::Transform transform_to_root_target =
-      render_pass->transform_to_root_target;
-  transform_to_root_target.FlattenTo2d();
-  if (transform_to_root_target.HasPerspective() ||
-      !transform_to_root_target.GetInverse(&transform_from_root_target)) {
-    *out_query_renderer = true;
-    return true;
-  }
-
-  gfx::Point point_in_render_pass_space(point_in_root_target);
-  transform_from_root_target.TransformPoint(&point_in_render_pass_space);
-  bool non_surface_was_hit = false;
-
-  for (const DrawQuad* quad : render_pass->quad_list) {
-    gfx::Transform target_to_quad_transform;
-    gfx::Point point_in_quad_space;
-    if (!PointInQuad(quad, point_in_render_pass_space,
-                     &target_to_quad_transform, &point_in_quad_space)) {
-      if (target_to_quad_transform.HasPerspective()) {
-        *out_query_renderer = true;
-        return false;
-      }
-      continue;
-    }
-
-    switch (quad->material) {
-      case DrawQuad::Material::kSurfaceContent: {
-        // We've hit a SurfaceDrawQuad, we need to recurse into this
-        // Surface.
-        const SurfaceDrawQuad* surface_quad =
-            SurfaceDrawQuad::MaterialCast(quad);
-
-        if (delegate_ &&
-            delegate_->RejectHitTarget(surface_quad, point_in_quad_space)) {
-          continue;
-        }
-
-        // For any point that hits a Surface, we should defer to the renderer.
-        // Some DrawQuads are not valid hit test targets and information
-        // needed to distinguish them is not available here.
-        *out_query_renderer = true;
-
-        if (non_surface_was_hit)
-          return true;
-
-        gfx::Transform transform_to_child_space;
-        if (GetTargetSurfaceAtPointInternal(
-                surface_quad->surface_range.end(), 0, point_in_quad_space,
-                referenced_passes, out_surface_id, &transform_to_child_space,
-                out_query_renderer)) {
-          *out_transform = transform_to_child_space * target_to_quad_transform *
-                           transform_from_root_target;
-          return true;
-        } else if (delegate_ && delegate_->AcceptHitTarget(
-                                    surface_quad, point_in_quad_space)) {
-          *out_surface_id = surface_quad->surface_range.end();
-          *out_transform = transform_to_child_space * target_to_quad_transform *
-                           transform_from_root_target;
-          return true;
-        }
-        break;
-      }
-
-      case DrawQuad::Material::kRenderPass: {
-        // We've hit a RenderPassDrawQuad, we need to recurse into this
-        // RenderPass.
-        const RenderPassDrawQuad* render_quad =
-            RenderPassDrawQuad::MaterialCast(quad);
-
-        SurfaceId out_surface_id_candidate;
-        gfx::Transform transform_to_child_space;
-
-        if (GetTargetSurfaceAtPointInternal(
-                surface_id, render_quad->render_pass_id, point_in_root_target,
-                referenced_passes, &out_surface_id_candidate,
-                &transform_to_child_space, out_query_renderer)) {
-          // If |non_surface_was_hit| is set, then the above call was only for
-          // the purpose of potentially setting |out_query_renderer|.
-          if (!non_surface_was_hit) {
-            *out_transform = transform_to_child_space;
-            *out_surface_id = out_surface_id_candidate;
-            if (surface_id == out_surface_id_candidate) {
-              // Don't return here even though we hit a viable target, in order
-              // to continue looking for occluded surfaces that might be
-              // underneath.
-              non_surface_was_hit = true;
-            } else {
-              return true;
-            }
-          }
-        }
-        break;
-      }
-
-      default: {
-        // We've hit a different type of quad in the current Surface. Typically
-        // this quad will receive the event, but continue iterating to look for
-        // occluded surface quads.
-        *out_surface_id = surface_id;
-        non_surface_was_hit = true;
-      }
-    }
-  }
-
-  if (non_surface_was_hit)
-    return true;
-
-  // No quads were found beneath the provided |point|.
-  return false;
-}
-
-bool SurfaceHittest::GetTransformToTargetSurfaceInternal(
-    const SurfaceId& root_surface_id,
-    const SurfaceId& target_surface_id,
-    RenderPassId render_pass_id,
-    std::set<const RenderPass*>* referenced_passes,
-    gfx::Transform* out_transform) {
-  if (root_surface_id == target_surface_id) {
-    *out_transform = gfx::Transform();
-    return true;
-  }
-
-  const RenderPass* render_pass =
-      GetRenderPassForSurfaceById(root_surface_id, render_pass_id);
-  if (!render_pass)
-    return false;
-
-  // To avoid an infinite recursion, we need to skip the RenderPass if it's
-  // already been referenced.
-  if (referenced_passes->find(render_pass) != referenced_passes->end())
-    return false;
-
-  referenced_passes->insert(render_pass);
-
-  // The |transform_to_root_target| matrix may have no back-projection if the
-  // forward projection is degenerate.
-  gfx::Transform transform_from_root_target;
-  gfx::Transform transform_to_root_target =
-      render_pass->transform_to_root_target;
-  transform_to_root_target.FlattenTo2d();
-  if (!transform_to_root_target.GetInverse(&transform_from_root_target)) {
-    return false;
-  }
-
-  for (const DrawQuad* quad : render_pass->quad_list) {
-    if (quad->material == DrawQuad::Material::kSurfaceContent) {
-      gfx::Transform target_to_quad_transform;
-      gfx::Transform quad_to_target_transform =
-          quad->shared_quad_state->quad_to_target_transform;
-      quad_to_target_transform.FlattenTo2d();
-      if (!quad_to_target_transform.GetInverse(&target_to_quad_transform)) {
-        return false;
-      }
-
-      const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
-      if (surface_quad->surface_range.end() == target_surface_id) {
-        *out_transform = target_to_quad_transform * transform_from_root_target;
-        return true;
-      }
-
-      // This isn't the target surface. Let's recurse deeper to see if we can
-      // find the |target_surface_id| there.
-      gfx::Transform transform_to_child_space;
-      if (GetTransformToTargetSurfaceInternal(
-              surface_quad->surface_range.end(), target_surface_id, 0,
-              referenced_passes, &transform_to_child_space)) {
-        *out_transform = transform_to_child_space * target_to_quad_transform *
-                         transform_from_root_target;
-        return true;
-      }
-      continue;
-    }
-
-    if (quad->material == DrawQuad::Material::kRenderPass) {
-      // We've hit a RenderPassDrawQuad, we need to recurse into this
-      // RenderPass.
-      const RenderPassDrawQuad* render_quad =
-          RenderPassDrawQuad::MaterialCast(quad);
-
-      gfx::Transform transform_to_child_space;
-      if (GetTransformToTargetSurfaceInternal(
-              root_surface_id, target_surface_id, render_quad->render_pass_id,
-              referenced_passes, &transform_to_child_space)) {
-        *out_transform = transform_to_child_space;
-        return true;
-      }
-
-      continue;
-    }
-  }
-
-  // The target surface was not found.
-  return false;
-}
-
-const RenderPass* SurfaceHittest::GetRenderPassForSurfaceById(
-    const SurfaceId& surface_id,
-    RenderPassId render_pass_id) {
-  Surface* surface = manager_->GetSurfaceForId(surface_id);
-  if (!surface)
-    return nullptr;
-  if (!surface->HasActiveFrame())
-    return nullptr;
-  const CompositorFrame& surface_frame = surface->GetActiveFrame();
-
-  if (!render_pass_id)
-    return surface_frame.render_pass_list.back().get();
-
-  for (const auto& render_pass : surface_frame.render_pass_list) {
-    if (render_pass->id == render_pass_id)
-      return render_pass.get();
-  }
-
-  return nullptr;
-}
-
-bool SurfaceHittest::PointInQuad(const DrawQuad* quad,
-                                 const gfx::Point& point_in_render_pass_space,
-                                 gfx::Transform* target_to_quad_transform,
-                                 gfx::Point* point_in_quad_space) {
-  // First we test against the clip_rect. The clip_rect is in target space, so
-  // we can test the point directly.
-  if (quad->shared_quad_state->is_clipped &&
-      !quad->shared_quad_state->clip_rect.Contains(
-          point_in_render_pass_space)) {
-    return false;
-  }
-
-  // We now transform the point to content space and test if it hits the
-  // rect.
-  gfx::Transform transform = quad->shared_quad_state->quad_to_target_transform;
-  transform.FlattenTo2d();
-  if (!transform.GetInverse(target_to_quad_transform) ||
-      target_to_quad_transform->HasPerspective()) {
-    return false;
-  }
-
-  *point_in_quad_space = point_in_render_pass_space;
-  target_to_quad_transform->TransformPoint(point_in_quad_space);
-
-  return quad->rect.Contains(*point_in_quad_space);
-}
-
-}  // namespace viz
diff --git a/components/viz/service/surfaces/surface_hittest.h b/components/viz/service/surfaces/surface_hittest.h
deleted file mode 100644
index c297e04c..0000000
--- a/components/viz/service/surfaces/surface_hittest.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_H_
-#define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_H_
-
-#include <set>
-
-#include "components/viz/common/quads/render_pass.h"
-#include "components/viz/common/surfaces/surface_id.h"
-#include "components/viz/service/viz_service_export.h"
-
-namespace gfx {
-class Point;
-class Transform;
-}  // namespace gfx
-
-namespace cc {
-class DrawQuad;
-class RenderPass;
-}  // namespace cc
-
-namespace viz {
-
-class SurfaceHittestDelegate;
-class SurfaceManager;
-
-// Performs a hittest in surface quads.
-class VIZ_SERVICE_EXPORT SurfaceHittest {
- public:
-  SurfaceHittest(SurfaceHittestDelegate* delegate, SurfaceManager* manager);
-  ~SurfaceHittest();
-
-  // Returns the target surface that falls underneath the provided |point|.
-  // |out_query_renderer| is set to true if the result is not high confidence,
-  // which means that there could be a different result when hit testing is
-  // performed in the renderer process. In that case the returned SurfaceId and
-  // Transform should be ignored.
-  // When |out_query_renderer| is set to false the returned SurfaceId and
-  // Transform can be taken as correct without further verification.
-  // Also returns the |transform| to convert the |point| to the target surface's
-  // space.
-  SurfaceId GetTargetSurfaceAtPoint(const SurfaceId& root_surface_id,
-                                    const gfx::Point& point,
-                                    gfx::Transform* transform,
-                                    bool* out_query_renderer);
-
-  // Returns whether the target surface falls inside the provide root surface.
-  // Returns the |transform| to convert points from the root surface coordinate
-  // space to the target surface coordinate space.
-  bool GetTransformToTargetSurface(const SurfaceId& root_surface_id,
-                                   const SurfaceId& target_surface_id,
-                                   gfx::Transform* transform);
-
-  // Attempts to transform a point from the coordinate space of one surface to
-  // that of another, where one is surface is embedded within the other.
-  // Returns true if the transform is successfully applied, and false if
-  // neither surface is contained with the other.
-  bool TransformPointToTargetSurface(const SurfaceId& original_surface_id,
-                                     const SurfaceId& target_surface_id,
-                                     gfx::PointF* point);
-
- private:
-  bool GetTargetSurfaceAtPointInternal(
-      const SurfaceId& surface_id,
-      RenderPassId render_pass_id,
-      const gfx::Point& point_in_root_target,
-      std::set<const RenderPass*>* referenced_passes,
-      SurfaceId* out_surface_id,
-      gfx::Transform* out_transform,
-      bool* out_query_renderer);
-
-  bool GetTransformToTargetSurfaceInternal(
-      const SurfaceId& root_surface_id,
-      const SurfaceId& target_surface_id,
-      RenderPassId render_pass_id,
-      std::set<const RenderPass*>* referenced_passes,
-      gfx::Transform* out_transform);
-
-  const RenderPass* GetRenderPassForSurfaceById(const SurfaceId& surface_id,
-                                                RenderPassId render_pass_id);
-
-  bool PointInQuad(const DrawQuad* quad,
-                   const gfx::Point& point_in_render_pass_space,
-                   gfx::Transform* target_to_quad_transform,
-                   gfx::Point* point_in_quad_space);
-
-  SurfaceHittestDelegate* const delegate_;
-  SurfaceManager* const manager_;
-};
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_H_
diff --git a/components/viz/service/surfaces/surface_hittest_delegate.h b/components/viz/service/surfaces/surface_hittest_delegate.h
deleted file mode 100644
index d1ae2e1f..0000000
--- a/components/viz/service/surfaces/surface_hittest_delegate.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_DELEGATE_H_
-#define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_DELEGATE_H_
-
-namespace gfx {
-class Point;
-}  // namespace gfx
-
-namespace viz {
-class SurfaceDrawQuad;
-
-// Clients of SurfaceHittest can provide a SurfaceHittestDelegate implementation
-// to override the hit target based on metadata outside of the Surfaces system.
-class SurfaceHittestDelegate {
- public:
-  // Return true if this delegate rejects this |surface_quad| as a candidate hit
-  // target.
-  virtual bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
-                               const gfx::Point& point_in_quad_space) = 0;
-
-  // Return true if this delegate accepts this |surface_quad| as a candidate hit
-  // target.
-  virtual bool AcceptHitTarget(const SurfaceDrawQuad* surface_quad,
-                               const gfx::Point& point_in_quad_space) = 0;
-};
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_HITTEST_DELEGATE_H_
diff --git a/components/viz/service/surfaces/surface_hittest_unittest.cc b/components/viz/service/surfaces/surface_hittest_unittest.cc
deleted file mode 100644
index 580f2b4..0000000
--- a/components/viz/service/surfaces/surface_hittest_unittest.cc
+++ /dev/null
@@ -1,697 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/stl_util.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
-#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
-#include "components/viz/service/surfaces/surface_manager.h"
-#include "components/viz/test/compositor_frame_helpers.h"
-#include "components/viz/test/fake_compositor_frame_sink_client.h"
-#include "components/viz/test/surface_hittest_test_helpers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace viz {
-
-namespace {
-
-constexpr bool kIsRoot = true;
-constexpr bool kIsChildRoot = false;
-constexpr bool kNeedsSyncPoints = true;
-constexpr FrameSinkId kRootFrameSink(2, 0);
-constexpr FrameSinkId kChildFrameSink(65563, 0);
-constexpr FrameSinkId kArbitraryFrameSink(1337, 7331);
-
-struct TestCase {
-  SurfaceId input_surface_id;
-  gfx::Point input_point;
-  SurfaceId expected_layer_tree_frame_sink_id;
-  gfx::Point expected_output_point;
-  bool query_renderer;
-};
-
-void RunTests(SurfaceHittestDelegate* delegate,
-              SurfaceManager* manager,
-              TestCase* tests,
-              size_t test_count) {
-  SurfaceHittest hittest(delegate, manager);
-  bool query_renderer;
-  for (size_t i = 0; i < test_count; ++i) {
-    const TestCase& test = tests[i];
-    gfx::Point point(test.input_point);
-    gfx::Transform transform;
-    EXPECT_EQ(test.expected_layer_tree_frame_sink_id,
-              hittest.GetTargetSurfaceAtPoint(test.input_surface_id, point,
-                                              &transform, &query_renderer));
-    transform.TransformPoint(&point);
-    EXPECT_EQ(test.expected_output_point, point);
-    EXPECT_EQ(test.query_renderer, query_renderer);
-
-    // Verify that GetTransformToTargetSurface returns true and returns the same
-    // transform as returned by GetTargetSurfaceAtPoint.
-    gfx::Transform target_transform;
-    EXPECT_TRUE(hittest.GetTransformToTargetSurface(
-        test.input_surface_id, test.expected_layer_tree_frame_sink_id,
-        &target_transform));
-    EXPECT_EQ(transform, target_transform);
-  }
-}
-
-}  // namespace
-
-using namespace test;
-
-class SurfaceHittestTest : public testing::Test {
- public:
-  SurfaceHittestTest() : frame_sink_manager_(&shared_bitmap_manager_) {}
-  ~SurfaceHittestTest() override = default;
-
-  CompositorFrameSinkSupport& root_support() { return *supports_[0]; }
-
-  CompositorFrameSinkSupport& child_support() { return *supports_[1]; }
-
-  SurfaceManager* surface_manager() {
-    return frame_sink_manager_.surface_manager();
-  }
-
-  // testing::Test:
-  void SetUp() override {
-    testing::Test::SetUp();
-
-    supports_.push_back(std::make_unique<CompositorFrameSinkSupport>(
-        &client_, &frame_sink_manager_, kRootFrameSink, kIsRoot,
-        kNeedsSyncPoints));
-    supports_.push_back(std::make_unique<CompositorFrameSinkSupport>(
-        &client_, &frame_sink_manager_, kChildFrameSink, kIsChildRoot,
-        kNeedsSyncPoints));
-  }
-
-  void TearDown() override { supports_.clear(); }
-
- private:
-  ServerSharedBitmapManager shared_bitmap_manager_;
-  FrameSinkManagerImpl frame_sink_manager_;
-  std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_;
-  FakeCompositorFrameSinkClient client_;
-
-  DISALLOW_COPY_AND_ASSIGN(SurfaceHittestTest);
-};
-
-// This test verifies that hit testing on a surface that does not exist does
-// not crash.
-TEST_F(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Add a reference to a non-existant child surface on the root surface.
-  SurfaceId child_surface_id(
-      kArbitraryFrameSink,
-      LocalSurfaceId(0xdeadbeef, 0xdeadbeef, base::UnguessableToken::Create()));
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(root_pass, gfx::Transform(), root_rect, child_rect,
-                        child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  {
-    SurfaceHittest hittest(nullptr, surface_manager());
-    // It is expected this test will complete without crashes.
-    gfx::Transform transform;
-    bool query_renderer;
-    EXPECT_EQ(root_surface_id, hittest.GetTargetSurfaceAtPoint(
-                                   root_surface_id, gfx::Point(100, 100),
-                                   &transform, &query_renderer));
-  }
-}
-
-TEST_F(SurfaceHittestTest, Hittest_SingleSurface) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-  TestCase tests[] = {
-      {root_surface_id, gfx::Point(100, 100), root_surface_id,
-       gfx::Point(100, 100), false},
-  };
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-}
-
-TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Add a reference to the child surface on the root surface.
-  ParentLocalSurfaceIdAllocator child_allocator;
-  child_allocator.GenerateId();
-  SurfaceId child_surface_id(
-      kChildFrameSink,
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Creates a child surface.
-  RenderPass* child_pass = nullptr;
-  CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass);
-
-  // Add a solid quad in the child surface.
-  gfx::Rect child_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(
-      child_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_solid_quad_rect);
-
-  // Submit the frame.
-  child_support().SubmitCompositorFrame(
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(child_frame));
-
-  TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
-                       gfx::Point(10, 10), false},
-                      {root_surface_id, gfx::Point(99, 99), root_surface_id,
-                       gfx::Point(99, 99), true},
-                      {root_surface_id, gfx::Point(100, 100), child_surface_id,
-                       gfx::Point(50, 50), true},
-                      {root_surface_id, gfx::Point(199, 199), child_surface_id,
-                       gfx::Point(149, 149), true},
-                      {root_surface_id, gfx::Point(200, 200), root_surface_id,
-                       gfx::Point(200, 200), true},
-                      {root_surface_id, gfx::Point(290, 290), root_surface_id,
-                       gfx::Point(290, 290), false}};
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-
-  // Submit another root frame, with a slightly perturbed child Surface.
-  root_frame = CreateCompositorFrame(root_rect, &root_pass);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 75.0f, 0.0f, 1.0f, 0.0f, 75.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Verify that point (100, 100) no longer falls on the child surface.
-  // Verify that the transform to the child surface's space has also shifted.
-  {
-    SurfaceHittest hittest(nullptr, surface_manager());
-
-    gfx::Point point(100, 100);
-    gfx::Transform transform;
-    bool query_renderer;
-    EXPECT_EQ(root_surface_id,
-              hittest.GetTargetSurfaceAtPoint(root_surface_id, point,
-                                              &transform, &query_renderer));
-    transform.TransformPoint(&point);
-    EXPECT_EQ(gfx::Point(100, 100), point);
-    EXPECT_EQ(query_renderer, true);
-
-    gfx::Point point_in_target_space(100, 100);
-    gfx::Transform target_transform;
-    EXPECT_TRUE(hittest.GetTransformToTargetSurface(
-        root_surface_id, child_surface_id, &target_transform));
-    target_transform.TransformPoint(&point_in_target_space);
-    EXPECT_NE(transform, target_transform);
-    EXPECT_EQ(gfx::Point(25, 25), point_in_target_space);
-  }
-}
-
-TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Add a solid quad to the root surface, occluding the child surface.
-  gfx::Rect root_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, root_solid_quad_rect);
-
-  // Add a reference to the child surface on the root surface.
-  ParentLocalSurfaceIdAllocator child_allocator;
-  child_allocator.GenerateId();
-  SurfaceId child_surface_id(
-      kChildFrameSink,
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Creates a child surface.
-  RenderPass* child_pass = nullptr;
-  CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass);
-
-  // Add a solid quad in the child surface.
-  gfx::Rect child_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(
-      child_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_solid_quad_rect);
-
-  // Submit the frame.
-  child_support().SubmitCompositorFrame(
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(child_frame));
-
-  TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
-                       gfx::Point(10, 10), false},
-                      {root_surface_id, gfx::Point(99, 99), root_surface_id,
-                       gfx::Point(99, 99), true},
-                      {root_surface_id, gfx::Point(100, 100), root_surface_id,
-                       gfx::Point(100, 100), true},
-                      {root_surface_id, gfx::Point(199, 199), child_surface_id,
-                       gfx::Point(149, 149), true},
-                      {root_surface_id, gfx::Point(200, 200), root_surface_id,
-                       gfx::Point(200, 200), true},
-                      {root_surface_id, gfx::Point(290, 290), root_surface_id,
-                       gfx::Point(290, 290), false}};
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-}
-
-// This test verifies that hit testing will progress to the next quad if it
-// encounters an invalid RenderPassDrawQuad for whatever reason.
-TEST_F(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Create a RenderPassDrawQuad to a non-existant RenderPass.
-  int invalid_render_pass_id = 1337;
-  CreateRenderPassDrawQuad(root_pass, gfx::Transform(), root_rect, root_rect,
-                           invalid_render_pass_id);
-
-  // Add a reference to the child surface on the root surface.
-  ParentLocalSurfaceIdAllocator child_allocator;
-  child_allocator.GenerateId();
-  LocalSurfaceId child_local_surface_id =
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id();
-  SurfaceId child_surface_id(kChildFrameSink, child_local_surface_id);
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Creates a child surface.
-  RenderPass* child_pass = nullptr;
-  CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass);
-
-  // Add a solid quad in the child surface.
-  gfx::Rect child_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(
-      child_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_solid_quad_rect);
-
-  // Submit the frame.
-  child_support().SubmitCompositorFrame(
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(child_frame));
-
-  TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
-                       gfx::Point(10, 10), false},
-                      {root_surface_id, gfx::Point(99, 99), root_surface_id,
-                       gfx::Point(99, 99), true},
-                      {root_surface_id, gfx::Point(100, 100), child_surface_id,
-                       gfx::Point(50, 50), true},
-                      {root_surface_id, gfx::Point(199, 199), child_surface_id,
-                       gfx::Point(149, 149), true},
-                      {root_surface_id, gfx::Point(200, 200), root_surface_id,
-                       gfx::Point(200, 200), true},
-                      {root_surface_id, gfx::Point(290, 290), root_surface_id,
-                       gfx::Point(290, 290), false}};
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-}
-
-TEST_F(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
-  // Create a CompositorFrame with two RenderPasses.
-  gfx::Rect root_rect(300, 300);
-  CompositorFrame root_frame = MakeDefaultCompositorFrame();
-  RenderPassList& render_pass_list = root_frame.render_pass_list;
-
-  // Create a child RenderPass.
-  int child_render_pass_id = 3;
-  gfx::Transform transform_to_root_target(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f,
-                                          0.0f, 50.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-                                          0.0f, 0.0f, 0.0f, 1.0f);
-  CreateRenderPass(child_render_pass_id, gfx::Rect(100, 100),
-                   transform_to_root_target, &render_pass_list);
-
-  // Create the root RenderPass.
-  int root_render_pass_id = 2;
-  CreateRenderPass(root_render_pass_id, root_rect, gfx::Transform(),
-                   &render_pass_list);
-
-  RenderPass* root_pass = nullptr;
-  root_pass = root_frame.render_pass_list.back().get();
-
-  // Create a RenderPassDrawQuad.
-  gfx::Rect render_pass_quad_rect(100, 100);
-  CreateRenderPassDrawQuad(root_pass, transform_to_root_target, root_rect,
-                           render_pass_quad_rect, child_render_pass_id);
-
-  // Add a solid quad in the child render pass.
-  RenderPass* child_render_pass = root_frame.render_pass_list.front().get();
-  gfx::Rect child_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(child_render_pass, gfx::Transform(),
-                           gfx::Rect(100, 100), child_solid_quad_rect);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  TestCase tests[] = {// These tests just miss the RenderPassDrawQuad.
-                      {root_surface_id, gfx::Point(49, 49), root_surface_id,
-                       gfx::Point(49, 49), false},
-                      {root_surface_id, gfx::Point(150, 150), root_surface_id,
-                       gfx::Point(150, 150), false},
-                      // These tests just hit the boundaries of the
-                      // RenderPassDrawQuad.
-                      {root_surface_id, gfx::Point(50, 50), root_surface_id,
-                       gfx::Point(50, 50), false},
-                      {root_surface_id, gfx::Point(149, 149), root_surface_id,
-                       gfx::Point(149, 149), false},
-                      // These tests fall somewhere in the center of the
-                      // RenderPassDrawQuad.
-                      {root_surface_id, gfx::Point(99, 99), root_surface_id,
-                       gfx::Point(99, 99), false},
-                      {root_surface_id, gfx::Point(100, 100), root_surface_id,
-                       gfx::Point(100, 100), false}};
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-}
-
-TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Add a reference to the child surface on the root surface.
-  ParentLocalSurfaceIdAllocator child_allocator;
-  child_allocator.GenerateId();
-  SurfaceId child_surface_id(
-      kChildFrameSink,
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Creates a child surface.
-  RenderPass* child_pass = nullptr;
-  CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass);
-
-  // Add a solid quad in the child surface.
-  gfx::Rect child_solid_quad_rect(190, 190);
-  CreateSolidColorDrawQuad(
-      child_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 5.0f, 0.0f, 1.0f, 0.0f, 5.0f, 0.0f, 0.0f,
-                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_solid_quad_rect);
-
-  // Submit the frame.
-  child_support().SubmitCompositorFrame(
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(child_frame));
-
-  TestCase test_expectations_without_insets[] = {
-      {root_surface_id, gfx::Point(55, 55), child_surface_id, gfx::Point(5, 5),
-       true},
-      {root_surface_id, gfx::Point(60, 60), child_surface_id,
-       gfx::Point(10, 10), true},
-      {root_surface_id, gfx::Point(239, 239), child_surface_id,
-       gfx::Point(189, 189), true},
-      {root_surface_id, gfx::Point(244, 244), child_surface_id,
-       gfx::Point(194, 194), true},
-      {root_surface_id, gfx::Point(50, 50), root_surface_id, gfx::Point(50, 50),
-       true},
-      {root_surface_id, gfx::Point(249, 249), root_surface_id,
-       gfx::Point(249, 249), true},
-  };
-
-  TestSurfaceHittestDelegate empty_delegate;
-  RunTests(&empty_delegate, surface_manager(), test_expectations_without_insets,
-           base::size(test_expectations_without_insets));
-
-  // Verify that insets have NOT affected hit targeting.
-  EXPECT_EQ(0, empty_delegate.reject_target_overrides());
-  EXPECT_EQ(0, empty_delegate.accept_target_overrides());
-
-  TestCase test_expectations_with_reject_insets[] = {
-      // Point (55, 55) falls outside the child surface due to the insets
-      // introduced above.
-      {root_surface_id, gfx::Point(55, 55), root_surface_id, gfx::Point(55, 55),
-       false},
-      // These two points still fall within the child surface.
-      {root_surface_id, gfx::Point(60, 60), child_surface_id,
-       gfx::Point(10, 10), true},
-      {root_surface_id, gfx::Point(239, 239), child_surface_id,
-       gfx::Point(189, 189), true},
-      // Point (244, 244) falls outside the child surface due to the insets
-      // introduced above.
-      {root_surface_id, gfx::Point(244, 244), root_surface_id,
-       gfx::Point(244, 244), false},
-      // Next two points also fall within within the insets indroduced above.
-      {root_surface_id, gfx::Point(50, 50), root_surface_id, gfx::Point(50, 50),
-       false},
-      {root_surface_id, gfx::Point(249, 249), root_surface_id,
-       gfx::Point(249, 249), false},
-  };
-
-  TestSurfaceHittestDelegate reject_delegate;
-  reject_delegate.AddInsetsForRejectSurface(child_surface_id,
-                                            gfx::Insets(10, 10, 10, 10));
-  RunTests(&reject_delegate, surface_manager(),
-           test_expectations_with_reject_insets,
-           base::size(test_expectations_with_reject_insets));
-
-  // Verify that insets have affected hit targeting.
-  EXPECT_EQ(4, reject_delegate.reject_target_overrides());
-  EXPECT_EQ(0, reject_delegate.accept_target_overrides());
-
-  TestCase test_expectations_with_accept_insets[] = {
-      {root_surface_id, gfx::Point(55, 55), child_surface_id, gfx::Point(5, 5),
-       true},
-      {root_surface_id, gfx::Point(60, 60), child_surface_id,
-       gfx::Point(10, 10), true},
-      {root_surface_id, gfx::Point(239, 239), child_surface_id,
-       gfx::Point(189, 189), true},
-      {root_surface_id, gfx::Point(244, 244), child_surface_id,
-       gfx::Point(194, 194), true},
-      // Next two points fall within within the insets indroduced above.
-      {root_surface_id, gfx::Point(50, 50), child_surface_id, gfx::Point(0, 0),
-       true},
-      {root_surface_id, gfx::Point(249, 249), child_surface_id,
-       gfx::Point(199, 199), true},
-  };
-
-  TestSurfaceHittestDelegate accept_delegate;
-  accept_delegate.AddInsetsForAcceptSurface(child_surface_id,
-                                            gfx::Insets(5, 5, 5, 5));
-  RunTests(&accept_delegate, surface_manager(),
-           test_expectations_with_accept_insets,
-           base::size(test_expectations_with_accept_insets));
-
-  // Verify that insets have affected hit targeting.
-  EXPECT_EQ(0, accept_delegate.reject_target_overrides());
-  EXPECT_EQ(2, accept_delegate.accept_target_overrides());
-}
-
-// Hit test against a child surface that has a non-flat transform. This
-// verifies that the transform is flattened before hit testing.
-TEST_F(SurfaceHittestTest, Hittest_ChildSurfaceWithNonFlatTransform) {
-  // Creates a root surface.
-  gfx::Rect root_rect(300, 300);
-  RenderPass* root_pass = nullptr;
-  CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass);
-
-  // Add a reference to the child surface on the root surface.
-  ParentLocalSurfaceIdAllocator child_allocator;
-  child_allocator.GenerateId();
-  SurfaceId child_surface_id(
-      kChildFrameSink,
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  gfx::Rect child_rect(200, 200);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 1.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-
-  // Submit the root frame.
-  ParentLocalSurfaceIdAllocator root_allocator;
-  root_allocator.GenerateId();
-  SurfaceId root_surface_id(
-      kRootFrameSink,
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id());
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Creates a child surface.
-  RenderPass* child_pass = nullptr;
-  CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass);
-
-  // Add a solid quad in the child surface.
-  gfx::Rect child_solid_quad_rect(100, 100);
-  CreateSolidColorDrawQuad(
-      child_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_solid_quad_rect);
-
-  // Submit the frame.
-  child_support().SubmitCompositorFrame(
-      child_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(child_frame));
-
-  TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
-                       gfx::Point(10, 10), false},
-                      {root_surface_id, gfx::Point(99, 99), root_surface_id,
-                       gfx::Point(99, 99), true},
-                      {root_surface_id, gfx::Point(100, 100), child_surface_id,
-                       gfx::Point(50, 50), true},
-                      {root_surface_id, gfx::Point(199, 199), child_surface_id,
-                       gfx::Point(149, 149), true},
-                      {root_surface_id, gfx::Point(200, 200), root_surface_id,
-                       gfx::Point(200, 200), true},
-                      {root_surface_id, gfx::Point(290, 290), root_surface_id,
-                       gfx::Point(290, 290), false}};
-
-  RunTests(nullptr, surface_manager(), tests, base::size(tests));
-
-  // Submit another root frame, with a slightly perturbed child Surface.
-  root_frame = CreateCompositorFrame(root_rect, &root_pass);
-  CreateSurfaceDrawQuad(
-      root_pass,
-      gfx::Transform(1.0f, 0.0f, 0.0f, 75.0f, 0.0f, 1.0f, 0.0f, 75.0f, 0.0f,
-                     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
-      root_rect, child_rect, child_surface_id);
-  root_support().SubmitCompositorFrame(
-      root_allocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(),
-      std::move(root_frame));
-
-  // Verify that point (100, 100) no longer falls on the child surface.
-  // Verify that the transform to the child surface's space has also shifted.
-  {
-    SurfaceHittest hittest(nullptr, surface_manager());
-
-    gfx::Point point(100, 100);
-    gfx::Transform transform;
-    bool query_renderer;
-    EXPECT_EQ(root_surface_id,
-              hittest.GetTargetSurfaceAtPoint(root_surface_id, point,
-                                              &transform, &query_renderer));
-    transform.TransformPoint(&point);
-    EXPECT_EQ(gfx::Point(100, 100), point);
-    EXPECT_EQ(query_renderer, true);
-
-    gfx::Point point_in_target_space(100, 100);
-    gfx::Transform target_transform;
-    EXPECT_TRUE(hittest.GetTransformToTargetSurface(
-        root_surface_id, child_surface_id, &target_transform));
-    target_transform.TransformPoint(&point_in_target_space);
-    EXPECT_NE(transform, target_transform);
-    EXPECT_EQ(gfx::Point(25, 25), point_in_target_space);
-  }
-}
-
-}  // namespace viz
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index a0869ce..57e32f8 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -45,8 +45,6 @@
     "paths.h",
     "stub_surface_client.cc",
     "stub_surface_client.h",
-    "surface_hittest_test_helpers.cc",
-    "surface_hittest_test_helpers.h",
     "surface_id_allocator_set.cc",
     "surface_id_allocator_set.h",
     "test_context_provider.cc",
diff --git a/components/viz/test/surface_hittest_test_helpers.cc b/components/viz/test/surface_hittest_test_helpers.cc
deleted file mode 100644
index 4e3ec60..0000000
--- a/components/viz/test/surface_hittest_test_helpers.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/test/surface_hittest_test_helpers.h"
-
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/render_pass_draw_quad.h"
-#include "components/viz/common/quads/shared_quad_state.h"
-#include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/surface_draw_quad.h"
-#include "components/viz/test/compositor_frame_helpers.h"
-
-namespace viz {
-namespace test {
-
-void CreateSharedQuadState(RenderPass* pass,
-                           const gfx::Transform& transform,
-                           const gfx::Rect& root_rect) {
-  SharedQuadState* child_shared_state = pass->CreateAndAppendSharedQuadState();
-  child_shared_state->SetAll(transform, root_rect, root_rect, gfx::RRectF(),
-                             root_rect, false, false, 1.0f,
-                             SkBlendMode::kSrcOver, 0);
-}
-
-void CreateSolidColorDrawQuad(RenderPass* pass,
-                              const gfx::Transform& transform,
-                              const gfx::Rect& root_rect,
-                              const gfx::Rect& quad_rect) {
-  CreateSharedQuadState(pass, transform, root_rect);
-  SolidColorDrawQuad* color_quad =
-      pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
-  color_quad->SetNew(pass->shared_quad_state_list.back(), quad_rect, quad_rect,
-                     SK_ColorYELLOW, false);
-}
-
-void CreateRenderPassDrawQuad(RenderPass* pass,
-                              const gfx::Transform& transform,
-                              const gfx::Rect& root_rect,
-                              const gfx::Rect& quad_rect,
-                              int render_pass_id) {
-  CreateSharedQuadState(pass, transform, root_rect);
-  RenderPassDrawQuad* render_pass_quad =
-      pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
-  render_pass_quad->SetNew(pass->shared_quad_state_list.back(), quad_rect,
-                           quad_rect, render_pass_id, ResourceId(),
-                           gfx::RectF(), gfx::Size(), gfx::Vector2dF(),
-                           gfx::PointF(), gfx::RectF(), false, 1.0f);
-}
-
-void CreateSurfaceDrawQuad(RenderPass* pass,
-                           const gfx::Transform& transform,
-                           const gfx::Rect& root_rect,
-                           const gfx::Rect& quad_rect,
-                           SurfaceId surface_id) {
-  CreateSharedQuadState(pass, transform, root_rect);
-  SurfaceDrawQuad* surface_quad =
-      pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
-  surface_quad->SetNew(pass->shared_quad_state_list.back(), quad_rect,
-                       quad_rect, SurfaceRange(base::nullopt, surface_id),
-                       SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false,
-                       /*ignores_input_event=*/false);
-}
-
-void CreateRenderPass(int render_pass_id,
-                      const gfx::Rect& rect,
-                      const gfx::Transform& transform_to_root_target,
-                      RenderPassList* render_pass_list) {
-  std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
-  render_pass->SetNew(render_pass_id, rect, rect, transform_to_root_target);
-  render_pass_list->push_back(std::move(render_pass));
-}
-
-CompositorFrame CreateCompositorFrame(const gfx::Rect& root_rect,
-                                      RenderPass** render_pass) {
-  CompositorFrame root_frame = MakeDefaultCompositorFrame();
-  int root_id = 1;
-  CreateRenderPass(root_id, root_rect, gfx::Transform(),
-                   &root_frame.render_pass_list);
-  *render_pass = root_frame.render_pass_list.back().get();
-  return root_frame;
-}
-
-TestSurfaceHittestDelegate::TestSurfaceHittestDelegate()
-    : reject_target_overrides_(0), accept_target_overrides_(0) {}
-
-TestSurfaceHittestDelegate::~TestSurfaceHittestDelegate() {}
-
-void TestSurfaceHittestDelegate::AddInsetsForRejectSurface(
-    const SurfaceId& surface_id,
-    const gfx::Insets& inset) {
-  insets_for_reject_.insert(std::make_pair(surface_id, inset));
-}
-
-void TestSurfaceHittestDelegate::AddInsetsForAcceptSurface(
-    const SurfaceId& surface_id,
-    const gfx::Insets& inset) {
-  insets_for_accept_.insert(std::make_pair(surface_id, inset));
-}
-
-bool TestSurfaceHittestDelegate::RejectHitTarget(
-    const SurfaceDrawQuad* surface_quad,
-    const gfx::Point& point_in_quad_space) {
-  if (!insets_for_reject_.count(surface_quad->surface_range.end()))
-    return false;
-  gfx::Rect bounds(surface_quad->rect);
-  bounds.Inset(insets_for_reject_[surface_quad->surface_range.end()]);
-  // If the point provided falls outside the inset, then we skip this surface.
-  if (!bounds.Contains(point_in_quad_space)) {
-    if (surface_quad->rect.Contains(point_in_quad_space))
-      ++reject_target_overrides_;
-    return true;
-  }
-  return false;
-}
-
-bool TestSurfaceHittestDelegate::AcceptHitTarget(
-    const SurfaceDrawQuad* surface_quad,
-    const gfx::Point& point_in_quad_space) {
-  if (!insets_for_accept_.count(surface_quad->surface_range.end()))
-    return false;
-  gfx::Rect bounds(surface_quad->rect);
-  bounds.Inset(insets_for_accept_[surface_quad->surface_range.end()]);
-  // If the point provided falls outside the inset, then we accept this surface.
-  if (!bounds.Contains(point_in_quad_space)) {
-    ++accept_target_overrides_;
-    return true;
-  }
-  return false;
-}
-
-}  // namespace test
-}  // namespace viz
diff --git a/components/viz/test/surface_hittest_test_helpers.h b/components/viz/test/surface_hittest_test_helpers.h
deleted file mode 100644
index 838cb75..0000000
--- a/components/viz/test/surface_hittest_test_helpers.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
-#define COMPONENTS_VIZ_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
-
-#include <map>
-#include <memory>
-
-#include "base/macros.h"
-#include "components/viz/common/quads/render_pass.h"
-#include "components/viz/common/surfaces/surface_id.h"
-#include "components/viz/service/surfaces/surface_hittest_delegate.h"
-#include "ui/gfx/geometry/insets.h"
-
-namespace gfx {
-class Transform;
-}
-
-namespace viz {
-class CompositorFrame;
-
-namespace test {
-
-void CreateSharedQuadState(RenderPass* pass,
-                           const gfx::Transform& transform,
-                           const gfx::Rect& root_rect);
-
-void CreateSolidColorDrawQuad(RenderPass* pass,
-                              const gfx::Transform& transform,
-                              const gfx::Rect& root_rect,
-                              const gfx::Rect& quad_rect);
-
-void CreateRenderPassDrawQuad(RenderPass* pass,
-                              const gfx::Transform& transform,
-                              const gfx::Rect& root_rect,
-                              const gfx::Rect& quad_rect,
-                              int render_pass_id);
-
-void CreateSurfaceDrawQuad(RenderPass* pass,
-                           const gfx::Transform& transform,
-                           const gfx::Rect& root_rect,
-                           const gfx::Rect& quad_rect,
-                           SurfaceId surface_id);
-
-void CreateRenderPass(int render_pass_id,
-                      const gfx::Rect& rect,
-                      const gfx::Transform& transform_to_root_target,
-                      RenderPassList* render_pass_list);
-
-CompositorFrame CreateCompositorFrameWithRenderPassList(
-    RenderPassList* render_pass_list);
-
-CompositorFrame CreateCompositorFrame(const gfx::Rect& root_rect,
-                                      RenderPass** render_pass);
-
-class TestSurfaceHittestDelegate : public SurfaceHittestDelegate {
- public:
-  TestSurfaceHittestDelegate();
-  ~TestSurfaceHittestDelegate();
-
-  int reject_target_overrides() const { return reject_target_overrides_; }
-  int accept_target_overrides() const { return accept_target_overrides_; }
-
-  void AddInsetsForRejectSurface(const SurfaceId& surface_id,
-                                 const gfx::Insets& inset);
-  void AddInsetsForAcceptSurface(const SurfaceId& surface_id,
-                                 const gfx::Insets& inset);
-
-  // SurfaceHittestDelegate implementation.
-  bool RejectHitTarget(const SurfaceDrawQuad* surface_quad,
-                       const gfx::Point& point_in_quad_space) override;
-  bool AcceptHitTarget(const SurfaceDrawQuad* surface_quad,
-                       const gfx::Point& point_in_quad_space) override;
-
- private:
-  int reject_target_overrides_;
-  int accept_target_overrides_;
-  std::map<SurfaceId, gfx::Insets> insets_for_reject_;
-  std::map<SurfaceId, gfx::Insets> insets_for_accept_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSurfaceHittestDelegate);
-};
-
-}  // namespace test
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_TEST_SURFACE_HITTEST_TEST_HELPERS_H_
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index e379b84..36af126 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -491,8 +491,7 @@
       compositor->frame_sink_id(), GetHostFrameSinkManager(),
       GetFrameSinkManager(), data->display.get(), data->display_client.get(),
       context_provider, shared_worker_context_provider(),
-      compositor->task_runner(), GetGpuMemoryBufferManager(),
-      features::IsVizHitTestingEnabled());
+      compositor->task_runner(), GetGpuMemoryBufferManager());
   data->display->Resize(compositor->size());
   data->display->SetOutputIsSecure(data->output_is_secure);
   compositor->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc
index 481a73e..1d1c93bc 100644
--- a/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -9,7 +9,6 @@
 #include "components/viz/common/features.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
@@ -214,31 +213,6 @@
   return transformed_point;
 }
 
-bool CrossProcessFrameConnector::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    const viz::SurfaceId& local_surface_id,
-    gfx::PointF* transformed_point) {
-  if (original_surface == local_surface_id) {
-    *transformed_point = point;
-    return true;
-  }
-
-  // Transformations use physical pixels rather than DIP, so conversion
-  // is necessary.
-  *transformed_point =
-      gfx::ConvertPointToPixel(view_->GetDeviceScaleFactor(), point);
-  viz::SurfaceHittest hittest(nullptr,
-                              GetFrameSinkManager()->surface_manager());
-  if (!hittest.TransformPointToTargetSurface(original_surface, local_surface_id,
-                                             transformed_point))
-    return false;
-
-  *transformed_point =
-      gfx::ConvertPointToDIP(view_->GetDeviceScaleFactor(), *transformed_point);
-  return true;
-}
-
 bool CrossProcessFrameConnector::TransformPointToCoordSpaceForView(
     const gfx::PointF& point,
     RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/frame_host/cross_process_frame_connector.h b/content/browser/frame_host/cross_process_frame_connector.h
index 12b07781..0334178 100644
--- a/content/browser/frame_host/cross_process_frame_connector.h
+++ b/content/browser/frame_host/cross_process_frame_connector.h
@@ -86,11 +86,6 @@
   gfx::PointF TransformPointToRootCoordSpace(
       const gfx::PointF& point,
       const viz::SurfaceId& surface_id) override;
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      const viz::SurfaceId& local_surface_id,
-      gfx::PointF* transformed_point) override;
   bool TransformPointToCoordSpaceForView(
       const gfx::PointF& point,
       RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index 1384d8b..73f4e57 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -15,7 +15,6 @@
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
 #include "components/viz/service/surfaces/surface_manager.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/compositor/surface_utils.h"
@@ -240,7 +239,7 @@
     const gfx::PointF& point) {
   viz::SurfaceId surface_id = GetCurrentSurfaceId();
   // LocalSurfaceId is not needed in Viz hit-test.
-  if (!guest_ || (!use_viz_hit_test_ && !surface_id.is_valid())) {
+  if (!guest_) {
     return point;
   }
 
@@ -259,31 +258,6 @@
   return transformed_point;
 }
 
-bool RenderWidgetHostViewGuest::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  viz::SurfaceId surface_id = GetCurrentSurfaceId();
-  *transformed_point = point;
-  if (!guest_ || !surface_id.is_valid())
-    return false;
-
-  if (original_surface == surface_id)
-    return true;
-
-  *transformed_point = gfx::ConvertPointToPixel(GetDeviceScaleFactor(), point);
-  viz::SurfaceHittest hittest(nullptr,
-                              GetFrameSinkManager()->surface_manager());
-  if (!hittest.TransformPointToTargetSurface(original_surface, surface_id,
-                                             transformed_point)) {
-    return false;
-  }
-
-  *transformed_point =
-      gfx::ConvertPointToDIP(GetDeviceScaleFactor(), *transformed_point);
-  return true;
-}
-
 gfx::PointF RenderWidgetHostViewGuest::TransformRootPointToViewCoordSpace(
     const gfx::PointF& point) {
   RenderWidgetHostViewBase* root_rwhv = GetRootView(this);
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h
index 3c568ad..f2c0066 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -79,10 +79,6 @@
   GetTouchSelectionControllerClientManager() override;
   gfx::PointF TransformPointToRootCoordSpaceF(
       const gfx::PointF& point) override;
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point) override;
   gfx::PointF TransformRootPointToViewCoordSpace(
       const gfx::PointF& point) override;
 
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 0c95d9b..c0f7fd52 100644
--- a/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -540,7 +540,12 @@
   DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTest);
 };
 
-IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockImages) {
+#if defined(OS_ANDROID)
+#define MAYBE_BlockImages DISABLED_BlockImages
+#else
+#define MAYBE_BlockImages BlockImages
+#endif
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, MAYBE_BlockImages) {
   embedded_test_server()->StartAcceptingConnections();
 
   // The following are files under content/test/data/site_isolation. All
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 092c679e..e2fcd8d 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -539,7 +539,6 @@
       std::unique_ptr<NavigationRequestInfo> request_info,
       std::unique_ptr<NavigationUIData> navigation_ui_data,
       network::mojom::URLLoaderFactoryPtrInfo factory_for_webui,
-      int frame_tree_node_id,
       bool needs_loader_factory_interceptor,
       base::Time ui_post_time,
       std::string accept_langs) {
@@ -548,10 +547,10 @@
     DCHECK(!started_);
     ui_to_io_time_ += (base::Time::Now() - ui_post_time);
     global_request_id_ = MakeGlobalRequestID();
-    frame_tree_node_id_ = frame_tree_node_id;
+    frame_tree_node_id_ = request_info->frame_tree_node_id;
     started_ = true;
     web_contents_getter_ = base::BindRepeating(
-        &WebContents::FromFrameTreeNodeId, frame_tree_node_id);
+        &WebContents::FromFrameTreeNodeId, frame_tree_node_id_);
     navigation_ui_data_ = std::move(navigation_ui_data);
 
     base::PostTaskWithTraits(
@@ -576,8 +575,12 @@
     // TODO(http://crbug.com/824840): Find out if this is necessary with network
     // service, and make it work on UI thread if so.
     if (resource_request_->request_body && !IsNavigationLoaderOnUIEnabled()) {
-      GetBodyBlobDataHandles(resource_request_->request_body.get(),
-                             resource_context_, &blob_handles_);
+      bool result =
+          GetBodyBlobDataHandles(resource_request_->request_body.get(),
+                                 resource_context_, &blob_handles_);
+      // When network service is enabled, we are not supposed to get blobs
+      // here. See if this causes a crash to verify.
+      CHECK(result && blob_handles_.empty());
     }
 
     StartInternal(
@@ -1752,17 +1755,16 @@
       bypass_redirect_checks, weak_factory_.GetWeakPtr());
   RunOrPostTaskIfNecessary(
       FROM_HERE, GetLoaderRequestControllerThreadID(),
-      base::BindOnce(&URLLoaderRequestController::Start,
-                     base::Unretained(request_controller_.get()),
-                     std::move(network_factory_info),
-                     service_worker_navigation_handle_core,
-                     appcache_handle_core,
-                     std::move(prefetched_signed_exchange_cache),
-                     std::move(signed_exchange_prefetch_metric_recorder),
-                     std::move(request_info), std::move(navigation_ui_data),
-                     std::move(factory_for_webui), frame_tree_node_id,
-                     needs_loader_factory_interceptor, base::Time::Now(),
-                     std::move(accept_langs)));
+      base::BindOnce(
+          &URLLoaderRequestController::Start,
+          base::Unretained(request_controller_.get()),
+          std::move(network_factory_info),
+          service_worker_navigation_handle_core, appcache_handle_core,
+          std::move(prefetched_signed_exchange_cache),
+          std::move(signed_exchange_prefetch_metric_recorder),
+          std::move(request_info), std::move(navigation_ui_data),
+          std::move(factory_for_webui), needs_loader_factory_interceptor,
+          base::Time::Now(), std::move(accept_langs)));
 }
 
 NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
diff --git a/content/browser/native_file_system/native_file_system_directory_handle_impl.cc b/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
index c45d279..4967789 100644
--- a/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
+++ b/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
@@ -78,13 +78,13 @@
   DoRequestPermission(writable, std::move(callback));
 }
 
-void NativeFileSystemDirectoryHandleImpl::GetFile(const std::string& name,
+void NativeFileSystemDirectoryHandleImpl::GetFile(const std::string& basename,
                                                   bool create,
                                                   GetFileCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   storage::FileSystemURL child_url;
-  const base::File::Error file_error = GetChildURL(name, &child_url);
+  const base::File::Error file_error = GetChildURL(basename, &child_url);
   if (file_error != base::File::FILE_OK) {
     std::move(callback).Run(NativeFileSystemError::New(file_error), nullptr);
     return;
@@ -121,13 +121,13 @@
 }
 
 void NativeFileSystemDirectoryHandleImpl::GetDirectory(
-    const std::string& name,
+    const std::string& basename,
     bool create,
     GetDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   storage::FileSystemURL child_url;
-  const base::File::Error file_error = GetChildURL(name, &child_url);
+  const base::File::Error file_error = GetChildURL(basename, &child_url);
   if (file_error != base::File::FILE_OK) {
     std::move(callback).Run(NativeFileSystemError::New(file_error), nullptr);
     return;
@@ -174,14 +174,23 @@
                  base::Owned(new ReadDirectoryState{std::move(callback)})));
 }
 
-void NativeFileSystemDirectoryHandleImpl::Remove(bool recurse,
-                                                 RemoveCallback callback) {
+void NativeFileSystemDirectoryHandleImpl::RemoveEntry(
+    const std::string& basename,
+    bool recurse,
+    RemoveEntryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  storage::FileSystemURL child_url;
+  const base::File::Error file_error = GetChildURL(basename, &child_url);
+  if (file_error != base::File::FILE_OK) {
+    std::move(callback).Run(NativeFileSystemError::New(file_error));
+    return;
+  }
+
   RunWithWritePermission(
-      base::BindOnce(&NativeFileSystemDirectoryHandleImpl::RemoveImpl,
-                     weak_factory_.GetWeakPtr(), recurse),
-      base::BindOnce([](RemoveCallback callback) {
+      base::BindOnce(&NativeFileSystemDirectoryHandleImpl::RemoveEntryImpl,
+                     weak_factory_.GetWeakPtr(), child_url, recurse),
+      base::BindOnce([](RemoveEntryCallback callback) {
         std::move(callback).Run(
             NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED));
       }),
@@ -269,17 +278,17 @@
   }
 
   for (const auto& entry : file_list) {
-    std::string name = storage::FilePathToString(entry.name);
+    std::string basename = storage::FilePathToString(entry.name);
 
     storage::FileSystemURL child_url;
-    const base::File::Error file_error = GetChildURL(name, &child_url);
+    const base::File::Error file_error = GetChildURL(basename, &child_url);
 
     // All entries must exist in this directory as a direct child with a valid
-    // |name|.
+    // |basename|.
     CHECK_EQ(file_error, base::File::FILE_OK);
 
     state->entries.push_back(
-        CreateEntry(name, child_url,
+        CreateEntry(basename, child_url,
                     entry.type == filesystem::mojom::FsFileType::DIRECTORY));
   }
 
@@ -292,39 +301,41 @@
   }
 }
 
-void NativeFileSystemDirectoryHandleImpl::RemoveImpl(bool recurse,
-                                                     RemoveCallback callback) {
+void NativeFileSystemDirectoryHandleImpl::RemoveEntryImpl(
+    const storage::FileSystemURL& url,
+    bool recurse,
+    RemoveEntryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_EQ(GetWritePermissionStatus(),
             blink::mojom::PermissionStatus::GRANTED);
 
   operation_runner()->Remove(
-      url(), recurse,
+      url, recurse,
       base::BindOnce(
-          [](RemoveCallback callback, base::File::Error result) {
+          [](RemoveEntryCallback callback, base::File::Error result) {
             std::move(callback).Run(NativeFileSystemError::New(result));
           },
           std::move(callback)));
 }
 
 base::File::Error NativeFileSystemDirectoryHandleImpl::GetChildURL(
-    const std::string& name,
+    const std::string& basename,
     storage::FileSystemURL* result) {
   // TODO(mek): Rather than doing URL serialization and parsing we should just
   // have a way to get a child FileSystemURL directly from its parent.
 
-  if (name.empty()) {
+  if (basename.empty()) {
     return base::File::FILE_ERROR_NOT_FOUND;
   }
 
-  if (ContainsPathSeparator(name) || IsCurrentOrParentDirectory(name)) {
-    // |name| must refer to a entry that exists in this directory as a direct
-    // child.
+  if (ContainsPathSeparator(basename) || IsCurrentOrParentDirectory(basename)) {
+    // |basename| must refer to a entry that exists in this directory as a
+    // direct child.
     return base::File::FILE_ERROR_SECURITY;
   }
 
   std::string escaped_name =
-      net::EscapeQueryParamValue(name, /*use_plus=*/false);
+      net::EscapeQueryParamValue(basename, /*use_plus=*/false);
 
   GURL parent_url = url().ToGURL();
   std::string path = base::StrCat({parent_url.path(), "/", escaped_name});
@@ -337,7 +348,7 @@
 }
 
 NativeFileSystemEntryPtr NativeFileSystemDirectoryHandleImpl::CreateEntry(
-    const std::string& name,
+    const std::string& basename,
     const storage::FileSystemURL& url,
     bool is_directory) {
   if (is_directory) {
@@ -346,14 +357,14 @@
             manager()
                 ->CreateDirectoryHandle(context(), url, handle_state())
                 .PassInterface()),
-        name);
+        basename);
   }
   return NativeFileSystemEntry::New(
       NativeFileSystemHandle::NewFile(
           manager()
               ->CreateFileHandle(context(), url, handle_state())
               .PassInterface()),
-      name);
+      basename);
 }
 
 base::WeakPtr<NativeFileSystemHandleBase>
diff --git a/content/browser/native_file_system/native_file_system_directory_handle_impl.h b/content/browser/native_file_system/native_file_system_directory_handle_impl.h
index 66ebb08c..590fb545 100644
--- a/content/browser/native_file_system/native_file_system_directory_handle_impl.h
+++ b/content/browser/native_file_system/native_file_system_directory_handle_impl.h
@@ -36,14 +36,16 @@
                            GetPermissionStatusCallback callback) override;
   void RequestPermission(bool writable,
                          RequestPermissionCallback callback) override;
-  void GetFile(const std::string& name,
+  void GetFile(const std::string& basename,
                bool create,
                GetFileCallback callback) override;
-  void GetDirectory(const std::string& name,
+  void GetDirectory(const std::string& basename,
                     bool create,
                     GetDirectoryCallback callback) override;
   void GetEntries(GetEntriesCallback callback) override;
-  void Remove(bool recurse, RemoveCallback callback) override;
+  void RemoveEntry(const std::string& basename,
+                   bool recurse,
+                   RemoveEntryCallback callback) override;
   void Transfer(
       blink::mojom::NativeFileSystemTransferTokenRequest token) override;
 
@@ -71,17 +73,20 @@
       std::vector<filesystem::mojom::DirectoryEntry> file_list,
       bool has_more);
 
-  void RemoveImpl(bool recurse, RemoveCallback callback);
+  void RemoveEntryImpl(const storage::FileSystemURL& url,
+                       bool recurse,
+                       RemoveEntryCallback callback);
 
   // Calculates a FileSystemURL for a (direct) child of this directory with the
-  // given name.  Returns an error when |name| includes invalid input like "/".
-  base::File::Error GetChildURL(const std::string& name,
+  // given basename.  Returns an error when |basename| includes invalid input
+  // like "/".
+  base::File::Error GetChildURL(const std::string& basename,
                                 storage::FileSystemURL* result)
       WARN_UNUSED_RESULT;
 
   // Helper to create a blink::mojom::NativeFileSystemEntry struct.
   blink::mojom::NativeFileSystemEntryPtr CreateEntry(
-      const std::string& name,
+      const std::string& basename,
       const storage::FileSystemURL& url,
       bool is_directory);
 
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index af1e42958..11bceb3a 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -860,7 +860,7 @@
       frame_sink_id_, GetHostFrameSinkManager(), manager, display_.get(),
       nullptr /* display_client */, context_provider,
       nullptr /* worker_context_provider */, task_runner,
-      gpu_memory_buffer_manager, features::IsVizHitTestingEnabled());
+      gpu_memory_buffer_manager);
 
   display_->SetVisible(true);
   display_->Resize(size_);
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 448d0b5..d749f1c 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -24,7 +24,6 @@
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/public/common/content_switches.h"
@@ -187,23 +186,6 @@
   return local_surface_id_.is_valid();
 }
 
-bool DelegatedFrameHost::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
-  if (!surface_id.is_valid() || enable_viz_)
-    return false;
-  *transformed_point = point;
-  if (original_surface == surface_id)
-    return true;
-
-  viz::SurfaceHittest hittest(nullptr,
-                              GetFrameSinkManager()->surface_manager());
-  return hittest.TransformPointToTargetSurface(original_surface, surface_id,
-                                               transformed_point);
-}
-
 void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
   if (enable_viz_) {
     NOTIMPLEMENTED();
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index 5c42110..ef202d7 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -138,15 +138,6 @@
   bool CanCopyFromCompositingSurface() const;
   const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
 
-  // Given the SurfaceID of a Surface that is contained within this class'
-  // Surface, find the relative transform between the Surfaces and apply it
-  // to a point. Returns false if a Surface has not yet been created or if
-  // |original_surface| is not embedded within our current Surface.
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point);
-
   void SetNeedsBeginFrames(bool needs_begin_frames);
   void SetWantsAnimateOnlyBeginFrames();
   void DidNotProduceFrame(const viz::BeginFrameAck& ack);
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc
index 88a2f7e..205fe47 100644
--- a/content/browser/renderer_host/frame_connector_delegate.cc
+++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -58,14 +58,6 @@
   return gfx::PointF();
 }
 
-bool FrameConnectorDelegate::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    const viz::SurfaceId& local_surface_id,
-    gfx::PointF* transformed_point) {
-  return false;
-}
-
 bool FrameConnectorDelegate::TransformPointToCoordSpaceForView(
     const gfx::PointF& point,
     RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/frame_connector_delegate.h b/content/browser/renderer_host/frame_connector_delegate.h
index 91b8859..60125b507 100644
--- a/content/browser/renderer_host/frame_connector_delegate.h
+++ b/content/browser/renderer_host/frame_connector_delegate.h
@@ -119,20 +119,6 @@
       const gfx::PointF& point,
       const viz::SurfaceId& surface_id);
 
-  // Given a point in the coordinate space of a different Surface, transform
-  // it into the coordinate space for this view (corresponding to
-  // local_surface_id).
-  // TransformPointToLocalCoordSpaceLegacy() can only transform points between
-  // surfaces where one is embedded (not necessarily directly) within the
-  // other, and will return false if this is not the case. For points that can
-  // be in sibling surfaces, they must first be converted to the root
-  // surface's coordinate space.
-  virtual bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      const viz::SurfaceId& local_surface_id,
-      gfx::PointF* transformed_point);
-
   // Transform a point into the coordinate space of the root
   // RenderWidgetHostView, for the current view's coordinate space.
   // Returns false if |target_view| and |view_| do not have the same root
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index c235f1d..b1d091d 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -452,29 +452,6 @@
     manager->RemoveHitTestRegionObserver(this);
 }
 
-RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate(
-    const std::unordered_map<viz::SurfaceId, HittestData, viz::SurfaceIdHash>&
-        hittest_data)
-    : hittest_data_(hittest_data) {}
-
-bool RenderWidgetHostInputEventRouter::HittestDelegate::RejectHitTarget(
-    const viz::SurfaceDrawQuad* surface_quad,
-    const gfx::Point& point_in_quad_space) {
-  auto it = hittest_data_.find(surface_quad->surface_range.end());
-  if (it != hittest_data_.end() && it->second.ignored_for_hittest)
-    return true;
-  return false;
-}
-
-bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
-    const viz::SurfaceDrawQuad* surface_quad,
-    const gfx::Point& point_in_quad_space) {
-  auto it = hittest_data_.find(surface_quad->surface_range.end());
-  if (it != hittest_data_.end() && !it->second.ignored_for_hittest)
-    return true;
-  return false;
-}
-
 RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
     : last_mouse_move_target_(nullptr),
       last_mouse_move_root_view_(nullptr),
@@ -482,7 +459,6 @@
       last_device_scale_factor_(1.f),
       active_touches_(0),
       event_targeter_(std::make_unique<RenderWidgetTargeter>(this)),
-      use_viz_hit_test_(features::IsVizHitTestingEnabled()),
       touch_event_ack_queue_(new TouchEventAckQueue(this)),
       weak_ptr_factory_(this) {
   viz::HostFrameSinkManager* manager = GetHostFrameSinkManager();
@@ -592,50 +568,37 @@
   viz::FrameSinkId frame_sink_id;
   bool query_renderer = false;
   bool should_verify_result = false;
-  if (use_viz_hit_test_) {
-    viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
-                                               root_view->GetRootFrameSinkId());
-    if (!query) {
-      *transformed_point = point;
-      return {root_view, false, *transformed_point, false, false};
-    }
-    float device_scale_factor = root_view->GetDeviceScaleFactor();
-    DCHECK_GT(device_scale_factor, 0.0f);
-    gfx::PointF point_in_pixels =
-        gfx::ConvertPointToPixel(device_scale_factor, point);
-    viz::Target target = query->FindTargetForLocationStartingFrom(
-        source, point_in_pixels, root_view->GetFrameSinkId());
-    frame_sink_id = target.frame_sink_id;
-    if (frame_sink_id.is_valid()) {
-      *transformed_point = gfx::ConvertPointToDIP(device_scale_factor,
-                                                  target.location_in_target);
-    } else {
-      *transformed_point = point;
-    }
-    // To ensure the correctness of viz hit testing with cc generated data, we
-    // verify hit test results when:
-    // a) We use cc generated data to do synchronous hit testing and
-    // b) We use HitTestQuery to find the target (instead of reusing previous
-    // targets when hit testing latched events) and
-    // c) We are not hit testing MouseMove events which is too frequent to
-    // verify it without impacting performance.
-    // The code that implements c) locates in |FindMouseEventTarget|.
-    if (target.flags & viz::HitTestRegionFlags::kHitTestAsk)
-      query_renderer = true;
-    else if (features::IsVizHitTestingSurfaceLayerEnabled())
-      should_verify_result = true;
-  } else {
-    // The hittest delegate is used to reject hittesting quads based on extra
-    // hittesting data send by the renderer.
-    HittestDelegate delegate(hittest_data_);
-
-    // The conversion of point to transform_point is done over the course of the
-    // hit testing, and reflect transformations that would normally be applied
-    // in the renderer process if the event was being routed between frames
-    // within a single process with only one RenderWidgetHost.
-    frame_sink_id = root_view->FrameSinkIdAtPoint(
-        &delegate, point, transformed_point, &query_renderer);
+  viz::HitTestQuery* query = GetHitTestQuery(GetHostFrameSinkManager(),
+                                             root_view->GetRootFrameSinkId());
+  if (!query) {
+    *transformed_point = point;
+    return {root_view, false, *transformed_point, false, false};
   }
+  float device_scale_factor = root_view->GetDeviceScaleFactor();
+  DCHECK_GT(device_scale_factor, 0.0f);
+  gfx::PointF point_in_pixels =
+      gfx::ConvertPointToPixel(device_scale_factor, point);
+  viz::Target target = query->FindTargetForLocationStartingFrom(
+      source, point_in_pixels, root_view->GetFrameSinkId());
+  frame_sink_id = target.frame_sink_id;
+  if (frame_sink_id.is_valid()) {
+    *transformed_point =
+        gfx::ConvertPointToDIP(device_scale_factor, target.location_in_target);
+  } else {
+    *transformed_point = point;
+  }
+  // To ensure the correctness of viz hit testing with cc generated data, we
+  // verify hit test results when:
+  // a) We use cc generated data to do synchronous hit testing and
+  // b) We use HitTestQuery to find the target (instead of reusing previous
+  // targets when hit testing latched events) and
+  // c) We are not hit testing MouseMove events which is too frequent to
+  // verify it without impacting performance.
+  // The code that implements c) locates in |FindMouseEventTarget|.
+  if (target.flags & viz::HitTestRegionFlags::kHitTestAsk)
+    query_renderer = true;
+  else if (features::IsVizHitTestingSurfaceLayerEnabled())
+    should_verify_result = true;
 
   auto* view = FindViewFromFrameSinkId(frame_sink_id);
   // Send the event to |root_view| if |view| is not in |root_view|'s sub-tree
@@ -1766,14 +1729,6 @@
 
 bool RenderWidgetHostInputEventRouter::ShouldContinueHitTesting(
     RenderWidgetHostViewBase* target_view) const {
-  // TODO(kenrb): It would be better if we could determine if the
-  // event's point has a chance of hitting an embedded child and returning
-  // false if not, but Viz hit testing does not easily support that. This
-  // currently assumes any embedded view could potentially be the event
-  // target.
-  if (!use_viz_hit_test_)
-    return true;
-
   // Determine if |view| has any embedded children that could potentially
   // receive the event.
   auto* widget_host =
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index df0f636..4de25f4 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -18,7 +18,6 @@
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/host/hit_test/hit_test_query.h"
 #include "components/viz/host/hit_test/hit_test_region_observer.h"
-#include "components/viz/service/surfaces/surface_hittest_delegate.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/browser/renderer_host/input/touch_emulator_client.h"
 #include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
@@ -195,20 +194,6 @@
     bool ignored_for_hittest;
   };
 
-  class HittestDelegate : public viz::SurfaceHittestDelegate {
-   public:
-    HittestDelegate(const std::unordered_map<viz::SurfaceId,
-                                             HittestData,
-                                             viz::SurfaceIdHash>& hittest_data);
-    bool RejectHitTarget(const viz::SurfaceDrawQuad* surface_quad,
-                         const gfx::Point& point_in_quad_space) override;
-    bool AcceptHitTarget(const viz::SurfaceDrawQuad* surface_quad,
-                         const gfx::Point& point_in_quad_space) override;
-
-    const std::unordered_map<viz::SurfaceId, HittestData, viz::SurfaceIdHash>&
-        hittest_data_;
-  };
-
   using FrameSinkIdOwnerMap = std::unordered_map<viz::FrameSinkId,
                                                  RenderWidgetHostViewBase*,
                                                  viz::FrameSinkIdHash>;
@@ -427,7 +412,6 @@
       hittest_data_;
 
   std::unique_ptr<RenderWidgetTargeter> event_targeter_;
-  bool use_viz_hit_test_ = false;
   bool events_being_flushed_ = false;
 
   std::unique_ptr<TouchEmulator> touch_emulator_;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 030ed61..e398fc58 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -132,17 +132,6 @@
       : TestRenderWidgetHostView(rwh) {}
   ~MockRootRenderWidgetHostView() override = default;
 
-  viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate*,
-                                      const gfx::PointF&,
-                                      gfx::PointF*,
-                                      bool* query_renderer) override {
-    if (force_query_renderer_on_hit_test_)
-      *query_renderer = true;
-    DCHECK(current_hittest_result_)
-        << "Must set a Hittest result before calling this function";
-    return current_hittest_result_->GetFrameSinkId();
-  }
-
   bool TransformPointToCoordSpaceForView(
       const gfx::PointF& point,
       RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index a798653..d392b81 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -36,7 +36,6 @@
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
 #include "content/browser/accessibility/web_contents_accessibility_android.h"
 #include "content/browser/android/content_feature_list.h"
@@ -746,37 +745,6 @@
                                : viz::SurfaceId();
 }
 
-bool RenderWidgetHostViewAndroid::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  if (!delegated_frame_host_)
-    return false;
-
-  float scale_factor = view_.GetDipScale();
-  DCHECK_GT(scale_factor, 0);
-  // Transformations use physical pixels rather than DIP, so conversion
-  // is necessary.
-  gfx::PointF point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
-
-  viz::SurfaceId surface_id = delegated_frame_host_->SurfaceId();
-  if (!surface_id.is_valid())
-    return false;
-
-  if (original_surface == surface_id)
-    return true;
-
-  *transformed_point = point_in_pixels;
-  viz::SurfaceHittest hittest(nullptr,
-                              GetFrameSinkManager()->surface_manager());
-  if (!hittest.TransformPointToTargetSurface(original_surface, surface_id,
-                                             transformed_point))
-    return false;
-
-  *transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
-  return true;
-}
-
 bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView(
     const gfx::PointF& point,
     RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 6c689f62..5fd34c3 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -176,10 +176,6 @@
   void SetNeedsBeginFrames(bool needs_begin_frames) override;
   void SetWantsAnimateOnlyBeginFrames() override;
   const viz::FrameSinkId& GetFrameSinkId() const override;
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point) override;
   viz::FrameSinkId GetRootFrameSinkId() override;
   viz::SurfaceId GetCurrentSurfaceId() const override;
   bool TransformPointToCoordSpaceForView(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index aec7d21..b1a4cbc 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1722,25 +1722,6 @@
   event_handler_->OnMouseEvent(event);
 }
 
-bool RenderWidgetHostViewAura::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  // Transformations use physical pixels rather than DIP, so conversion
-  // is necessary.
-  gfx::PointF point_in_pixels =
-      gfx::ConvertPointToPixel(device_scale_factor_, point);
-  // TODO: this shouldn't be used with aura-mus, so that the null check so
-  // go away and become a DCHECK.
-  if (delegated_frame_host_ &&
-      !delegated_frame_host_->TransformPointToLocalCoordSpaceLegacy(
-          point_in_pixels, original_surface, transformed_point))
-    return false;
-  *transformed_point =
-      gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
-  return true;
-}
-
 bool RenderWidgetHostViewAura::HasFallbackSurface() const {
   return delegated_frame_host_ && delegated_frame_host_->HasFallbackSurface();
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 86a98b25..1521774 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -182,10 +182,6 @@
   const viz::FrameSinkId& GetFrameSinkId() const override;
   const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
       const override;
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point) override;
   bool TransformPointToCoordSpaceForView(
       const gfx::PointF& point,
       RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 23912e8..cd8d45ce 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -11,7 +11,6 @@
 #include "components/viz/common/features.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "components/viz/service/surfaces/surface_hittest.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/frame_host/render_widget_host_view_guest.h"
@@ -43,9 +42,7 @@
 namespace content {
 
 RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
-    : use_viz_hit_test_(features::IsVizHitTestingEnabled()),
-      host_(RenderWidgetHostImpl::From(host)),
-      weak_factory_(this) {
+    : host_(RenderWidgetHostImpl::From(host)), weak_factory_(this) {
   host_->render_frame_metadata_provider()->AddObserver(this);
 }
 
@@ -630,42 +627,6 @@
   return false;
 }
 
-viz::FrameSinkId RenderWidgetHostViewBase::FrameSinkIdAtPoint(
-    viz::SurfaceHittestDelegate* delegate,
-    const gfx::PointF& point,
-    gfx::PointF* transformed_point,
-    bool* out_query_renderer) {
-  float device_scale_factor = ui::GetScaleFactorForNativeView(GetNativeView());
-  DCHECK(device_scale_factor != 0.0f);
-
-  // The surface hittest happens in device pixels, so we need to convert the
-  // |point| from DIPs to pixels before hittesting.
-  gfx::PointF point_in_pixels =
-      gfx::ConvertPointToPixel(device_scale_factor, point);
-  viz::SurfaceId surface_id = GetCurrentSurfaceId();
-  if (!surface_id.is_valid()) {
-    // Force a query of the renderer if we don't have a surface id yet.
-    *out_query_renderer = true;
-    return GetFrameSinkId();
-  }
-  viz::SurfaceHittest hittest(delegate,
-                              GetFrameSinkManager()->surface_manager());
-  gfx::Transform target_transform;
-  viz::SurfaceId target_local_surface_id = hittest.GetTargetSurfaceAtPoint(
-      surface_id, gfx::ToFlooredPoint(point_in_pixels), &target_transform,
-      out_query_renderer);
-  *transformed_point = point_in_pixels;
-  if (target_local_surface_id.is_valid()) {
-    target_transform.TransformPoint(transformed_point);
-  }
-  *transformed_point =
-      gfx::ConvertPointToDIP(device_scale_factor, *transformed_point);
-  // It is possible that the renderer has not yet produced a surface, in which
-  // case we return our current FrameSinkId.
-  auto frame_sink_id = target_local_surface_id.frame_sink_id();
-  return frame_sink_id.is_valid() ? frame_sink_id : GetFrameSinkId();
-}
-
 void RenderWidgetHostViewBase::ProcessMouseEvent(
     const blink::WebMouseEvent& event,
     const ui::LatencyInfo& latency) {
@@ -714,26 +675,6 @@
   return point;
 }
 
-bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  if (use_viz_hit_test_) {
-    return TransformPointToLocalCoordSpaceViz(point, original_surface,
-                                              transformed_point);
-  }
-  return TransformPointToLocalCoordSpaceLegacy(point, original_surface,
-                                               transformed_point);
-}
-
-bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  *transformed_point = point;
-  return true;
-}
-
 bool RenderWidgetHostViewBase::TransformPointToCoordSpaceForView(
     const gfx::PointF& point,
     RenderWidgetHostViewBase* target_view,
@@ -861,7 +802,6 @@
     RenderWidgetHostViewBase* target_view,
     const gfx::PointF& point,
     gfx::PointF* transformed_point) const {
-  DCHECK(use_viz_hit_test_);
   DCHECK(original_view);
   DCHECK(target_view);
   viz::FrameSinkId root_frame_sink_id = original_view->GetRootFrameSinkId();
@@ -921,8 +861,6 @@
     return true;
   }
 
-  if (!use_viz_hit_test_)
-    return false;
   viz::FrameSinkId root_frame_sink_id = GetRootFrameSinkId();
   if (!root_frame_sink_id.is_valid())
     return false;
@@ -970,11 +908,10 @@
   return true;
 }
 
-bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceViz(
+bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
     const gfx::PointF& point,
     const viz::SurfaceId& original_surface,
     gfx::PointF* transformed_point) {
-  DCHECK(use_viz_hit_test_);
   viz::FrameSinkId original_frame_sink_id = original_surface.frame_sink_id();
   viz::FrameSinkId target_frame_sink_id = GetFrameSinkId();
   if (!original_frame_sink_id.is_valid() || !target_frame_sink_id.is_valid())
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 11cd489..5bac450f 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -63,10 +63,6 @@
 struct DidOverscrollParams;
 }
 
-namespace viz {
-class SurfaceHittestDelegate;
-}
-
 namespace content {
 
 class BrowserAccessibilityDelegate;
@@ -345,21 +341,6 @@
   // page during the 500 milliseconds prior to the event.
   virtual bool ScreenRectIsUnstableFor(const blink::WebInputEvent& event);
 
-  // When there are multiple RenderWidgetHostViews for a single page, input
-  // events need to be targeted to the correct one for handling. The following
-  // methods are invoked on the RenderWidgetHostView that should be able to
-  // properly handle the event (i.e. it has focus for keyboard events, or has
-  // been identified by hit testing mouse, touch or gesture events).
-  // |out_query_renderer| is set if there is low confidence in the hit test
-  // result which means that renderer process hit testing could potentially
-  // give a different result. In that case the returned FrameSinkId and
-  // transformed point should be ignored.
-  virtual viz::FrameSinkId FrameSinkIdAtPoint(
-      viz::SurfaceHittestDelegate* delegate,
-      const gfx::PointF& point,
-      gfx::PointF* transformed_point,
-      bool* out_query_renderer);
-
   virtual void PreProcessMouseEvent(const blink::WebMouseEvent& event) {}
   virtual void PreProcessTouchEvent(const blink::WebTouchEvent& event) {}
 
@@ -387,11 +368,6 @@
                                        const viz::SurfaceId& original_surface,
                                        gfx::PointF* transformed_point);
 
-  // This is deprecated, and will be removed once Viz hit-test is the default.
-  virtual bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point);
   // Given a RenderWidgetHostViewBase that renders to a Surface that is
   // contained within this class' Surface, find the relative transform between
   // the Surfaces and apply it to a point. Returns false if a Surface has not
@@ -621,9 +597,6 @@
 
   virtual bool HasFallbackSurface() const;
 
-  // Cached bool to test if the VizHitTesting feature is enabled.
-  const bool use_viz_hit_test_;
-
   // The model object. Members will become private when
   // RenderWidgetHostViewGuest is removed.
   RenderWidgetHostImpl* host_;
@@ -690,13 +663,6 @@
                                         const gfx::PointF& point,
                                         gfx::PointF* transformed_point) const;
 
-  // Used to transform |point| when Viz hit-test is enabled.
-  // TransformPointToLocalCoordSpaceLegacy is used in non-Viz hit-testing.
-  bool TransformPointToLocalCoordSpaceViz(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point);
-
   bool view_stopped_flinging_for_test() const {
     return view_stopped_flinging_for_test_;
   }
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 1eaeb082..6beba9c32 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -743,33 +743,20 @@
     const gfx::PointF& point) {
   viz::SurfaceId surface_id = GetCurrentSurfaceId();
   // LocalSurfaceId is not needed in Viz hit-test.
-  if (!frame_connector_ || (!use_viz_hit_test_ && !surface_id.is_valid())) {
+  if (!frame_connector_) {
     return point;
   }
 
   return frame_connector_->TransformPointToRootCoordSpace(point, surface_id);
 }
 
-bool RenderWidgetHostViewChildFrame::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  *transformed_point = point;
-  viz::SurfaceId surface_id = GetCurrentSurfaceId();
-  if (!frame_connector_ || !surface_id.is_valid())
-    return false;
-
-  return frame_connector_->TransformPointToLocalCoordSpaceLegacy(
-      point, original_surface, surface_id, transformed_point);
-}
-
 bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView(
     const gfx::PointF& point,
     RenderWidgetHostViewBase* target_view,
     gfx::PointF* transformed_point) {
   viz::SurfaceId surface_id = GetCurrentSurfaceId();
   // LocalSurfaceId is not needed in Viz hit-test.
-  if (!frame_connector_ || (!use_viz_hit_test_ && !surface_id.is_valid())) {
+  if (!frame_connector_) {
     return false;
   }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 2658bd9..f79c952a 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -148,10 +148,6 @@
   bool HasSize() const override;
   gfx::PointF TransformPointToRootCoordSpaceF(
       const gfx::PointF& point) override;
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point) override;
   bool TransformPointToCoordSpaceForView(
       const gfx::PointF& point,
       RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 0eeacea..901bf009 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -207,10 +207,6 @@
   void InjectTouchEvent(const blink::WebTouchEvent& event,
                         const ui::LatencyInfo& latency_info);
 
-  bool TransformPointToLocalCoordSpaceLegacy(
-      const gfx::PointF& point,
-      const viz::SurfaceId& original_surface,
-      gfx::PointF* transformed_point) override;
   bool TransformPointToCoordSpaceForView(
       const gfx::PointF& point,
       RenderWidgetHostViewBase* target_view,
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index ac6ce63..66edee6 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1274,22 +1274,6 @@
   }
 }
 
-bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpaceLegacy(
-    const gfx::PointF& point,
-    const viz::SurfaceId& original_surface,
-    gfx::PointF* transformed_point) {
-  // Transformations use physical pixels rather than DIP, so conversion
-  // is necessary.
-  float scale_factor = display_.device_scale_factor();
-  gfx::PointF point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
-  if (!browser_compositor_->GetDelegatedFrameHost()
-           ->TransformPointToLocalCoordSpaceLegacy(
-               point_in_pixels, original_surface, transformed_point))
-    return false;
-  *transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
-  return true;
-}
-
 bool RenderWidgetHostViewMac::HasFallbackSurface() const {
   return browser_compositor_->GetDelegatedFrameHost()->HasFallbackSurface();
 }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index de6d513..41fdfe17 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -14067,20 +14067,6 @@
 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
 namespace {
 
-class SitePerProcessDoubleTapZoomBrowserTest
-    : public SitePerProcessBrowserTest {
- public:
-  SitePerProcessDoubleTapZoomBrowserTest() {}
-
- protected:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    SitePerProcessBrowserTest::SetUpCommandLine(command_line);
-    feature_list_.InitAndEnableFeature(features::kEnableVizHitTestDrawQuad);
-  }
-
-  base::test::ScopedFeatureList feature_list_;
-};
-
 void EnableDoubleTapZoomInRenderView(FrameTreeNode* node) {
   content::RenderViewHost* rvh =
       node->current_frame_host()->GetRenderViewHost();
@@ -14093,7 +14079,7 @@
 
 }  // namespace
 
-IN_PROC_BROWSER_TEST_F(SitePerProcessDoubleTapZoomBrowserTest,
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
                        TouchscreenAnimateDoubleTapZoomInOOPIF) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index e08c81b..0836dcd 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -718,15 +718,12 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     SitePerProcessBrowserTest::SetUpCommandLine(command_line);
     ui::PlatformEventSource::SetIgnoreNativePlatformEvents(true);
-    const char kParam[] = "provider";
-    std::map<std::string, std::string> parameters;
     if (std::get<0>(GetParam()) == HitTestType::kDrawQuad) {
-      parameters[kParam] = "draw_quad";
+      // Default enabled.
     } else if (std::get<0>(GetParam()) == HitTestType::kSurfaceLayer) {
-      parameters[kParam] = "surface_layer";
+      feature_list_.InitAndEnableFeature(
+          features::kEnableVizHitTestSurfaceLayer);
     }
-    feature_list_.InitAndEnableFeatureWithParameters(
-        features::kEnableVizHitTest, parameters);
   }
 
   base::test::ScopedFeatureList feature_list_;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index a5789b16..0d6c71a 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -589,7 +589,7 @@
 
 // Enable garbage collection of WebAssembly code.
 const base::Feature kWebAssemblyCodeGC{"WebAssemblyCodeGC",
-                                       base::FEATURE_DISABLED_BY_DEFAULT};
+                                       base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable WebAssembly SIMD
 // https://github.com/WebAssembly/Simd
diff --git a/content/renderer/fetchers/associated_resource_fetcher_impl.cc b/content/renderer/fetchers/associated_resource_fetcher_impl.cc
index 34ad36e..0a53fe13 100644
--- a/content/renderer/fetchers/associated_resource_fetcher_impl.cc
+++ b/content/renderer/fetchers/associated_resource_fetcher_impl.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/strings/string_util.h"
-#include "base/time/time.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_http_body.h"
 #include "third_party/blink/public/platform/web_string.h"
diff --git a/content/renderer/fetchers/associated_resource_fetcher_impl.h b/content/renderer/fetchers/associated_resource_fetcher_impl.h
index ffba6454..d7846a7b 100644
--- a/content/renderer/fetchers/associated_resource_fetcher_impl.h
+++ b/content/renderer/fetchers/associated_resource_fetcher_impl.h
@@ -11,7 +11,6 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/timer/timer.h"
 #include "content/public/renderer/associated_resource_fetcher.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/public/web/web_associated_url_loader_options.h"
@@ -58,9 +57,6 @@
   // Request to send.
   blink::WebURLRequest request_;
 
-  // Limit how long to wait for the server.
-  base::OneShotTimer timeout_timer_;
-
   DISALLOW_COPY_AND_ASSIGN(AssociatedResourceFetcherImpl);
 };
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 7b26dcde..d2e9ecbb 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -715,6 +715,7 @@
 crbug.com/696345 [ no-angle linux amd-0x6613 ] conformance2/transform_feedback/switching-objects.html [ Failure ]
 crbug.com/851159 [ linux amd-0x6613 ] conformance2/buffers/get-buffer-sub-data-validity.html [ Failure ]
 crbug.com/913301 [ linux amd-0x6613 ] conformance2/textures/misc/generate-mipmap-with-large-base-level.html [ Failure ]
+crbug.com/809237 [ linux amd-0x6613 ] conformance2/uniforms/incompatible-texture-type-for-sampler.html [ Skip ]
 
 ####################
 # Android failures #
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index e22fbbd..109a007 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -67,8 +67,6 @@
         "android/gvr/gvr_gamepad_data_fetcher.cc",
         "android/gvr/gvr_gamepad_data_fetcher.h",
         "android/gvr/gvr_gamepad_data_provider.h",
-        "android/gvr/vr_module_delegate.cc",
-        "android/gvr/vr_module_delegate.h",
       ]
 
       if (enable_arcore) {
diff --git a/device/vr/android/gvr/gvr_device.cc b/device/vr/android/gvr/gvr_device.cc
index 2a2d025..d7ecba3 100644
--- a/device/vr/android/gvr/gvr_device.cc
+++ b/device/vr/android/gvr/gvr_device.cc
@@ -6,6 +6,7 @@
 
 #include <math.h>
 #include <algorithm>
+#include <string>
 #include <utility>
 
 #include "base/android/android_hardware_buffer_compat.h"
@@ -170,10 +171,7 @@
   pending_request_session_callback_ = std::move(callback);
 
   if (!gvr_api_) {
-    int render_process_id = options->render_process_id;
-    int render_frame_id = options->render_frame_id;
-    Init(render_process_id, render_frame_id,
-         base::BindOnce(&GvrDevice::OnInitRequestSessionFinished,
+    Init(base::BindOnce(&GvrDevice::OnInitRequestSessionFinished,
                         base::Unretained(this), std::move(options)));
     return;
   }
@@ -249,12 +247,9 @@
   }
 }
 
-void GvrDevice::EnsureInitialized(int render_process_id,
-                                  int render_frame_id,
-                                  EnsureInitializedCallback callback) {
-  Init(render_process_id, render_frame_id,
-       base::BindOnce([](EnsureInitializedCallback callback,
-                         bool success) { std::move(callback).Run(); },
+void GvrDevice::EnsureInitialized(EnsureInitializedCallback callback) {
+  Init(base::BindOnce([](EnsureInitializedCallback callback,
+                         bool) { std::move(callback).Run(); },
                       std::move(callback)));
 }
 
@@ -275,36 +270,7 @@
   OnActivate(reason, std::move(on_handled));
 }
 
-void GvrDevice::Init(int render_process_id,
-                     int render_frame_id,
-                     base::OnceCallback<void(bool)> on_finished) {
-  if (!module_delegate_) {
-    VrModuleDelegateFactory* factory = VrModuleDelegateFactory::Get();
-    if (factory) {
-      module_delegate_ =
-          factory->CreateDelegate(render_process_id, render_frame_id);
-    }
-  }
-
-  if (!module_delegate_) {
-    std::move(on_finished).Run(false);
-    return;
-  }
-  if (!module_delegate_->ModuleInstalled()) {
-    module_delegate_->InstallModule(
-        base::BindOnce(&GvrDevice::OnVrModuleInstalled,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(on_finished)));
-    return;
-  }
-  OnVrModuleInstalled(std::move(on_finished), true);
-}
-
-void GvrDevice::OnVrModuleInstalled(base::OnceCallback<void(bool)> on_finished,
-                                    bool success) {
-  if (!success) {
-    std::move(on_finished).Run(false);
-    return;
-  }
+void GvrDevice::Init(base::OnceCallback<void(bool)> on_finished) {
   GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
   if (!delegate_provider || delegate_provider->ShouldDisableGvrDevice()) {
     std::move(on_finished).Run(false);
diff --git a/device/vr/android/gvr/gvr_device.h b/device/vr/android/gvr/gvr_device.h
index 875a272..ae8d803f 100644
--- a/device/vr/android/gvr/gvr_device.h
+++ b/device/vr/android/gvr/gvr_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_VR_ANDROID_GVR_DEVICE_H
-#define DEVICE_VR_ANDROID_GVR_DEVICE_H
+#ifndef DEVICE_VR_ANDROID_GVR_GVR_DEVICE_H_
+#define DEVICE_VR_ANDROID_GVR_GVR_DEVICE_H_
 
 #include <jni.h>
 
@@ -11,7 +11,6 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
-#include "device/vr/android/gvr/vr_module_delegate.h"
 #include "device/vr/vr_device_base.h"
 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
 
@@ -31,9 +30,7 @@
       mojom::XRRuntime::RequestSessionCallback callback) override;
   void PauseTracking() override;
   void ResumeTracking() override;
-  void EnsureInitialized(int render_process_id,
-                         int render_frame_id,
-                         EnsureInitializedCallback callback) override;
+  void EnsureInitialized(EnsureInitializedCallback callback) override;
 
   void OnDisplayConfigurationChanged(
       JNIEnv* env,
@@ -55,11 +52,7 @@
   void StopPresenting();
   GvrDelegateProvider* GetGvrDelegateProvider();
 
-  void Init(int render_process_id,
-            int render_frame_id,
-            base::OnceCallback<void(bool)> on_finished);
-  void OnVrModuleInstalled(base::OnceCallback<void(bool)> on_finished,
-                           bool success);
+  void Init(base::OnceCallback<void(bool)> on_finished);
   void CreateNonPresentingContext();
   void OnInitRequestSessionFinished(
       mojom::XRRuntimeSessionOptionsPtr options,
@@ -72,8 +65,6 @@
 
   mojo::Binding<mojom::XRSessionController> exclusive_controller_binding_;
 
-  std::unique_ptr<VrModuleDelegate> module_delegate_;
-
   mojom::XRRuntime::RequestSessionCallback pending_request_session_callback_;
 
   base::WeakPtrFactory<GvrDevice> weak_ptr_factory_;
@@ -83,4 +74,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_VR_ANDROID_GVR_DEVICE_H
+#endif  // DEVICE_VR_ANDROID_GVR_GVR_DEVICE_H_
diff --git a/device/vr/android/gvr/vr_module_delegate.cc b/device/vr/android/gvr/vr_module_delegate.cc
deleted file mode 100644
index 6d6062e..0000000
--- a/device/vr/android/gvr/vr_module_delegate.cc
+++ /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.
-
-#include "device/vr/android/gvr/vr_module_delegate.h"
-
-namespace device {
-
-namespace {
-// Storing the global factory in a raw pointer - as opposed to e.g. an
-// std::unique_ptr - to avoid adding a static initializer.
-VrModuleDelegateFactory* g_vr_module_delegate_factory = nullptr;
-}  // namespace
-
-// static
-VrModuleDelegateFactory* VrModuleDelegateFactory::Get() {
-  return g_vr_module_delegate_factory;
-}
-
-// static
-void VrModuleDelegateFactory::Set(
-    std::unique_ptr<VrModuleDelegateFactory> factory) {
-  if (g_vr_module_delegate_factory) {
-    delete g_vr_module_delegate_factory;
-  }
-  g_vr_module_delegate_factory = factory.release();
-}
-
-}  // namespace device
diff --git a/device/vr/android/gvr/vr_module_delegate.h b/device/vr/android/gvr/vr_module_delegate.h
deleted file mode 100644
index 5bd6638..0000000
--- a/device/vr/android/gvr/vr_module_delegate.h
+++ /dev/null
@@ -1,52 +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 DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
-#define DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "device/vr/vr_export.h"
-
-namespace device {
-
-// Delegates installation of the VR module.
-class DEVICE_VR_EXPORT VrModuleDelegate {
- public:
-  VrModuleDelegate() = default;
-  virtual ~VrModuleDelegate() = default;
-  // Returns true if the VR module is installed.
-  virtual bool ModuleInstalled() = 0;
-  // Asynchronously requests to install the VR module. |on_finished| is called
-  // after the module install is completed. If |success| is false the module
-  // install failed.
-  virtual void InstallModule(
-      base::OnceCallback<void(bool success)> on_finished) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VrModuleDelegate);
-};
-
-// Create a VR module delegate.
-class DEVICE_VR_EXPORT VrModuleDelegateFactory {
- public:
-  VrModuleDelegateFactory() = default;
-  virtual ~VrModuleDelegateFactory() = default;
-  // Returns the global module delegate factory.
-  static VrModuleDelegateFactory* Get();
-  // Sets the global module delegate factory.
-  static void Set(std::unique_ptr<VrModuleDelegateFactory> factory);
-  // Instantiates a VR module delegate. |render_process_id| and
-  // |render_frame_id| refer to the tab in which to show module install UI.
-  virtual std::unique_ptr<VrModuleDelegate> CreateDelegate(
-      int render_process_id,
-      int render_frame_id) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(VrModuleDelegateFactory);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_VR_ANDROID_GVR_VR_MODULE_DELEGATE_H_
diff --git a/device/vr/oculus/oculus_device.cc b/device/vr/oculus/oculus_device.cc
index 3a3068f..2cf7031 100644
--- a/device/vr/oculus/oculus_device.cc
+++ b/device/vr/oculus/oculus_device.cc
@@ -6,6 +6,7 @@
 
 #include <math.h>
 
+#include <string>
 #include <utility>
 
 #include "base/bind.h"
@@ -180,9 +181,7 @@
   outstanding_session_requests_count_++;
 }
 
-void OculusDevice::EnsureInitialized(int render_process_id,
-                                     int render_frame_id,
-                                     EnsureInitializedCallback callback) {
+void OculusDevice::EnsureInitialized(EnsureInitializedCallback callback) {
   EnsureValidDisplayInfo();
   std::move(callback).Run();
 }
@@ -259,7 +258,7 @@
 }
 
 void OculusDevice::StartOvrSession() {
-  DCHECK(outstanding_session_requests_count_ == 0);
+  DCHECK_EQ(outstanding_session_requests_count_, 0);
   ovrInitParams initParams = {ovrInit_RequestVersion | ovrInit_Invisible,
                               OVR_MINOR_VERSION, NULL, 0, 0};
   ovrResult result = ovr_Initialize(&initParams);
diff --git a/device/vr/oculus/oculus_device.h b/device/vr/oculus/oculus_device.h
index 5134c3bf..a44754a 100644
--- a/device/vr/oculus/oculus_device.h
+++ b/device/vr/oculus/oculus_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_VR_OCULUS_DEVICE_H
-#define DEVICE_VR_OCULUS_DEVICE_H
+#ifndef DEVICE_VR_OCULUS_OCULUS_DEVICE_H_
+#define DEVICE_VR_OCULUS_OCULUS_DEVICE_H_
 
 #include <memory>
 
@@ -24,7 +24,7 @@
       public mojom::IsolatedXRGamepadProviderFactory,
       public mojom::XRCompositorHost {
  public:
-  explicit OculusDevice();
+  OculusDevice();
   ~OculusDevice() override;
 
   static bool IsHwAvailable();
@@ -34,9 +34,7 @@
   void RequestSession(
       mojom::XRRuntimeSessionOptionsPtr options,
       mojom::XRRuntime::RequestSessionCallback callback) override;
-  void EnsureInitialized(int render_process_id,
-                         int render_frame_id,
-                         EnsureInitializedCallback callback) override;
+  void EnsureInitialized(EnsureInitializedCallback callback) override;
   void OnRequestSessionResult(mojom::XRRuntime::RequestSessionCallback callback,
                               bool result,
                               mojom::XRSessionPtr session);
@@ -86,4 +84,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_VR_OCULUS_DEVICE_H
+#endif  // DEVICE_VR_OCULUS_OCULUS_DEVICE_H_
diff --git a/device/vr/openvr/openvr_device.cc b/device/vr/openvr/openvr_device.cc
index 6601036..43a420e 100644
--- a/device/vr/openvr/openvr_device.cc
+++ b/device/vr/openvr/openvr_device.cc
@@ -6,6 +6,8 @@
 
 #include <math.h>
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -55,8 +57,7 @@
      mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3],
      mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3],
      mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3],
-     0.0f,        0.0f,        0.0f,        1.0f
-  );
+     0.0f,        0.0f,        0.0f,        1.0f);
   // clang-format on
 }
 
@@ -215,9 +216,7 @@
   outstanding_session_requests_count_++;
 }
 
-void OpenVRDevice::EnsureInitialized(int render_process_id,
-                                     int render_frame_id,
-                                     EnsureInitializedCallback callback) {
+void OpenVRDevice::EnsureInitialized(EnsureInitializedCallback callback) {
   EnsureValidDisplayInfo();
   std::move(callback).Run();
 }
diff --git a/device/vr/openvr/openvr_device.h b/device/vr/openvr/openvr_device.h
index a71b51e5..f2cd4d4 100644
--- a/device/vr/openvr/openvr_device.h
+++ b/device/vr/openvr/openvr_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_VR_OPENVR_DEVICE_H
-#define DEVICE_VR_OPENVR_DEVICE_H
+#ifndef DEVICE_VR_OPENVR_OPENVR_DEVICE_H_
+#define DEVICE_VR_OPENVR_OPENVR_DEVICE_H_
 
 #include <memory>
 
@@ -37,9 +37,7 @@
   void RequestSession(
       mojom::XRRuntimeSessionOptionsPtr options,
       mojom::XRRuntime::RequestSessionCallback callback) override;
-  void EnsureInitialized(int render_process_id,
-                         int render_frame_id,
-                         EnsureInitializedCallback callback) override;
+  void EnsureInitialized(EnsureInitializedCallback callback) override;
 
   void OnPollingEvents();
 
@@ -90,4 +88,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_VR_OPENVR_DEVICE_H
+#endif  // DEVICE_VR_OPENVR_OPENVR_DEVICE_H_
diff --git a/device/vr/public/mojom/isolated_xr_service.mojom b/device/vr/public/mojom/isolated_xr_service.mojom
index e0a4109..90237de 100644
--- a/device/vr/public/mojom/isolated_xr_service.mojom
+++ b/device/vr/public/mojom/isolated_xr_service.mojom
@@ -73,14 +73,13 @@
   ListenToDeviceChanges(associated XRRuntimeEventListener listener) =>
       (VRDisplayInfo? display_info);
 
-  // Ensure that the runtime has installed all prerequisites, and is ready to
+  // Ensure that the runtime has installed most prerequisites, and is ready to
   // start. May result in updated display info being sent to registered
   // listeners. RequestSession will fail if this hasn't been called.
-  // |render_process_id| and |render_frame_id| are needed to reference the tab
-  // module install UI would be shown in if necessary.
-  // TODO(crbug.com/854655): Remove |render_process_id| and |render_frame_id|
-  // and show module install UI in the browser process.
-  EnsureInitialized(int32 render_process_id, int32 render_frame_id) => ();
+  // NOTE: When crbug.com/980000 is resolved, GvrDevice::EnsureInitialized
+  // won't install GVR runtime; it will be installed in
+  // GvrDevice::RequestSession().
+  EnsureInitialized() => ();
 
   SetListeningForActivate(bool listen_for_activation);
 
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc
index f0be39e..878dee5 100644
--- a/device/vr/vr_device_base.cc
+++ b/device/vr/vr_device_base.cc
@@ -4,6 +4,8 @@
 
 #include "device/vr/vr_device_base.h"
 
+#include <utility>
+
 #include "base/metrics/histogram_functions.h"
 #include "device/vr/vr_device_provider.h"
 
@@ -74,9 +76,7 @@
   OnListeningForActivate(is_listening);
 }
 
-void VRDeviceBase::EnsureInitialized(int render_process_id,
-                                     int render_frame_id,
-                                     EnsureInitializedCallback callback) {
+void VRDeviceBase::EnsureInitialized(EnsureInitializedCallback callback) {
   std::move(callback).Run();
 }
 
diff --git a/device/vr/vr_device_base.h b/device/vr/vr_device_base.h
index 1815026..42efcad 100644
--- a/device/vr/vr_device_base.h
+++ b/device/vr/vr_device_base.h
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_VR_VR_DEVICE_BASE_H
-#define DEVICE_VR_VR_DEVICE_BASE_H
+#ifndef DEVICE_VR_VR_DEVICE_BASE_H_
+#define DEVICE_VR_VR_DEVICE_BASE_H_
+
+#include <memory>
+#include <vector>
 
 #include "base/callback.h"
 #include "base/macros.h"
@@ -28,9 +31,7 @@
       mojom::XRRuntimeEventListenerAssociatedPtrInfo listener,
       mojom::XRRuntime::ListenToDeviceChangesCallback callback) final;
   void SetListeningForActivate(bool is_listening) override;
-  void EnsureInitialized(int render_process_id,
-                         int render_frame_id,
-                         EnsureInitializedCallback callback) override;
+  void EnsureInitialized(EnsureInitializedCallback callback) override;
   void SetInlinePosesEnabled(bool enable) override;
 
   virtual void RequestHitTest(
@@ -86,4 +87,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_VR_VR_DEVICE_BASE_H
+#endif  // DEVICE_VR_VR_DEVICE_BASE_H_
diff --git a/extensions/browser/api/storage/storage_api.cc b/extensions/browser/api/storage/storage_api.cc
index ecc8a46..11b396b8 100644
--- a/extensions/browser/api/storage/storage_api.cc
+++ b/extensions/browser/api/storage/storage_api.cc
@@ -51,6 +51,15 @@
   EXTENSION_FUNCTION_VALIDATE(settings_namespace_ !=
                               settings_namespace::INVALID);
 
+  if (extension()->is_login_screen_extension() &&
+      settings_namespace_ != settings_namespace::MANAGED) {
+    // Login screen extensions are not allowed to use local/sync storage for
+    // security reasons (see crbug.com/978443).
+    return RespondNow(Error(base::StringPrintf(
+        "\"%s\" is not available for login screen extensions",
+        settings_namespace_string.c_str())));
+  }
+
   StorageFrontend* frontend = StorageFrontend::Get(browser_context());
   if (!frontend->IsStorageEnabled(settings_namespace_)) {
     return RespondNow(Error(
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
index 381a00a..eff2ba43 100644
--- a/extensions/common/api/_permission_features.json
+++ b/extensions/common/api/_permission_features.json
@@ -565,11 +565,22 @@
       ]
     }
   ],
-  "storage": {
-    "channel": "stable",
-    "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
-    "min_manifest_version": 2
-  },
+  "storage": [
+    {
+      "channel": "stable",
+      "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
+      "min_manifest_version": 2
+    },
+    {
+      "channel": "dev",
+      "extension_types": ["login_screen_extension"],
+      "min_manifest_version": 2,
+      "whitelist": [
+        "E219EE36A3B40612FD2A8CD6937B03EF0C97D3FE", // Imprivata (login screen)
+        "7FE4A999359A456C4B0FB7B7AD85CEA29CA50519"  // Login screen APIs test extension
+      ]
+    }
+  ],
   "system.cpu": [
     {
       "channel": "stable",
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
index 81e37990..ae98ae1 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -1126,7 +1126,7 @@
           result.Set(v8::Array::New(isolate, 0));
           return;
         }
-        std::vector<ui::LanguageSpan> language_annotation =
+        std::vector<ui::AXLanguageSpan> language_annotation =
             tree->language_info_stats->GetLanguageAnnotationForStringAttribute(
                 *node, attr);
         const std::string& attribute_value = node->GetStringAttribute(attr);
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc
index 76ae971..d7aa381 100644
--- a/google_apis/drive/drive_api_requests.cc
+++ b/google_apis/drive/drive_api_requests.cc
@@ -53,7 +53,6 @@
 const char kMultipartMixedMimeTypePrefix[] = "multipart/mixed; boundary=";
 
 // UMA names.
-const char kUMADriveBatchUploadResponseCode[] = "Drive.BatchUploadResponseCode";
 const char kUMADriveTotalFileCountInBatchUpload[] =
     "Drive.TotalFileCountInBatchUpload";
 const char kUMADriveTotalFileSizeInBatchUpload[] =
@@ -1325,19 +1324,6 @@
     const network::ResourceResponseHead* response_head,
     base::FilePath response_file,
     std::string response_body) {
-  // Return the detailed raw HTTP code if the error code is abstracted
-  // DRIVE_OTHER_ERROR. If HTTP connection is failed and the status code is -1,
-  // return network status error.
-  int histogram_error = 0;
-  if (GetErrorCode() != DRIVE_OTHER_ERROR) {
-    histogram_error = GetErrorCode();
-  } else if (response_head && response_head->headers->response_code() != -1) {
-    histogram_error = response_head->headers->response_code();
-  } else {
-    histogram_error = NetError();
-  }
-  base::UmaHistogramSparse(kUMADriveBatchUploadResponseCode, histogram_error);
-
   if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) {
     RunCallbackOnPrematureFailure(GetErrorCode());
     sender_->RequestFinished(this);
diff --git a/google_apis/gaia/oauth2_access_token_manager.cc b/google_apis/gaia/oauth2_access_token_manager.cc
index f21e8d1..f0964c1 100644
--- a/google_apis/gaia/oauth2_access_token_manager.cc
+++ b/google_apis/gaia/oauth2_access_token_manager.cc
@@ -29,6 +29,16 @@
   return nullptr;
 }
 
+bool OAuth2AccessTokenManager::Delegate::HandleAccessTokenFetch(
+    RequestImpl* request,
+    const CoreAccountId& account_id,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    const std::string& client_id,
+    const std::string& client_secret,
+    const ScopeSet& scopes) {
+  return false;
+}
+
 OAuth2AccessTokenManager::Request::Request() {}
 
 OAuth2AccessTokenManager::Request::~Request() {}
@@ -630,7 +640,14 @@
   if (token_response && token_response->access_token.length()) {
     InformConsumerWithCachedTokenResponse(token_response, request.get(),
                                           request_parameters);
+  } else if (delegate_->HandleAccessTokenFetch(request.get(), account_id,
+                                               url_loader_factory, client_id,
+                                               client_secret, scopes)) {
+    // The delegate handling the fetch request means that we *don't* perform a
+    // fetch.
   } else {
+    // The token isn't in the cache and the delegate isn't fetching it: fetch it
+    // ourselves!
     // TODO(https://crbug.com/967598): Use directly
     // OAuth2AccessTokenManager::FetchOAuth2Token this fully manages access
     // tokens independently of OAuth2TokenService. For now, some tests need to
diff --git a/google_apis/gaia/oauth2_access_token_manager.h b/google_apis/gaia/oauth2_access_token_manager.h
index 6894c6d..7dbd401 100644
--- a/google_apis/gaia/oauth2_access_token_manager.h
+++ b/google_apis/gaia/oauth2_access_token_manager.h
@@ -24,6 +24,7 @@
  public:
   // A set of scopes in OAuth2 authentication.
   typedef std::set<std::string> ScopeSet;
+  class RequestImpl;
 
   class Delegate {
    public:
@@ -49,6 +50,18 @@
     virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
         const;
 
+    // Gives the delegate a chance to handle the access token request before
+    // the manager sends the request over the network. Returns true if the
+    // request was handled by the delegate (in which case the manager will not
+    // send the request) and false otherwise.
+    virtual bool HandleAccessTokenFetch(
+        RequestImpl* request,
+        const CoreAccountId& account_id,
+        scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+        const std::string& client_id,
+        const std::string& client_secret,
+        const ScopeSet& scopes);
+
     // Called when an access token is invalidated.
     virtual void OnAccessTokenInvalidated(const CoreAccountId& account_id,
                                           const std::string& client_id,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 1a30331..5e8cc73 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -2428,7 +2428,7 @@
   context_creation_attribs_.stencil_size = 8;
   context_creation_attribs_.bind_generates_resource = true;
 
-  gl::init::InitializeGLOneOffImplementation(gl::kGLImplementationEGLANGLE,
+  gl::init::InitializeGLOneOffImplementation(gl::kGLImplementationEGLGLES2,
                                              false, false, false, true);
 
   scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo();
diff --git a/gpu/command_buffer/service/gpu_switches.cc b/gpu/command_buffer/service/gpu_switches.cc
index c515c94..e7798d4 100644
--- a/gpu/command_buffer/service/gpu_switches.cc
+++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -6,6 +6,13 @@
 
 #include "base/macros.h"
 
+namespace gpu {
+
+const char kCmdDecoderValidatingName[] = "validating";
+const char kCmdDecoderPassthroughName[] = "passthrough";
+
+}  // namespace gpu
+
 namespace switches {
 
 // Always return success when compiling a shader. Linking will still fail.
@@ -62,6 +69,10 @@
 // round intermediate values in ANGLE.
 const char kEmulateShaderPrecision[] = "emulate-shader-precision";
 
+// Use the Pass-through command decoder, skipping all validation and state
+// tracking.
+const char kUseCmdDecoder[] = "use-cmd-decoder";
+
 // Enable Vulkan support and select Vulkan implementation, must also have
 // ENABLE_VULKAN defined.
 const char kUseVulkan[] = "use-vulkan";
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h
index 9c71810..aa6dfbeb 100644
--- a/gpu/command_buffer/service/gpu_switches.h
+++ b/gpu/command_buffer/service/gpu_switches.h
@@ -10,6 +10,13 @@
 #include "gpu/config/gpu_switches.h"
 #include "gpu/gpu_export.h"
 
+namespace gpu {
+
+// The command decoder names that can be passed to --use-cmd-decoder.
+GPU_EXPORT extern const char kCmdDecoderValidatingName[];
+GPU_EXPORT extern const char kCmdDecoderPassthroughName[];
+}  // namespace gpu
+
 namespace switches {
 
 GPU_EXPORT extern const char kCompileShaderAlwaysSucceeds[];
@@ -28,6 +35,7 @@
 GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[];
 GPU_EXPORT extern const char kGLShaderIntermOutput[];
 GPU_EXPORT extern const char kEmulateShaderPrecision[];
+GPU_EXPORT extern const char kUseCmdDecoder[];
 GPU_EXPORT extern const char kUseVulkan[];
 GPU_EXPORT extern const char kVulkanImplementationNameNative[];
 GPU_EXPORT extern const char kVulkanImplementationNameSwiftshader[];
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index a1ed819..a97c10e 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -11,8 +11,8 @@
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/context_group.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_finch_features.h"
 #include "ui/gl/gl_switches.h"
-#include "ui/gl/gl_utils.h"
 
 #if defined(USE_EGL)
 #include "ui/gl/gl_surface_egl.h"
@@ -86,7 +86,20 @@
 }
 
 bool UsePassthroughCommandDecoder(const base::CommandLine* command_line) {
-  return gl::UsePassthroughCommandDecoder(command_line);
+  std::string switch_value;
+  if (command_line->HasSwitch(switches::kUseCmdDecoder)) {
+    switch_value = command_line->GetSwitchValueASCII(switches::kUseCmdDecoder);
+  }
+
+  if (switch_value == kCmdDecoderPassthroughName) {
+    return true;
+  } else if (switch_value == kCmdDecoderValidatingName) {
+    return false;
+  } else {
+    // Unrecognized or missing switch, use the default.
+    return base::FeatureList::IsEnabled(
+        features::kDefaultPassthroughCommandDecoder);
+  }
 }
 
 bool PassthroughCommandDecoderSupported() {
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index 0ecb375..f3cd14c 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -270,7 +270,6 @@
   switch (gl::GetGLImplementation()) {
 #if !defined(OS_MACOSX)
     case gl::kGLImplementationEGLGLES2:
-    case gl::kGLImplementationEGLANGLE:
       return NativeImageBufferEGL::Create(texture_id);
 #endif
     case gl::kGLImplementationMockGL:
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index f2f66e5..b3d8018 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -319,7 +319,7 @@
     command_line->AppendSwitchASCII(switches::kUseANGLE,
                                     gl::kANGLEImplementationNullName);
     CHECK(gl::init::InitializeGLOneOffImplementation(
-        gl::kGLImplementationEGLANGLE, false, false, false, true));
+        gl::kGLImplementationEGLGLES2, false, false, false, true));
 #elif defined(GPU_FUZZER_USE_SWIFTSHADER)
     command_line->AppendSwitchASCII(switches::kUseGL,
                                     gl::kGLImplementationSwiftShaderName);
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index 7cf3bfd..66675ae1 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -63,6 +63,11 @@
     "DefaultEnableOopRasterization", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+// Use the passthrough command decoder by default.  This can be overridden with
+// the --use-cmd-decoder=passthrough or --use-cmd-decoder=validating flags.
+const base::Feature kDefaultPassthroughCommandDecoder{
+    "DefaultPassthroughCommandDecoder", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Allow putting a video swapchain underneath the main swapchain, so overlays
 // can be used even if there are controls on top of the video. It can be
 // enabled only when overlay is supported.
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index 69bcf71..c222413 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -25,6 +25,8 @@
 
 GPU_EXPORT extern const base::Feature kDefaultEnableOopRasterization;
 
+GPU_EXPORT extern const base::Feature kDefaultPassthroughCommandDecoder;
+
 GPU_EXPORT extern const base::Feature kDirectCompositionUnderlays;
 
 GPU_EXPORT extern const base::Feature kGpuUseDisplayThreadPriority;
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index d396eff..a945e81 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -85,12 +85,12 @@
 
 void InitializePlatformOverlaySettings(GPUInfo* gpu_info) {
 #if defined(OS_WIN)
-  // This has to be called after a context is created, active GPU is identified,
-  // and GPU driver bug workarounds are computed again. Otherwise the workaround
-  // |disable_direct_composition| may not be correctly applied.
-  // Also, this has to be called after falling back to SwiftShader decision is
-  // finalized because this function depends on GL is ANGLE's GLES or not.
-  if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE) {
+// This has to be called after a context is created, active GPU is identified,
+// and GPU driver bug workarounds are computed again. Otherwise the workaround
+// |disable_direct_composition| may not be correctly applied.
+// Also, this has to be called after falling back to SwiftShader decision is
+// finalized because this function depends on GL is ANGLE's GLES or not.
+  if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
     DCHECK(gpu_info);
     gpu_info->direct_composition =
         gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported();
diff --git a/gpu/ipc/service/image_transport_surface_win.cc b/gpu/ipc/service/image_transport_surface_win.cc
index a365852..0b1526c8 100644
--- a/gpu/ipc/service/image_transport_surface_win.cc
+++ b/gpu/ipc/service/image_transport_surface_win.cc
@@ -31,7 +31,7 @@
   scoped_refptr<gl::GLSurface> surface;
   bool override_vsync_for_multi_window_swap = false;
 
-  if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE) {
+  if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) {
     auto vsync_provider =
         std::make_unique<gl::VSyncProviderWin>(surface_handle);
 
diff --git a/gpu/vulkan/demo/vulkan_demo.cc b/gpu/vulkan/demo/vulkan_demo.cc
index 451ae9f5..12bd91e 100644
--- a/gpu/vulkan/demo/vulkan_demo.cc
+++ b/gpu/vulkan/demo/vulkan_demo.cc
@@ -47,8 +47,8 @@
   window_->Show();
 
   // Sync up size between |window_| and |vulkan_surface_|
-  vulkan_surface_->SetSize(size);
-  sk_surfaces_.resize(vulkan_surface_->GetSwapChain()->num_images());
+  vulkan_surface_->Reshape(size, gfx::OVERLAY_TRANSFORM_NONE);
+  sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images());
 }
 
 void VulkanDemo::Destroy() {
@@ -67,15 +67,15 @@
 }
 
 void VulkanDemo::OnBoundsChanged(const gfx::Rect& new_bounds) {
-  if (vulkan_surface_->size() == new_bounds.size())
+  if (vulkan_surface_->image_size() == new_bounds.size())
     return;
-  auto old_size = vulkan_surface_->size();
-  vulkan_surface_->SetSize(new_bounds.size());
-  if (vulkan_surface_->size() != old_size) {
+  auto generation = vulkan_surface_->swap_chain_generation();
+  vulkan_surface_->Reshape(new_bounds.size(), gfx::OVERLAY_TRANSFORM_NONE);
+  if (vulkan_surface_->swap_chain_generation() != generation) {
     // Size has been changed, we need to clear all surfaces which will be
     // recreated later.
     sk_surfaces_.clear();
-    sk_surfaces_.resize(vulkan_surface_->GetSwapChain()->num_images());
+    sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images());
   }
 }
 
@@ -100,7 +100,7 @@
 }
 
 void VulkanDemo::CreateSkSurface() {
-  scoped_write_.emplace(vulkan_surface_->GetSwapChain());
+  scoped_write_.emplace(vulkan_surface_->swap_chain());
   auto& sk_surface = sk_surfaces_[scoped_write_->image_index()];
 
   if (!sk_surface) {
@@ -113,7 +113,7 @@
     vk_image_info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
     vk_image_info.fFormat = VK_FORMAT_B8G8R8A8_UNORM;
     vk_image_info.fLevelCount = 1;
-    const auto& size = vulkan_surface_->size();
+    const auto& size = vulkan_surface_->image_size();
     GrBackendRenderTarget render_target(size.width(), size.height(), 0, 0,
                                         vk_image_info);
     sk_surface = SkSurface::MakeFromBackendRenderTarget(
@@ -139,7 +139,7 @@
   constexpr float kWidth = 800;
   constexpr float kHeight = 600;
 
-  const auto& size = vulkan_surface_->size();
+  const auto& size = vulkan_surface_->image_size();
   canvas->scale(size.width() / kWidth, size.height() / kHeight);
 
   SkPaint paint;
diff --git a/gpu/vulkan/tests/vulkan_test.cc b/gpu/vulkan/tests/vulkan_test.cc
index bceeb2c..b30a4b53 100644
--- a/gpu/vulkan/tests/vulkan_test.cc
+++ b/gpu/vulkan/tests/vulkan_test.cc
@@ -18,7 +18,8 @@
   EXPECT_TRUE(surface);
   EXPECT_TRUE(surface->Initialize(GetDeviceQueue(),
                                   VulkanSurface::DEFAULT_SURFACE_FORMAT));
-  EXPECT_TRUE(surface->SetSize(gfx::Size(100, 100)));
+  EXPECT_TRUE(
+      surface->Reshape(gfx::Size(100, 100), gfx::OVERLAY_TRANSFORM_NONE));
   surface->Destroy();
 }
 
@@ -27,7 +28,8 @@
   ASSERT_TRUE(surface);
   ASSERT_TRUE(surface->Initialize(GetDeviceQueue(),
                                   VulkanSurface::DEFAULT_SURFACE_FORMAT));
-  ASSERT_TRUE(surface->SetSize(gfx::Size(100, 100)));
+  ASSERT_TRUE(
+      surface->Reshape(gfx::Size(100, 100), gfx::OVERLAY_TRANSFORM_NONE));
 
   // First swap is a special case, call it first to get better errors.
   EXPECT_EQ(gfx::SwapResult::SWAP_ACK, surface->SwapBuffers());
diff --git a/gpu/vulkan/vulkan_surface.cc b/gpu/vulkan/vulkan_surface.cc
index c4f703a..273404d 100644
--- a/gpu/vulkan/vulkan_surface.cc
+++ b/gpu/vulkan/vulkan_surface.cc
@@ -26,6 +26,48 @@
     VK_FORMAT_R5G6B5_UNORM_PACK16,  // FORMAT_RGB565,
 };
 
+VkSurfaceTransformFlagBitsKHR ToVkSurfaceTransformFlag(
+    gfx::OverlayTransform transform) {
+  switch (transform) {
+    case gfx::OVERLAY_TRANSFORM_NONE:
+      return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+    case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+      return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
+    case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+      return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+      return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+      return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
+    case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+      return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
+    default:
+      NOTREACHED() << "transform:" << transform;
+      return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+  };
+}
+
+gfx::OverlayTransform FromVkSurfaceTransformFlag(
+    VkSurfaceTransformFlagBitsKHR transform) {
+  switch (transform) {
+    case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_NONE;
+    case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+    case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+    case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+    case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+    case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+      return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+    default:
+      NOTREACHED() << "transform:" << transform;
+      return gfx::OVERLAY_TRANSFORM_INVALID;
+  }
+}
+
 }  // namespace
 
 VulkanSurface::~VulkanSurface() {
@@ -108,7 +150,7 @@
       return false;
     }
   }
-  return CreateSwapChain(gfx::Size());
+  return CreateSwapChain(gfx::Size(), gfx::OVERLAY_TRANSFORM_INVALID);
 }
 
 void VulkanSurface::Destroy() {
@@ -122,19 +164,17 @@
   return swap_chain_->PresentBuffer();
 }
 
-VulkanSwapChain* VulkanSurface::GetSwapChain() {
-  return swap_chain_.get();
-}
-
 void VulkanSurface::Finish() {
   vkQueueWaitIdle(device_queue_->GetVulkanQueue());
 }
 
-bool VulkanSurface::SetSize(const gfx::Size& size) {
-  return CreateSwapChain(size);
+bool VulkanSurface::Reshape(const gfx::Size& size,
+                            gfx::OverlayTransform transform) {
+  return CreateSwapChain(size, transform);
 }
 
-bool VulkanSurface::CreateSwapChain(const gfx::Size& new_size) {
+bool VulkanSurface::CreateSwapChain(const gfx::Size& size,
+                                    gfx::OverlayTransform transform) {
   // Get Surface Information.
   VkSurfaceCapabilitiesKHR surface_caps;
   VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
@@ -145,51 +185,61 @@
     return false;
   }
 
-  // For Android, the current vulkan surface size may not match the new_size
-  // (the current window size), in that case, we will create a swapchain with
-  // the requested new_size, and vulkan surface size should match the swapchain
+  auto vk_transform = transform != gfx::OVERLAY_TRANSFORM_INVALID
+                          ? ToVkSurfaceTransformFlag(transform)
+                          : surface_caps.currentTransform;
+  DCHECK(vk_transform == (vk_transform & surface_caps.supportedTransforms));
+  if (transform == gfx::OVERLAY_TRANSFORM_INVALID)
+    transform = FromVkSurfaceTransformFlag(surface_caps.currentTransform);
+
+  // For Android, the current vulkan surface size may not match the new size
+  // (the current window size), in that case, we will create a swap chain with
+  // the requested new size, and vulkan surface size should match the swapchain
   // images size soon.
-  if (!new_size.IsEmpty()) {
-    DLOG_IF(ERROR,
-            base::checked_cast<int>(surface_caps.currentExtent.width) !=
-                    new_size.width() ||
-                base::checked_cast<int>(surface_caps.currentExtent.height) !=
-                    new_size.height())
-        << "Requested new size doesn't match vulkan surface size.";
-    surface_caps.currentExtent.width = new_size.width();
-    surface_caps.currentExtent.height = new_size.height();
-  } else {
+  gfx::Size image_size = size;
+  if (image_size.IsEmpty()) {
     // If width and height of the surface are 0xFFFFFFFF, it means the surface
     // size will be determined by the extent of a swapchain targeting the
     // surface. In that case, we will use the minImageExtent for the swapchain.
     const uint32_t kUndefinedExtent = 0xFFFFFFFF;
     if (surface_caps.currentExtent.width == kUndefinedExtent &&
         surface_caps.currentExtent.height == kUndefinedExtent) {
-      surface_caps.currentExtent.width = surface_caps.minImageExtent.width;
-      surface_caps.currentExtent.height = surface_caps.minImageExtent.height;
+      image_size.SetSize(surface_caps.minImageExtent.width,
+                         surface_caps.minImageExtent.height);
+    } else {
+      image_size.SetSize(surface_caps.currentExtent.width,
+                         surface_caps.currentExtent.height);
+    }
+    if (transform == gfx::OVERLAY_TRANSFORM_ROTATE_90 ||
+        transform == gfx::OVERLAY_TRANSFORM_ROTATE_270) {
+      image_size.SetSize(image_size.height(), image_size.width());
     }
   }
 
-  DCHECK_GE(surface_caps.currentExtent.width,
+  DCHECK_GE(static_cast<uint32_t>(image_size.width()),
             surface_caps.minImageExtent.width);
-  DCHECK_GE(surface_caps.currentExtent.height,
+  DCHECK_GE(static_cast<uint32_t>(image_size.height()),
             surface_caps.minImageExtent.height);
-  DCHECK_LE(surface_caps.currentExtent.width,
+  DCHECK_LE(static_cast<uint32_t>(image_size.width()),
             surface_caps.maxImageExtent.width);
-  DCHECK_LE(surface_caps.currentExtent.height,
+  DCHECK_LE(static_cast<uint32_t>(image_size.height()),
             surface_caps.maxImageExtent.height);
-  DCHECK_GT(surface_caps.currentExtent.width, 0u);
-  DCHECK_GT(surface_caps.currentExtent.height, 0u);
+  DCHECK_GT(static_cast<uint32_t>(image_size.width()), 0u);
+  DCHECK_GT(static_cast<uint32_t>(image_size.height()), 0u);
 
-  if (size_ == new_size)
+  if (image_size_ == image_size && transform_ == transform)
     return true;
 
-  size_ = new_size;
+  image_size_ = image_size;
+  transform_ = transform;
+
   auto swap_chain = std::make_unique<VulkanSwapChain>();
 
-  // Create Swapchain.
-  if (!swap_chain->Initialize(device_queue_, surface_, surface_caps,
-                              surface_format_, std::move(swap_chain_))) {
+  // Create swap chain.
+  uint32_t min_image_count = std::max(surface_caps.minImageCount, 3u);
+  if (!swap_chain->Initialize(device_queue_, surface_, surface_format_,
+                              image_size_, min_image_count, vk_transform,
+                              std::move(swap_chain_))) {
     return false;
   }
 
diff --git a/gpu/vulkan/vulkan_surface.h b/gpu/vulkan/vulkan_surface.h
index c33a7387..4d24a5e 100644
--- a/gpu/vulkan/vulkan_surface.h
+++ b/gpu/vulkan/vulkan_surface.h
@@ -12,6 +12,7 @@
 #include "gpu/vulkan/vulkan_export.h"
 #include "gpu/vulkan/vulkan_swap_chain.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/overlay_transform.h"
 #include "ui/gfx/swap_result.h"
 
 namespace gpu {
@@ -41,21 +42,25 @@
 
   gfx::SwapResult SwapBuffers();
 
-  VulkanSwapChain* GetSwapChain();
-  uint32_t swap_chain_generation() const { return swap_chain_generation_; }
-
   void Finish();
 
-  virtual bool SetSize(const gfx::Size& size);
+  // Reshape the the surface and recreate swap chian if it is needed. The size
+  // is the current surface (window) size. The transform is the pre transform
+  // relative to the hardware natural orientation, applied to frame content.
+  // See VkSwapchainCreateInfoKHR::preTransform for detail.
+  virtual bool Reshape(const gfx::Size& size, gfx::OverlayTransform transform);
 
-  const gfx::Size& size() const { return size_; }
+  VulkanSwapChain* swap_chain() const { return swap_chain_.get(); }
+  uint32_t swap_chain_generation() const { return swap_chain_generation_; }
+  const gfx::Size& image_size() const { return image_size_; }
+  gfx::OverlayTransform transform() const { return transform_; }
   VkSurfaceFormatKHR surface_format() const { return surface_format_; }
 
  private:
-  bool CreateSwapChain(const gfx::Size& new_size);
+  bool CreateSwapChain(const gfx::Size& size, gfx::OverlayTransform transform);
 
   const VkInstance vk_instance_;
-  gfx::Size size_;
+
   VkSurfaceKHR surface_ = VK_NULL_HANDLE;
   VkSurfaceFormatKHR surface_format_ = {};
   VulkanDeviceQueue* device_queue_ = nullptr;
@@ -63,6 +68,13 @@
   // The generation of |swap_chain_|, it will be increasted if a new
   // |swap_chain_| is created due to resizing, etec.
   uint32_t swap_chain_generation_ = 0u;
+
+  // Swap chain image size.
+  gfx::Size image_size_;
+
+  // Swap chain pre-transform.
+  gfx::OverlayTransform transform_ = gfx::OVERLAY_TRANSFORM_INVALID;
+
   std::unique_ptr<VulkanSwapChain> swap_chain_;
 
   DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
diff --git a/gpu/vulkan/vulkan_swap_chain.cc b/gpu/vulkan/vulkan_swap_chain.cc
index c73853c..c600a3ea 100644
--- a/gpu/vulkan/vulkan_swap_chain.cc
+++ b/gpu/vulkan/vulkan_swap_chain.cc
@@ -39,15 +39,18 @@
 bool VulkanSwapChain::Initialize(
     VulkanDeviceQueue* device_queue,
     VkSurfaceKHR surface,
-    const VkSurfaceCapabilitiesKHR& surface_caps,
     const VkSurfaceFormatKHR& surface_format,
+    const gfx::Size& image_size,
+    uint32_t min_image_count,
+    VkSurfaceTransformFlagBitsKHR pre_transform,
     std::unique_ptr<VulkanSwapChain> old_swap_chain) {
   DCHECK(device_queue);
   device_queue_ = device_queue;
   device_queue_->GetFenceHelper()->ProcessCleanupTasks();
-  return InitializeSwapChain(surface, surface_caps, surface_format,
+  return InitializeSwapChain(surface, surface_format, image_size,
+                             min_image_count, pre_transform,
                              std::move(old_swap_chain)) &&
-         InitializeSwapImages(surface_caps, surface_format);
+         InitializeSwapImages(surface_format);
 }
 
 void VulkanSwapChain::Destroy() {
@@ -104,6 +107,8 @@
     DLOG(ERROR) << "vkQueuePresentKHR() failed: " << result;
     return gfx::SwapResult::SWAP_FAILED;
   }
+  DLOG_IF(ERROR, result == VK_SUBOPTIMAL_KHR) << "Swapchian is suboptimal.";
+
   acquired_image_.reset();
   fence_helper->EnqueueSemaphoreCleanupForSubmittedWork(end_write_semaphore_);
   end_write_semaphore_ = VK_NULL_HANDLE;
@@ -113,8 +118,10 @@
 
 bool VulkanSwapChain::InitializeSwapChain(
     VkSurfaceKHR surface,
-    const VkSurfaceCapabilitiesKHR& surface_caps,
     const VkSurfaceFormatKHR& surface_format,
+    const gfx::Size& image_size,
+    uint32_t min_image_count,
+    VkSurfaceTransformFlagBitsKHR pre_transform,
     std::unique_ptr<VulkanSwapChain> old_swap_chain) {
   VkDevice device = device_queue_->GetVulkanDevice();
   VkResult result = VK_SUCCESS;
@@ -122,22 +129,15 @@
   VkSwapchainCreateInfoKHR swap_chain_create_info = {};
   swap_chain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
   swap_chain_create_info.surface = surface;
-  swap_chain_create_info.minImageCount =
-      std::max(3u, surface_caps.minImageCount);
+  swap_chain_create_info.minImageCount = min_image_count,
   swap_chain_create_info.imageFormat = surface_format.format;
   swap_chain_create_info.imageColorSpace = surface_format.colorSpace;
-  swap_chain_create_info.imageExtent = surface_caps.currentExtent;
+  swap_chain_create_info.imageExtent.width = image_size.width();
+  swap_chain_create_info.imageExtent.height = image_size.height();
   swap_chain_create_info.imageArrayLayers = 1;
   swap_chain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
   swap_chain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
-  // Always set preTransform to VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR (which is
-  // relative to the presentation engine's natural orientation), if it does not
-  // match the currentTransform value returned by
-  // vkGetPhysicalDeviceSurfaceCapabilitiesKHR, the presentation engine will
-  // transform the image content as part of the presentation operation.
-  // TODO(penghuang): Support preTransform for better performance.
-  // https://crbug.com/957485
-  swap_chain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+  swap_chain_create_info.preTransform = pre_transform;
   swap_chain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
   swap_chain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
   swap_chain_create_info.clipped = true;
@@ -175,7 +175,6 @@
 }
 
 bool VulkanSwapChain::InitializeSwapImages(
-    const VkSurfaceCapabilitiesKHR& surface_caps,
     const VkSurfaceFormatKHR& surface_format) {
   VkDevice device = device_queue_->GetVulkanDevice();
   VkResult result = VK_SUCCESS;
diff --git a/gpu/vulkan/vulkan_swap_chain.h b/gpu/vulkan/vulkan_swap_chain.h
index 11f8996a..f5bfa33d4 100644
--- a/gpu/vulkan/vulkan_swap_chain.h
+++ b/gpu/vulkan/vulkan_swap_chain.h
@@ -57,11 +57,15 @@
   VulkanSwapChain();
   ~VulkanSwapChain();
 
+  // min_image_count is the minimum number of presentable images.
   bool Initialize(VulkanDeviceQueue* device_queue,
                   VkSurfaceKHR surface,
-                  const VkSurfaceCapabilitiesKHR& surface_caps,
                   const VkSurfaceFormatKHR& surface_format,
+                  const gfx::Size& image_size,
+                  uint32_t min_image_count,
+                  VkSurfaceTransformFlagBitsKHR pre_transform,
                   std::unique_ptr<VulkanSwapChain> old_swap_chain);
+
   // Destroy() should be called when all related GPU tasks have been finished.
   void Destroy();
 
@@ -73,14 +77,16 @@
 
  private:
   bool InitializeSwapChain(VkSurfaceKHR surface,
-                           const VkSurfaceCapabilitiesKHR& surface_caps,
                            const VkSurfaceFormatKHR& surface_format,
+                           const gfx::Size& image_size,
+                           uint32_t min_image_count,
+                           VkSurfaceTransformFlagBitsKHR pre_transform,
                            std::unique_ptr<VulkanSwapChain> old_swap_chain);
   void DestroySwapChain();
 
-  bool InitializeSwapImages(const VkSurfaceCapabilitiesKHR& surface_caps,
-                            const VkSurfaceFormatKHR& surface_format);
+  bool InitializeSwapImages(const VkSurfaceFormatKHR& surface_format);
   void DestroySwapImages();
+
   bool BeginWriteCurrentImage(VkImage* image,
                               uint32_t* image_index,
                               VkImageLayout* layout,
diff --git a/gpu/vulkan/x/vulkan_surface_x11.cc b/gpu/vulkan/x/vulkan_surface_x11.cc
index 4801bf3..e5255eed 100644
--- a/gpu/vulkan/x/vulkan_surface_x11.cc
+++ b/gpu/vulkan/x/vulkan_surface_x11.cc
@@ -128,9 +128,12 @@
 VulkanSurfaceX11::~VulkanSurfaceX11() {}
 
 // VulkanSurface:
-bool VulkanSurfaceX11::SetSize(const gfx::Size& size) {
+bool VulkanSurfaceX11::Reshape(const gfx::Size& size,
+                               gfx::OverlayTransform pre_transform) {
+  DCHECK_EQ(pre_transform, gfx::OVERLAY_TRANSFORM_NONE);
+
   XResizeWindow(gfx::GetXDisplay(), window_, size.width(), size.height());
-  return VulkanSurface::SetSize(size);
+  return VulkanSurface::Reshape(size, pre_transform);
 }
 
 bool VulkanSurfaceX11::CanDispatchXEvent(const XEvent* event) {
diff --git a/gpu/vulkan/x/vulkan_surface_x11.h b/gpu/vulkan/x/vulkan_surface_x11.h
index 5b26875b..5c99d6e 100644
--- a/gpu/vulkan/x/vulkan_surface_x11.h
+++ b/gpu/vulkan/x/vulkan_surface_x11.h
@@ -24,7 +24,8 @@
   ~VulkanSurfaceX11() override;
 
   // VulkanSurface:
-  bool SetSize(const gfx::Size& size) override;
+  bool Reshape(const gfx::Size& size,
+               gfx::OverlayTransform pre_transform) override;
 
  private:
   class ExposeEventForwarder;
diff --git a/media/gpu/test/rendering_helper.cc b/media/gpu/test/rendering_helper.cc
index e53d1417..ecfe1a0 100644
--- a/media/gpu/test/rendering_helper.cc
+++ b/media/gpu/test/rendering_helper.cc
@@ -63,11 +63,7 @@
 // static
 void RenderingHelper::InitializeOneOff(bool use_gl, base::WaitableEvent* done) {
   base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-#if defined(OS_WIN)
-  cmd_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationANGLEName);
-#else
   cmd_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationEGLName);
-#endif
 
   use_gl_ = use_gl;
 
diff --git a/services/network/public/cpp/url_request_for_blink.typemap b/services/network/public/cpp/url_request_for_blink.typemap
new file mode 100644
index 0000000..b43cde34
--- /dev/null
+++ b/services/network/public/cpp/url_request_for_blink.typemap
@@ -0,0 +1,15 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(minggang): Delete this file once all typemappings for network.mojom.URLRequest are done.
+mojom = "//services/network/public/mojom/url_loader.mojom"
+public_headers = [ "//services/network/public/cpp/resource_request_body.h" ]
+traits_headers = [ "//services/network/public/cpp/url_request_mojom_traits.h" ]
+public_deps = [
+  "//services/network/public/cpp:cpp_base",
+]
+type_mappings = [
+  "network.mojom.DataElement=network::DataElement[move_only]",
+  "network.mojom.URLRequestBody=scoped_refptr<network::ResourceRequestBody>[nullable_is_same_type,copyable_pass_by_value]",
+]
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc
index 3e7a2c5..b3d6138 100644
--- a/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -14,7 +14,6 @@
 #include "services/network/public/cpp/http_request_headers_mojom_traits.h"
 #include "services/network/public/cpp/network_ipc_param_traits.h"
 #include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom-shared.h"
 #include "url/mojom/origin_mojom_traits.h"
 #include "url/mojom/url_gurl_mojom_traits.h"
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h
index 8247516..ab4d8fc 100644
--- a/services/network/public/cpp/url_request_mojom_traits.h
+++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -19,7 +19,7 @@
 #include "services/network/public/cpp/data_element.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/chunked_data_pipe_getter.mojom-shared.h"
+#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
 #include "services/network/public/mojom/data_pipe_getter.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom-shared.h"
 
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 3c80b285..d664146 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2630,7 +2630,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 4
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests"
       },
@@ -3085,7 +3085,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 4
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests"
       },
@@ -8293,33 +8293,6 @@
           "--enable-gpu",
           "--test-launcher-bot-mode",
           "--test-launcher-jobs=1",
-          "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*",
-          "--no-xvfb"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "tab_capture_end2end_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912-19.0.2",
-              "os": "Ubuntu-19.04",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "expiration": 21600
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-gpu",
-          "--test-launcher-bot-mode",
-          "--test-launcher-jobs=1",
           "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter",
           "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization",
           "--use-gl=any",
@@ -8764,6 +8737,45 @@
       },
       {
         "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-features=VizDisplayCompositor,UseSkiaRenderer",
+          "--additional-driver-flag=--use-gl=any",
+          "--additional-driver-flag=--enable-gpu-rasterization",
+          "--additional-driver-flag=--force-gpu-rasterization",
+          "--additional-driver-flag=--enable-oop-rasterization",
+          "--additional-driver-flag=--disable-software-compositing-fallback",
+          "--additional-driver-flag=--disable-headless-mode",
+          "--no-xvfb",
+          "--fuzzy-diff",
+          "--skipped=always",
+          "--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "skia_renderer_gl_blink_web_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600
+        }
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -8794,6 +8806,48 @@
       },
       {
         "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-features=VizDisplayCompositor,UseSkiaRenderer",
+          "--additional-driver-flag=--use-gl=any",
+          "--additional-driver-flag=--enable-gpu-rasterization",
+          "--additional-driver-flag=--force-gpu-rasterization",
+          "--additional-driver-flag=--enable-oop-rasterization",
+          "--additional-driver-flag=--disable-software-compositing-fallback",
+          "--additional-driver-flag=--use-vulkan=native",
+          "--additional-driver-flag=--disable-vulkan-fallback-to-gl-for-testing",
+          "--additional-driver-flag=--disable-headless-mode",
+          "--no-xvfb",
+          "--fuzzy-diff",
+          "--skipped=always",
+          "--driver-logging",
+          "--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/use-vulkan=native"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "vulkan_native_blink_web_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600
+        }
+      },
+      {
+        "args": [
           "webgl_conformance",
           "--show-stdout",
           "--browser=release",
@@ -9002,33 +9056,6 @@
           "--enable-gpu",
           "--test-launcher-bot-mode",
           "--test-launcher-jobs=1",
-          "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*",
-          "--no-xvfb"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "tab_capture_end2end_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "containment_type": "AUTO",
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3-418.56",
-              "os": "Ubuntu-19.04",
-              "pool": "Chrome-GPU"
-            }
-          ],
-          "expiration": 21600
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-gpu",
-          "--test-launcher-bot-mode",
-          "--test-launcher-jobs=1",
           "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter",
           "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization",
           "--use-gl=any",
@@ -9500,6 +9527,45 @@
       },
       {
         "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-features=VizDisplayCompositor,UseSkiaRenderer",
+          "--additional-driver-flag=--use-gl=any",
+          "--additional-driver-flag=--enable-gpu-rasterization",
+          "--additional-driver-flag=--force-gpu-rasterization",
+          "--additional-driver-flag=--enable-oop-rasterization",
+          "--additional-driver-flag=--disable-software-compositing-fallback",
+          "--additional-driver-flag=--disable-headless-mode",
+          "--no-xvfb",
+          "--fuzzy-diff",
+          "--skipped=always",
+          "--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "skia_renderer_gl_blink_web_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600
+        }
+      },
+      {
+        "args": [
           "trace_test",
           "--show-stdout",
           "--browser=release",
@@ -9530,6 +9596,48 @@
       },
       {
         "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-features=VizDisplayCompositor,UseSkiaRenderer",
+          "--additional-driver-flag=--use-gl=any",
+          "--additional-driver-flag=--enable-gpu-rasterization",
+          "--additional-driver-flag=--force-gpu-rasterization",
+          "--additional-driver-flag=--enable-oop-rasterization",
+          "--additional-driver-flag=--disable-software-compositing-fallback",
+          "--additional-driver-flag=--use-vulkan=native",
+          "--additional-driver-flag=--disable-vulkan-fallback-to-gl-for-testing",
+          "--additional-driver-flag=--disable-headless-mode",
+          "--no-xvfb",
+          "--fuzzy-diff",
+          "--skipped=always",
+          "--driver-logging",
+          "--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/use-vulkan=native"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "vulkan_native_blink_web_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600
+        }
+      },
+      {
+        "args": [
           "webgl_conformance",
           "--show-stdout",
           "--browser=release",
@@ -12189,7 +12297,7 @@
               "pool": "Chrome-GPU"
             }
           ],
-          "shards": 6
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests"
       },
@@ -12214,7 +12322,7 @@
               "pool": "Chrome-GPU"
             }
           ],
-          "shards": 4
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests"
       },
@@ -32207,7 +32315,7 @@
               "pool": "Chrome-GPU"
             }
           ],
-          "shards": 6
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
@@ -32241,7 +32349,7 @@
               "pool": "Chrome-GPU"
             }
           ],
-          "shards": 6
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
@@ -32275,7 +32383,7 @@
               "pool": "Chrome-GPU"
             }
           ],
-          "shards": 4
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
@@ -37161,7 +37269,7 @@
             }
           ],
           "expiration": 21600,
-          "shards": 6
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
@@ -37196,7 +37304,7 @@
             }
           ],
           "expiration": 21600,
-          "shards": 6
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
@@ -37231,7 +37339,7 @@
             }
           ],
           "expiration": 21600,
-          "shards": 4
+          "shards": 10
         },
         "test": "angle_deqp_gles31_tests",
         "trigger_script": {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index fdfda9c..82210f7 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1335,6 +1335,9 @@
       # chromium.gpu.fyi
       'Win10 FYI Debug (NVIDIA)',
       'Win7 FYI Debug (AMD)',
+      # Disabled due to dbus crashes crbug.com/927465
+      'Linux FYI Experimental Release (Intel HD 630)',
+      'Linux FYI Experimental Release (NVIDIA)',
     ],
   },
   'telemetry_perf_unittests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index cc28bac4..7e821d1 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -2926,7 +2926,7 @@
         ],
         'should_retry_with_patch': False,
         'swarming': {
-          'shards': 6,
+          'shards': 10,
         },
         'test': 'angle_deqp_gles31_tests',
       },
@@ -2940,7 +2940,7 @@
         ],
         'should_retry_with_patch': False,
         'swarming': {
-          'shards': 6,
+          'shards': 10,
         },
         'test': 'angle_deqp_gles31_tests',
       },
@@ -2960,7 +2960,7 @@
         ],
         'should_retry_with_patch': False,
         'swarming': {
-          'shards': 4,
+          'shards': 10,
         },
         'test': 'angle_deqp_gles31_tests',
       },
@@ -3179,7 +3179,7 @@
       },
     },
 
-    'gpu_blink_web_tests': {
+    'gpu_blink_web_tests_skia_renderer': {
       'skia_renderer_gl_blink_web_tests': {
         # layout test failures are retried 3 times when '--test-list' is not
         # passed, but 0 times when '--test-list' is passed. We want to always
@@ -3211,6 +3211,41 @@
       },
     },
 
+    'gpu_blink_web_tests_vulkan': {
+      'vulkan_native_blink_web_tests': {
+        # layout test failures are retried 3 times when '--test-list' is not
+        # passed, but 0 times when '--test-list' is passed. We want to always
+        # retry 3 times, so we explicitly specify it.
+        'args': [
+          '--num-retries=3',
+          '--additional-driver-flag=--enable-features=VizDisplayCompositor,UseSkiaRenderer',
+          '--additional-driver-flag=--use-gl=any',
+          '--additional-driver-flag=--enable-gpu-rasterization',
+          '--additional-driver-flag=--force-gpu-rasterization',
+          '--additional-driver-flag=--enable-oop-rasterization',
+          '--additional-driver-flag=--disable-software-compositing-fallback',
+          '--additional-driver-flag=--use-vulkan=native',
+          '--additional-driver-flag=--disable-vulkan-fallback-to-gl-for-testing',
+          '--additional-driver-flag=--disable-headless-mode',
+          '--no-xvfb',
+          '--fuzzy-diff',
+          '--skipped=always',
+          '--driver-logging',
+          '--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter',
+          '--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer',
+          '--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/use-vulkan=native',
+        ],
+        'isolate_name': 'blink_web_tests_exparchive',
+        'merge': {
+          'args': [
+            '--verbose',
+          ],
+          'script': '//third_party/blink/tools/merge_web_test_results.py',
+        },
+        'results_handler': 'layout tests',
+      },
+   },
+
     # The command buffer perf tests are only run on Windows.
     # They are mostly driver and platform independent.
     'gpu_command_buffer_perf_passthrough_isolated_scripts': {
@@ -5069,6 +5104,17 @@
       'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests',
     ],
 
+    'gpu_blink_web_tests': [
+      'gpu_blink_web_tests_skia_renderer',
+      'gpu_blink_web_tests_vulkan',
+    ],
+
+    'gpu_blink_web_tests_and_angle_perf_isolated_scripts': [
+      'gpu_angle_perf_isolated_scripts',
+      'gpu_blink_web_tests_skia_renderer',
+      'gpu_blink_web_tests_vulkan',
+    ],
+
     'gpu_chromeos_telemetry_tests': [
       'gpu_webgl_conformance_telemetry_tests',
     ],
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index df795c73..57a94a0 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2614,6 +2614,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_fyi_linux_release_gtests',
+          'isolated_scripts': 'gpu_blink_web_tests',
           'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests',
         }
       },
@@ -2626,7 +2627,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_fyi_linux_release_gtests',
-          'isolated_scripts': 'gpu_angle_perf_isolated_scripts',
+          'isolated_scripts': 'gpu_blink_web_tests_and_angle_perf_isolated_scripts',
           'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests',
         },
       },
@@ -2701,7 +2702,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_fyi_linux_release_gtests',
-          'isolated_scripts': 'gpu_blink_web_tests',
+          'isolated_scripts': 'gpu_blink_web_tests_skia_renderer',
           'gpu_telemetry_tests': 'gpu_skia_renderer_telemetry_tests',
         },
       },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index bb76eec..3d010c4 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -5105,26 +5105,6 @@
             ]
         }
     ],
-    "SyncUSSAutofillWalletMetadata": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "SyncUSSAutofillWalletMetadata"
-                    ]
-                }
-            ]
-        }
-    ],
     "SyncUssBookmarks'": [
         {
             "platforms": [
@@ -5832,9 +5812,6 @@
                     "name": "VizHitTestSurfaceLayer",
                     "enable_features": [
                         "VizHitTestSurfaceLayer"
-                    ],
-                    "disable_features": [
-                        "VizHitTestDrawQuad"
                     ]
                 }
             ]
diff --git a/third_party/blink/public/blink_typemaps.gni b/third_party/blink/public/blink_typemaps.gni
index 1ed2050..492f006 100644
--- a/third_party/blink/public/blink_typemaps.gni
+++ b/third_party/blink/public/blink_typemaps.gni
@@ -14,6 +14,7 @@
   "//mojo/public/cpp/base/time.typemap",
   "//mojo/public/cpp/base/read_only_buffer.typemap",
   "//mojo/public/cpp/base/unguessable_token.typemap",
+  "//services/network/public/cpp/url_request_for_blink.typemap",
   "//services/viz/public/cpp/compositing/begin_frame_args_for_blink.typemap",
   "//services/viz/public/cpp/compositing/compositor_frame_for_blink.typemap",
   "//services/viz/public/cpp/compositing/frame_sink_id.typemap",
diff --git a/third_party/blink/public/mojom/frame/document_interface_broker.mojom b/third_party/blink/public/mojom/frame/document_interface_broker.mojom
index da68e362..6e12f17 100644
--- a/third_party/blink/public/mojom/frame/document_interface_broker.mojom
+++ b/third_party/blink/public/mojom/frame/document_interface_broker.mojom
@@ -16,12 +16,44 @@
 // An interface through which the renderer may request document-scoped
 // interfaces from the browser.
 interface DocumentInterfaceBroker {
+  // Binds the blink.mojom.AudioContextManager interface request to its remote
+  // implementation in the browser process, to allow sending real-time
+  // notifications originated from Blink's AudioContext.
   GetAudioContextManager(blink.mojom.AudioContextManager& request);
+
+  // Binds the blink.mojom.Authenticator interface request to its remote
+  // implementation in the browser process, to allow directing authenticators to
+  // create or use a public key credential.
   GetAuthenticator(blink.mojom.Authenticator& request);
+
+  // Binds the blink.mojom.CredentialManager interface request to its remote
+  // implementation in the browser process, to allow storing, retrieving and
+  // handling credentials.
   GetCredentialManager(blink.mojom.CredentialManager& request);
+
+  // Binds the blink.mojom.FrameHostTestInterface interface request to its
+  // remote implementation in the browser process, to allow using this test
+  // interface to exercise requesting document-scoped interfaces from the
+  // RenderFrameHost through the DocumentInterfaceBroker interface.
   GetFrameHostTestInterface(blink.mojom.FrameHostTestInterface& request);
-  GetPushMessaging(pending_receiver<blink.mojom.PushMessaging> request);
-  GetVirtualAuthenticatorManager(blink.test.mojom.VirtualAuthenticatorManager& request);
+
+  // Binds the blink.mojom.PushMessaging pending receiver request to its remote
+  // implementation in the browser process, to allow subscribing, unsubscribing
+  // and retrieving subscriptions related to push notifications (see Push API).
+  GetPushMessaging(pending_receiver<blink.mojom.PushMessaging> receiver);
+
+  // Binds the blink.test.mojom.VirtualAuthenticatorManager interface request to
+  // its remote implementation in the browser process, to manage a virtual
+  // environment that allows talking virtual authenticators via the WebAuth API.
+  GetVirtualAuthenticatorManager(
+      blink.test.mojom.VirtualAuthenticatorManager& request);
+
+  // Binds the blink.mojom.AppCacheHost interface request to its remote
+  // implementation in the browser process, to allow handling and interacting
+  // with the AppCache for a given host, referenced by the |host_id| parameter.
+  // This method also requires a remote of the blink.mojom.AppCacheFrontend
+  // interface, referenced by |frontend|, to enable communicating with the
+  // renderer process from the AppCacheService's implementation.
   RegisterAppCacheHost(blink.mojom.AppCacheHost& host_request,
                        AppCacheFrontend frontend,
                        mojo_base.mojom.UnguessableToken host_id);
diff --git a/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom b/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
index bec4a05..47d55c4 100644
--- a/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
+++ b/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
@@ -38,19 +38,19 @@
   // permission status for this handle.
   RequestPermission(bool writable) => (PermissionStatus status);
 
-  // Returns a file with the given |name| that is a child of this directory. If
-  // no such file exists, and |create| is true, the file is first created.
-  // Returns an error if the operation fails, or a handle to the newly created
-  // file if the operation succeeds.
-  GetFile(string name, bool create) =>
+  // Returns a file with the given |basename| that is a child of this
+  // directory. If no such file exists, and |create| is true, the file is first
+  // created. Returns an error if the operation fails, or a handle to the newly
+  // created file if the operation succeeds.
+  GetFile(string basename, bool create) =>
       (NativeFileSystemError result, NativeFileSystemFileHandle? file);
 
-  // Returns a directory with the given |name| that is a child of this
+  // Returns a directory with the given |basename| that is a child of this
   // directory. If no such directory exists, and |create| is true, the directory
   // is first created.
   // Returns an error if the operation fails, or a handle to the newly created
   // directory if the operation succeeds.
-  GetDirectory(string name, bool create) =>
+  GetDirectory(string basename, bool create) =>
       (NativeFileSystemError result, NativeFileSystemDirectoryHandle? directory);
 
   // Returns all the direct children of this directory.
@@ -58,8 +58,9 @@
   // until all entries have been retrieved.
   GetEntries() => (NativeFileSystemError result, array<NativeFileSystemEntry> entries);
 
-  // Deletes this directory. To delete recursively, set |recursive| to true.
-  Remove(bool recurse) => (NativeFileSystemError result);
+  // Deletes an entry which is a child of this directory.
+  // To delete recursively, set |recurse| to true.
+  RemoveEntry(string basename, bool recurse) => (NativeFileSystemError result);
 
   // Create a TransferToken for this directory. This token can be used to pass
   // a reference to this directory to other methods, for example to copy or move
diff --git a/third_party/blink/renderer/bindings/scripts/v8_interface.py b/third_party/blink/renderer/bindings/scripts/v8_interface.py
index 6aff5f9..6810582 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_interface.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_interface.py
@@ -887,11 +887,11 @@
     for index, method in enumerate(overloads, 1):
         method['overload_index'] = index
 
-    # [OriginTrialEnabled]
+    # [RuntimeEnabled]
     # TODO(iclelland): Allow origin trials on method overloads
     # (crbug.com/621641)
     if any(method.get('origin_trial_feature_name') for method in overloads):
-        raise Exception('[OriginTrialEnabled] cannot be specified on '
+        raise Exception('[RuntimeEnabled] for origin trial cannot be specified on '
                         'overloaded methods: %s.%s' % (interface.name, overloads[0]['name']))
 
     effective_overloads_by_length = effective_overload_set_by_length(overloads)
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py b/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
index b532622..3e2b834 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
@@ -163,6 +163,18 @@
         """
         return key in self._attributes
 
+    def __iter__(self):
+        """
+        Yields all ExtendedAttribute instances.
+        """
+        for attrs in self._attributes.values():
+            for attr in attrs:
+                yield attr
+
+    def __str__(self):
+        attrs = [str(attr) for attr in self]
+        return '[{}]'.format(', '.join(attrs))
+
     def get(self, key):
         """
         Returns an exnteded attribute whose key is |key|.
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_reference_proxy.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_reference_proxy.py
index 23d47da6..5baefa0 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_reference_proxy.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_reference_proxy.py
@@ -98,6 +98,10 @@
         self._target_attrs = target_attrs
         self._target_attrs_with_priority = target_attrs_with_priority
 
+    @classmethod
+    def is_reference(cls, obj):
+        return isinstance(obj, cls._RefById)
+
     def create(self, identifier):
         assert not self._did_resolve
         ref = RefByIdFactory._RefById(identifier, self._target_attrs,
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_types.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_types.py
index 9d74125..9346479f 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_types.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_types.py
@@ -3,393 +3,516 @@
 # found in the LICENSE file.
 
 import exceptions
+from blinkbuild.name_style_converter import NameStyleConverter
 from .common import WithCodeGeneratorInfo
 from .common import WithComponent
 from .common import WithDebugInfo
 from .common import WithExtendedAttributes
 from .common import WithIdentifier
+from .idl_reference_proxy import RefByIdFactory
+from .idl_reference_proxy import Proxy
+from .user_defined_type import UserDefinedType
 
-# This file defines following classes to provide IDL types
+# This file defines following classes to provide IDL types.
 #
-# Classes:
-# -IdlType
-# -  NumberType
-# -    IntegerType
-# -    RealNumberType
-# -  BooleanType
-# -  StringType
-# -  AnyType
-# -  ObjectType
-# -  VoidType
-# -  ArrayLikeType
-# -    SequenceType
-# -    FrozenArrayType
-# -  RecordType
-# -  PromiseType
-# -  UnionType
-# -  NullableType
-# -  AnnotatedType
+# <Classes>
+# IdlType
+# + SimpleType
+# + ReferenceType
+# + DefinitionType
+# + TypedefType
+# + _ArrayLikeType
+# | + SequenceType
+# | + FrozenArrayType
+# + RecordType
+# + PromiseType
+# + UnionType
+# + NullableType
+# + AnnotatedType
 
 
-class IdlType(WithCodeGeneratorInfo):
+class IdlType(WithCodeGeneratorInfo, WithDebugInfo):
+    """
+    Represents a 'type' in Web IDL
+
+    IdlType is an interface of types in Web IDL, and also provides all the
+    information that is necessary for type conversions.  For example, given the
+    conversion rules of ECMAScript bindings, you can produce a type converter
+    between Blink types and V8 types with using an IdlType.
+
+    Note that IdlType is designed to _not_ include knowledge about a certain
+    language bindings (such as ECMAScript bindings), thus it's out of scope for
+    IdlType to tell whether IDL dictionary type accepts ES null value or not.
+
+    *CAUTION*: Predicators are defined based on the exact definition of Web
+    IDL, and may behave counterintuitively. See examples below.
+
+      clamp_nullable_long = ...an IdlType of '[Clamp] long?'
+      isisntance(clamp_nullable_long, AnnotatedType)  # True
+      clamp_nullable_long.is_annotated  # True
+      clamp_nullable_long.is_nullable   # False, this is not a NullableType
+
+      nullable_long = clamp_nullable_long.inner_type
+      isinstance(nullable_long, NullableType)  # True
+      nullable_long.is_nullable  # True
+      nullable_long.is_numeric   # False, NullableType is not a numeric type
+
+      long_type = nullable_long.inner_type
+      isinstance(long_type, SimpleType)  # True
+      long_type.is_numeric               # True
+    """
+
+    def __init__(self, code_generator_info=None, debug_info=None):
+        WithCodeGeneratorInfo.__init__(self, code_generator_info)
+        WithDebugInfo.__init__(self, debug_info)
+
+    def __str__(self):
+        raise exceptions.NotImplementedError()
+
     @property
     def type_name(self):
         """
-        Returns type name as defined in WebIDL spec; e.g. LongLongOrNullClamp
-        for '[Clamp] long long?'.
-        @return Identifier
+        Returns type name of this type.
+        https://heycam.github.io/webidl/#dfn-type-name
+        @return str
         """
-        # TODO(peria): Replace with exceptions.NotImplementedError() after shipping.
-        assert 'type_name() is not implemented for class %s' % (type(self))
+        raise exceptions.NotImplementedError()
 
-    # These flags are used for types in args.
     @property
-    def is_optional(self):
+    def does_include_nullable_type(self):
         """
-        Returns True if this type is used in an optional argument.
+        Returns True if |self| includes a nulllable type.
+        https://heycam.github.io/webidl/#dfn-includes-a-nullable-type
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_variadic(self):
+    def is_numeric(self):
         """
-        Returns True if this type is used in a variadic argument.
+        Returns True if |self| is a number type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
-    # Some of following type checkers return True, if |this| meets the
-    # expectation.
     @property
-    def is_number_type(self):
+    def is_integer(self):
         """
-        Returns True if |self| is a NumberType.
+        Returns True if |self| is an integer type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_integer_type(self):
+    def is_boolean(self):
         """
-        Returns True if |self| is an IntegerType.
+        Returns True if |self| is a boolean type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_real_number_type(self):
+    def is_string(self):
         """
-        Returns True if |self| is a RealNumberType.
+        Returns True if |self| is a string type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_boolean_type(self):
+    def is_object(self):
         """
-        Returns True if |self| is a BooleanType.
+        Returns True if |self| is an object type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_string_type(self):
+    def is_symbol(self):
         """
-        Returns True if |self| is a StringType.
+        Returns True if |self| is a symbol type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_object_type(self):
+    def is_any(self):
         """
-        Returns True if |self| is an ObjectType.
+        Returns True if |self| is an any type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_any_type(self):
+    def is_void(self):
         """
-        Returns True if |self| is an AnyType.
+        Returns True if |self| is a void type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_interface_type(self):
+    def is_interface(self):
         """
-        Returns True if |self| is an InterfaceType.
+        Returns True if |self| is an interface type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_dictionary_type(self):
+    def is_callback_interface(self):
         """
-        Returns True if |self| is a DictionaryType.
+        Returns True if |self| is a callback interface type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_namespace_type(self):
+    def is_dictionary(self):
         """
-        Returns True if |self| is a NamespaceType.
+        Returns True if |self| is a dictionary type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_enumeration_type(self):
+    def is_enumeration(self):
         """
-        Returns True if |self| is an EnumerationType.
+        Returns True if |self| is an enumeration type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_callback_interface_type(self):
+    def is_callback_function(self):
         """
-        Returns True if |self| is a CallbackInterfaceType.
+        Returns True if |self| is a callback function type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_callback_function_type(self):
+    def is_typedef(self):
         """
-        Returns True if |self| is a CallbackFunctionType.
+        Returns True if |self| is a typedef.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_void_type(self):
+    def is_nullable(self):
         """
-        Returns True if |self| is a VoidType.
+        Returns True if |self| is a nullable type.
+
+        NOTE: If |self| is a union type which includes a nullable type, this
+        returns False, because |self| itself is not a nullable type.
+        Use |does_include_nullable_type| in such a case.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_nullable_type(self):
+    def is_annotated(self):
         """
-        Returns True if |self| is a NullableType.
+        Returns True if |self| is an annotated type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_annotated_type(self):
+    def is_promise(self):
         """
-        Returns True if |self| is an AnnotatedType.
+        Returns True if |self| is a promise type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_promise_type(self):
+    def is_record(self):
         """
-        Returns True if |self| is a PromiseType.
+        Returns True if |self| is a record type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_record_type(self):
+    def is_sequence(self):
         """
-        Returns True if |self| is a RecordType.
+        Returns True if |self| is a sequence type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_sequence_type(self):
+    def is_frozen_array(self):
         """
-        Returns True if |self| is a SequenceType.
+        Returns True if |self| is a froen array type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return False
 
     @property
-    def is_union_type(self):
+    def is_union(self):
         """
-        Returns True if |self| is a UnionType.
+        Returns True if |self| is a union type.
         @return bool
         """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def typedefs(self):
-        """
-        Returns Typedef instances which directly point this type.
-        @return tuple(Typedef)
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def inner_type(self):
-        """
-        Returns inner type if |this| is a nullable or an annotated type.
-        @return IdlType?
-        """
-        raise exceptions.NotImplementedError()
-
-    # One of following methods returns an instance, if |this| refers a definition.
-    @property
-    def interface(self):
-        """
-        Returns the interface that |self| points if |self| is an InterfaceType.
-        @return Interface
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def dictionary(self):
-        """
-        Returns the dictionary that |self| points if |self| is an DictionaryType.
-        @return Dictionary
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def namespace(self):
-        """
-        Returns the namespace that |self| points if |self| is an NamespaceType.
-        @return Namespace
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def enumeration(self):
-        """
-        Returns the enumeration that |self| points if |self| is an EnumerationType.
-        @return Enumeration
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def callback_interface(self):
-        """
-        Returns the callback interface that |self| points if |self| is an CallbackInterfaceType.
-        @return CallbackInterface
-        """
-        raise exceptions.NotImplementedError()
-
-    @property
-    def callback_function(self):
-        """
-        Returns the callback function that |self| points if |self| is an CallbackFunctionType.
-        @return CallbackFunction
-        """
-        raise exceptions.NotImplementedError()
+        return False
 
 
-class NumberType(IdlType, WithIdentifier):
-    """https://heycam.github.io/webidl/#idl-types"""
+class SimpleType(IdlType):
+    """
+    Represents built-in types that do not contain other types internally.
+    e.g. primitive types, string types, and object types.
+    https://heycam.github.io/webidl/#idl-types
+    """
+
+    _INTEGER_TYPES = ('byte', 'octet', 'short', 'unsigned short', 'long',
+                      'unsigned long', 'long long', 'unsigned long long')
+    _NUMERIC_TYPES = ('float', 'unrestricted float', 'double',
+                      'unrestricted double') + _INTEGER_TYPES
+    _STRING_TYPES = ('DOMString', 'ByteString', 'USVString')
+    _VALID_TYPES = ('any', 'boolean', 'object', 'symbol',
+                    'void') + _NUMERIC_TYPES + _STRING_TYPES
+
+    def __init__(self, name, code_generator_info=None, debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert name in SimpleType._VALID_TYPES, (
+            'Unknown type name: {}'.format(name))
+        self._name = name
+
+    def __str__(self):
+        return self._name
 
     # IdlType overrides
     @property
-    def is_number_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        if str(self) == 'DOMString':
+            return 'String'
+        return NameStyleConverter(self._name).to_upper_camel_case()
+
+    @property
+    def is_numeric(self):
+        return self._name in SimpleType._NUMERIC_TYPES
+
+    @property
+    def is_integer(self):
+        return self._name in SimpleType._INTEGER_TYPES
+
+    @property
+    def is_boolean(self):
+        return self._name == 'boolean'
+
+    @property
+    def is_string(self):
+        return self._name in SimpleType._STRING_TYPES
+
+    @property
+    def is_object(self):
+        return self._name == 'object'
+
+    @property
+    def is_symbol(self):
+        return self._name == 'symbol'
+
+    @property
+    def is_any(self):
+        return self._name == 'any'
+
+    @property
+    def is_void(self):
+        return self._name == 'void'
 
 
-class IntegerType(IdlType, WithIdentifier):
-    """https://heycam.github.io/webidl/#idl-types"""
+class ReferenceType(IdlType, WithIdentifier, Proxy):
+    """
+    Represents a type specified with the given identifier.
+
+    As the exact type definitions are unknown in early compilation phases, it
+    will be resolved in very end of the compilation phases.  Once everything is
+    resolved, a ReferenceType behaves as a proxy to the resolved type.
+
+    'typedef' in Web IDL is not a type, but we have TypedefType.  The
+    identifier may be resolved to a TypedefType.
+    """
+
+    def __init__(self,
+                 ref_to_idl_type,
+                 code_generator_info=None,
+                 debug_info=None):
+        assert RefByIdFactory.is_reference(ref_to_idl_type)
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        WithIdentifier.__init__(self, ref_to_idl_type.identifier)
+        # TODO(yukishiino): Set appropriate attributes to proxy.
+        Proxy.__init__(self, target_object=ref_to_idl_type)
+
+
+class DefinitionType(IdlType, WithIdentifier):
+    """
+    Represents a spec-author-defined type, e.g. interface type and dictionary
+    type.
+
+    Typedef and union type are not included.  They are represented as
+    TypedefType and UnionType respectively.
+    """
+
+    def __init__(self,
+                 user_def_type,
+                 code_generator_info=None,
+                 debug_info=None):
+        assert isinstance(user_def_type, UserDefinedType)
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        WithIdentifier.__init__(self, user_def_type.identifier)
+        self._definition = user_def_type
+
+    # TODO(peria): Consider exposing access of |_definition|
 
     # IdlType overrides
     @property
-    def is_integer_type(self):
-        raise exceptions.NotImplementedError()
-
-
-class RealNumberType(IdlType, WithIdentifier):
-    """https://heycam.github.io/webidl/#idl-types"""
+    def is_interface(self):
+        return self._definition.is_interface
 
     @property
-    def is_unrestricted(self):
+    def is_callback_interface(self):
+        return self._definition.is_callback_interface
+
+    @property
+    def is_dictionary(self):
+        return self._definition.is_dictionary
+
+    @property
+    def is_enumeration(self):
+        return self._definition.is_enumeration
+
+    @property
+    def is_callback_function(self):
+        return self._definition.is_callback_function
+
+
+class TypedefType(IdlType, WithIdentifier):
+    """
+    Represents a typedef definition as an IdlType.
+
+    'typedef' in Web IDL is not a type, however, there are use cases that have
+    interest in typedef names.  Thus, the IDL compiler does not resolve
+    typedefs transparently (i.e. does not remove typedefs entirely), and
+    IdlTypes representing typedefs remain and behave like AnnotatedType.  You
+    can track down the typedef'ed type to |original_type|.
+    """
+
+    def __init__(self, typedef, code_generator_info=None, debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        WithIdentifier.__init__(self, typedef.identifier)
+        self._typedef = typedef
+
+    @property
+    def original_type(self):
         """
-        Returns True if 'unrestricted' is specified.
-        @return bool
+        Returns the typedef'ed original type
+        @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._typedef.idl_type
 
     # IdlType overrides
     @property
-    def is_real_number_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.original_type.type_name
 
-
-class BooleanType(IdlType, WithIdentifier):
-    """https://heycam.github.io/webidl/#idl-types"""
-
-    # IdlType overrides
     @property
-    def is_boolean_type(self):
-        raise exceptions.NotImplementedError()
+    def does_include_nullable_type(self):
+        return self.original_type.does_include_nullable_type
 
-
-class StringType(IdlType, WithIdentifier):
-    """https://heycam.github.io/webidl/#idl-types"""
-
-    # IdlType overrides
     @property
-    def is_string_type(self):
-        raise exceptions.NotImplementedError()
+    def is_typedef(self):
+        return True
 
 
-class AnyType(IdlType):
+class _ArrayLikeType(IdlType):
+    def __init__(self, element_type, code_generator_info=None,
+                 debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert isinstance(element_type, IdlType)
+        self._element_type = element_type
 
-    # IdlType overrides
-    @property
-    def is_any_type(self):
-        raise exceptions.NotImplementedError()
-
-
-class ObjectType(IdlType):
-    # IdlType overrides
-    @property
-    def is_object_type(self):
-        raise exceptions.NotImplementedError()
-
-
-class VoidType(IdlType):
-    # IdlType overrides
-    @property
-    def is_void_type(self):
-        raise exceptions.NotImplementedError()
-
-
-class ArrayLikeType(IdlType):
     @property
     def element_type(self):
-        raise exceptions.NotImplementedError()
+        return self._element_type
 
 
-class SequenceType(ArrayLikeType):
+class SequenceType(_ArrayLikeType):
+    def __init__(self, element_type, code_generator_info=None,
+                 debug_info=None):
+        _ArrayLikeType.__init__(self, element_type)
+
     # IdlType overrides
+    def __str__(self):
+        return 'sequence<{}>'.format(self.element_type)
+
     @property
-    def is_sequence_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.element_type.type_name + 'Sequence'
+
+    @property
+    def is_sequence(self):
+        return True
 
 
-class FrozenArrayType(ArrayLikeType):
+class FrozenArrayType(_ArrayLikeType):
+    def __init__(self, element_type, code_generator_info=None,
+                 debug_info=None):
+        _ArrayLikeType.__init__(self, element_type)
+
     # IdlType overrides
+    def __str__(self):
+        return 'FrozenArray<{}>'.format(self.element_type)
+
     @property
-    def is_frozen_array_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.element_type.type_name + 'Array'
+
+    @property
+    def is_frozen_array(self):
+        return True
 
 
 class RecordType(IdlType):
+    def __init__(self,
+                 key_type,
+                 value_type,
+                 code_generator_info=None,
+                 debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert isinstance(key_type, IdlType)
+        assert isinstance(value_type, IdlType)
+
+        self._key_type = key_type
+        self._value_type = value_type
+
     @property
     def key_type(self):
         """
         Returns the key type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._key_type
 
     @property
     def value_type(self):
@@ -397,70 +520,165 @@
         Returns the value type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._value_type
 
     # IdlType overrides
+    def __str__(self):
+        return 'record<{}, {}>'.format(self.key_type, self.value_type)
+
     @property
-    def is_record_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.key_type.type_name + self.value_type.type_name + 'Record'
+
+    @property
+    def is_record(self):
+        return True
 
 
 class PromiseType(IdlType):
+    def __init__(self, result_type, code_generator_info=None, debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert isinstance(result_type, IdlType)
+        self._result_type = result_type
+
     @property
     def result_type(self):
         """
         Returns the result type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._result_type
 
     # IdlType overrides
+    def __str__(self):
+        return 'Promise<{}>'.format(self.result_type)
+
     @property
-    def is_promise_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.result_type.type_name + 'Promise'
+
+    @property
+    def is_promise(self):
+        return True
 
 
-class UnionType(IdlType, WithComponent, WithDebugInfo):
+# https://heycam.github.io/webidl/#idl-union
+class UnionType(IdlType):
+    def __init__(self, member_types, code_generator_info=None,
+                 debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert isinstance(member_types, (list, tuple))
+        assert all(isinstance(member, IdlType) for member in member_types)
+        self._member_types = tuple(member_types)
+
+    # TODO(peria): Make it possible to access the definition directly from this
+    # object.
+
     @property
     def member_types(self):
         """
         Returns a list of member types.
         @return tuple(IdlType)
         """
-        raise exceptions.NotImplementedError()
+        return self._member_types
 
     @property
     def flattened_member_types(self):
         """
         Returns a set of flattened member types.
+        NOTE: Returned set does not contain nullable types nor annotated types,
+        even if |self| contains nullable/annotated types in its members.
         https://heycam.github.io/webidl/#dfn-flattened-union-member-types
         @return set(IdlType)
         """
-        raise exceptions.NotImplementedError()
+        # TODO(peria): Implement this method.
+        assert False, 'Not implemented yet'
 
     # IdlType overrides
+    def __str__(self):
+        return '({})'.format(' or '.join([str(t) for t in self.member_types]))
+
     @property
-    def is_union_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return 'Or'.join([member.type_name for member in self.member_types])
+
+    @property
+    def does_include_nullable_type(self):
+        return any(
+            member.does_include_nullable_type for member in self.member_types)
+
+    @property
+    def is_union(self):
+        return True
 
 
 class NullableType(IdlType):
+    def __init__(self, inner_type, code_generator_info=None, debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        assert isinstance(inner_type, IdlType)
+        self._inner_type = inner_type
+
     # IdlType overrides
+    def __str__(self):
+        return '{}?'.format(self.inner_type)
+
     @property
-    def is_nullable_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.inner_type.type_name + 'OrNull'
+
+    @property
+    def does_include_nullable_type(self):
+        return True
+
+    @property
+    def is_nullable(self):
+        return True
 
     @property
     def inner_type(self):
-        raise exceptions.NotImplementedError()
+        return self._inner_type
 
 
 class AnnotatedType(IdlType, WithExtendedAttributes):
+    def __init__(self,
+                 inner_type,
+                 extended_attributes,
+                 code_generator_info=None,
+                 debug_info=None):
+        IdlType.__init__(
+            self,
+            code_generator_info=code_generator_info,
+            debug_info=debug_info)
+        WithExtendedAttributes.__init__(self, extended_attributes)
+        assert isinstance(inner_type, IdlType)
+        self._inner_type = inner_type
+
     # IdlType overrides
+    def __str__(self):
+        return '{} {}'.format(self.extended_attributes, self.inner_type)
+
     @property
-    def is_annotated_type(self):
-        raise exceptions.NotImplementedError()
+    def type_name(self):
+        return self.inner_type.type_name + ''.join(
+            sorted([ext_attr.key for ext_attr in self.extended_attributes]))
+
+    @property
+    def does_include_nullable_type(self):
+        return self.inner_type.does_include_nullable_type
+
+    @property
+    def is_annotated(self):
+        return True
 
     @property
     def inner_type(self):
-        raise exceptions.NotImplementedError()
+        return self._inner_type
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_types_test.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_types_test.py
new file mode 100644
index 0000000..b40fccd
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_types_test.py
@@ -0,0 +1,108 @@
+# 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 unittest
+
+from .extended_attribute import ExtendedAttribute
+from .extended_attribute import ExtendedAttributes
+from .idl_types import AnnotatedType
+from .idl_types import FrozenArrayType
+from .idl_types import NullableType
+from .idl_types import PromiseType
+from .idl_types import RecordType
+from .idl_types import SequenceType
+from .idl_types import SimpleType
+from .idl_types import UnionType
+
+
+class IdlTypesTest(unittest.TestCase):
+    def test_property(self):
+        self.assertTrue(SimpleType('any').is_any)
+        self.assertTrue(SimpleType('boolean').is_boolean)
+        self.assertTrue(SimpleType('object').is_object)
+        self.assertTrue(SimpleType('void').is_void)
+        self.assertTrue(SimpleType('symbol').is_symbol)
+
+        for x in ('byte', 'octet', 'short', 'unsigned short', 'long',
+                  'unsigned long', 'long long', 'unsigned long long'):
+            self.assertTrue(SimpleType(x).is_numeric)
+            self.assertTrue(SimpleType(x).is_integer)
+        for x in ('float', 'unrestricted float', 'double',
+                  'unrestricted double'):
+            self.assertTrue(SimpleType(x).is_numeric)
+            self.assertFalse(SimpleType(x).is_integer)
+        for x in ('DOMString', 'ByteString', 'USVString'):
+            self.assertTrue(SimpleType(x).is_string)
+
+        short_type = SimpleType('short')
+        string_type = SimpleType('DOMString')
+        ext_attrs = ExtendedAttributes([ExtendedAttribute('Clamp')])
+        self.assertTrue(PromiseType(short_type).is_promise)
+        self.assertTrue(RecordType(short_type, string_type).is_record)
+        self.assertTrue(SequenceType(short_type).is_sequence)
+        self.assertTrue(FrozenArrayType(short_type).is_frozen_array)
+        self.assertTrue(UnionType([short_type, string_type]).is_union)
+        self.assertTrue(NullableType(short_type).is_nullable)
+        annotated_type = AnnotatedType(short_type, ext_attrs)
+        self.assertTrue(annotated_type.is_annotated)
+        # Predictors are not transparent
+        self.assertFalse(annotated_type.is_numeric)
+
+        self.assertFalse(SimpleType('long').is_string)
+        self.assertFalse(SimpleType('DOMString').is_object)
+        self.assertFalse(SimpleType('symbol').is_string)
+
+    def test_type_name(self):
+        type_names = {
+            'byte': 'Byte',
+            'unsigned long long': 'UnsignedLongLong',
+            'unrestricted double': 'UnrestrictedDouble',
+            'DOMString': 'String',
+            'ByteString': 'ByteString',
+            'USVString': 'USVString',
+            'any': 'Any',
+            'boolean': 'Boolean',
+            'object': 'Object',
+            'void': 'Void',
+            'symbol': 'Symbol',
+        }
+        for name, expect in type_names.iteritems():
+            self.assertEqual(expect, SimpleType(name).type_name)
+
+        short_type = SimpleType('short')
+        string_type = SimpleType('DOMString')
+        self.assertEqual('ShortOrString',
+                         UnionType([short_type, string_type]).type_name)
+        self.assertEqual('StringOrShort',
+                         UnionType([string_type, short_type]).type_name)
+        self.assertEqual('ShortPromise', PromiseType(short_type).type_name)
+        self.assertEqual('ShortStringRecord',
+                         RecordType(short_type, string_type).type_name)
+        self.assertEqual('ShortSequence', SequenceType(short_type).type_name)
+        self.assertEqual('ShortArray', FrozenArrayType(short_type).type_name)
+        self.assertEqual('ShortOrNull', NullableType(short_type).type_name)
+
+        ext_attrs = ExtendedAttributes(
+            [ExtendedAttribute('TreatNullAs', 'EmptyString')])
+        self.assertEqual('StringTreatNullAs',
+                         AnnotatedType(string_type, ext_attrs).type_name)
+
+    def test_union_types(self):
+        # Test target: ((unrestricted double or object)? or
+        #               [TreatNullAs=EmptyString] DOMString)
+        treat_null_as = ExtendedAttribute('TreatNullAs', 'EmptyString')
+        annotated_string = AnnotatedType(
+            SimpleType('DOMString'), ExtendedAttributes([treat_null_as]))
+        obj = SimpleType('object')
+        unrestricted_double = SimpleType('unrestricted double')
+        union = UnionType(
+            [UnionType([unrestricted_double, obj]), annotated_string])
+
+        self.assertEqual(len(union.member_types), 2)
+        # TODO(peria): Enable following tests.
+        # self.assertEqual(len(union.flattened_member_types), 3)
+        # self.assertTrue(union.does_include_nullable_type)
+
+    # TODO(peria): Implement tests for ReferenceType, DefinitionType, and
+    # TypeAlias
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/typedef.py b/third_party/blink/renderer/bindings/scripts/web_idl/typedef.py
index cd0b7c3..5f3151b 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/typedef.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/typedef.py
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import exceptions
 from .common import WithCodeGeneratorInfo
 from .common import WithComponent
 from .common import WithDebugInfo
@@ -35,4 +34,4 @@
         Returns the type to have an alias.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'Not implemented yet'
diff --git a/third_party/blink/renderer/bindings/tests/idls/core/test_interface_origin_trial_enabled.idl b/third_party/blink/renderer/bindings/tests/idls/core/test_interface_origin_trial_enabled.idl
index cb5f4b6..0174b17 100644
--- a/third_party/blink/renderer/bindings/tests/idls/core/test_interface_origin_trial_enabled.idl
+++ b/third_party/blink/renderer/bindings/tests/idls/core/test_interface_origin_trial_enabled.idl
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Test for [OriginTrialEnabled] extended attribute applied to an interface.
-// This is separate from TestInterface (and TestInterface[2|3]), as the
-// [OriginTrialEnabled] attribute takes precedence over [RuntimeEnabled].
+// Test for [RuntimeEnabled] extended attribute applied to an interface that
+// references an origin trial controlled feature.
 
 [
     RuntimeEnabled=InterfaceFeatureName
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc
index 8d7491aa..78af922 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -133,7 +133,7 @@
 
 // static
 CSSMathExpressionNumericLiteral* CSSMathExpressionNumericLiteral::Create(
-    CSSPrimitiveValue* value,
+    CSSNumericLiteralValue* value,
     bool is_integer) {
   return MakeGarbageCollected<CSSMathExpressionNumericLiteral>(value,
                                                                is_integer);
@@ -151,7 +151,7 @@
 }
 
 CSSMathExpressionNumericLiteral::CSSMathExpressionNumericLiteral(
-    CSSPrimitiveValue* value,
+    CSSNumericLiteralValue* value,
     bool is_integer)
     : CSSMathExpressionNode(UnitCategory(value->TypeWithCalcResolved()),
                             is_integer),
@@ -194,7 +194,7 @@
 }
 
 double CSSMathExpressionNumericLiteral::DoubleValue() const {
-  if (HasDoubleValue(TypeWithCalcResolved()))
+  if (HasDoubleValue(ResolvedUnitType()))
     return value_->GetDoubleValue();
   NOTREACHED();
   return 0;
@@ -239,8 +239,8 @@
                         To<CSSMathExpressionNumericLiteral>(other).value_);
 }
 
-CSSPrimitiveValue::UnitType
-CSSMathExpressionNumericLiteral::TypeWithCalcResolved() const {
+CSSPrimitiveValue::UnitType CSSMathExpressionNumericLiteral::ResolvedUnitType()
+    const {
   return value_->TypeWithCalcResolved();
 }
 
@@ -372,10 +372,9 @@
   // Simplify addition and subtraction between same types.
   if (op == CSSMathOperator::kAdd || op == CSSMathOperator::kSubtract) {
     if (left_category == right_side->Category()) {
-      CSSPrimitiveValue::UnitType left_type = left_side->TypeWithCalcResolved();
+      CSSPrimitiveValue::UnitType left_type = left_side->ResolvedUnitType();
       if (HasDoubleValue(left_type)) {
-        CSSPrimitiveValue::UnitType right_type =
-            right_side->TypeWithCalcResolved();
+        CSSPrimitiveValue::UnitType right_type = right_side->ResolvedUnitType();
         if (left_type == right_type) {
           return CSSMathExpressionNumericLiteral::Create(
               EvaluateOperator(left_side->DoubleValue(),
@@ -423,7 +422,7 @@
     if (op == CSSMathOperator::kDivide && !number)
       return nullptr;
 
-    CSSPrimitiveValue::UnitType other_type = other_side->TypeWithCalcResolved();
+    CSSPrimitiveValue::UnitType other_type = other_side->ResolvedUnitType();
     if (HasDoubleValue(other_type)) {
       return CSSMathExpressionNumericLiteral::Create(
           EvaluateOperator(other_side->DoubleValue(), number, op), other_type,
@@ -565,8 +564,8 @@
          operator_ == other.operator_;
 }
 
-CSSPrimitiveValue::UnitType
-CSSMathExpressionBinaryOperation::TypeWithCalcResolved() const {
+CSSPrimitiveValue::UnitType CSSMathExpressionBinaryOperation::ResolvedUnitType()
+    const {
   switch (category_) {
     case kCalcNumber:
       DCHECK_EQ(left_side_->Category(), kCalcNumber);
@@ -575,12 +574,11 @@
     case kCalcLength:
     case kCalcPercent: {
       if (left_side_->Category() == kCalcNumber)
-        return right_side_->TypeWithCalcResolved();
+        return right_side_->ResolvedUnitType();
       if (right_side_->Category() == kCalcNumber)
-        return left_side_->TypeWithCalcResolved();
-      CSSPrimitiveValue::UnitType left_type =
-          left_side_->TypeWithCalcResolved();
-      if (left_type == right_side_->TypeWithCalcResolved())
+        return left_side_->ResolvedUnitType();
+      CSSPrimitiveValue::UnitType left_type = left_side_->ResolvedUnitType();
+      if (left_type == right_side_->ResolvedUnitType())
         return left_type;
       return CSSPrimitiveValue::UnitType::kUnknown;
     }
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h
index 80c34c5..161e03e1b 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.h
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -41,6 +41,8 @@
 
 namespace blink {
 
+class CSSNumericLiteralValue;
+
 // The order of this enum should not change since its elements are used as
 // indices in the addSubtractResult matrix.
 enum CalculationCategory {
@@ -81,7 +83,12 @@
   }
 
   CalculationCategory Category() const { return category_; }
-  virtual CSSPrimitiveValue::UnitType TypeWithCalcResolved() const = 0;
+
+  // Returns the unit type of the math expression *without doing any type
+  // conversion* (e.g., 1px + 1em needs type conversion to resolve).
+  // Returns |UnitType::kUnknown| if type conversion is required.
+  virtual CSSPrimitiveValue::UnitType ResolvedUnitType() const = 0;
+
   bool IsInteger() const { return is_integer_; }
 
   bool IsNestedCalc() const { return is_nested_calc_; }
@@ -100,16 +107,16 @@
   bool is_nested_calc_ = false;
 };
 
-// TODO(crbug.com/825895): Make it store a CSSNumericLiteralValue
 class CORE_EXPORT CSSMathExpressionNumericLiteral final
     : public CSSMathExpressionNode {
  public:
-  static CSSMathExpressionNumericLiteral* Create(CSSPrimitiveValue* value,
+  static CSSMathExpressionNumericLiteral* Create(CSSNumericLiteralValue* value,
                                                  bool is_integer = false);
   static CSSMathExpressionNumericLiteral*
   Create(double value, CSSPrimitiveValue::UnitType type, bool is_integer);
 
-  CSSMathExpressionNumericLiteral(CSSPrimitiveValue* value, bool is_integer);
+  CSSMathExpressionNumericLiteral(CSSNumericLiteralValue* value,
+                                  bool is_integer);
 
   bool IsNumericLiteral() const final { return true; }
 
@@ -125,11 +132,11 @@
   void AccumulateLengthArray(CSSLengthArray& length_array,
                              double multiplier) const final;
   bool operator==(const CSSMathExpressionNode& other) const final;
-  CSSPrimitiveValue::UnitType TypeWithCalcResolved() const final;
+  CSSPrimitiveValue::UnitType ResolvedUnitType() const final;
   void Trace(blink::Visitor* visitor) final;
 
  private:
-  Member<CSSPrimitiveValue> value_;
+  Member<CSSNumericLiteralValue> value_;
 };
 
 template <>
@@ -175,7 +182,7 @@
                              double multiplier) const final;
   String CustomCSSText() const final;
   bool operator==(const CSSMathExpressionNode& exp) const final;
-  CSSPrimitiveValue::UnitType TypeWithCalcResolved() const final;
+  CSSPrimitiveValue::UnitType ResolvedUnitType() const final;
   void Trace(blink::Visitor* visitor) final;
 
  private:
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.cc b/third_party/blink/renderer/core/css/css_math_function_value.cc
index 6f16911..8a47eecf 100644
--- a/third_party/blink/renderer/core/css/css_math_function_value.cc
+++ b/third_party/blink/renderer/core/css/css_math_function_value.cc
@@ -75,6 +75,11 @@
   return UnitType::kUnknown;
 }
 
+bool CSSMathFunctionValue::MayHaveRelativeUnit() const {
+  UnitType resolved_type = expression_->ResolvedUnitType();
+  return IsRelativeUnit(resolved_type) || resolved_type == UnitType::kUnknown;
+}
+
 double CSSMathFunctionValue::DoubleValue() const {
   // TODO(crbug.com/979895): Make sure this function is called only when
   // applicable.
@@ -83,7 +88,7 @@
 
 double CSSMathFunctionValue::ComputeSeconds() const {
   DCHECK_EQ(kCalcTime, expression_->Category());
-  UnitType current_type = expression_->TypeWithCalcResolved();
+  UnitType current_type = expression_->ResolvedUnitType();
   if (current_type == UnitType::kSeconds)
     return GetDoubleValue();
   if (current_type == UnitType::kMilliseconds)
@@ -94,7 +99,7 @@
 
 double CSSMathFunctionValue::ComputeDegrees() const {
   DCHECK_EQ(kCalcAngle, expression_->Category());
-  UnitType current_type = expression_->TypeWithCalcResolved();
+  UnitType current_type = expression_->ResolvedUnitType();
   switch (current_type) {
     case UnitType::kDegrees:
       return GetDoubleValue();
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.h b/third_party/blink/renderer/core/css/css_math_function_value.h
index 77e4669..acfb6e8 100644
--- a/third_party/blink/renderer/core/css/css_math_function_value.h
+++ b/third_party/blink/renderer/core/css/css_math_function_value.h
@@ -32,6 +32,7 @@
   }
 
   UnitType TypeWithMathFunctionResolved() const;
+  bool MayHaveRelativeUnit() const;
 
   CalculationCategory Category() const { return expression_->Category(); }
   bool IsInt() const { return expression_->IsInteger(); }
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_test.cc b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
index 0b9944b..eb7f504 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value_test.cc
+++ b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
@@ -19,7 +19,7 @@
   UnitType unit_type;
 };
 
-CSSPrimitiveValue* Create(UnitValue v) {
+CSSNumericLiteralValue* Create(UnitValue v) {
   return CSSNumericLiteralValue::Create(v.value, v.unit_type);
 }
 
diff --git a/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc b/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
index 2027d02..f4d3b80 100644
--- a/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
@@ -111,7 +111,7 @@
 
 CSSNumericValue* CalcToNumericValue(const CSSMathExpressionNode& root) {
   if (root.IsNumericLiteral()) {
-    const CSSPrimitiveValue::UnitType unit = root.TypeWithCalcResolved();
+    const CSSPrimitiveValue::UnitType unit = root.ResolvedUnitType();
     auto* value = CSSUnitValue::Create(
         root.DoubleValue(), unit == CSSPrimitiveValue::UnitType::kInteger
                                 ? CSSPrimitiveValue::UnitType::kNumber
diff --git a/third_party/blink/renderer/core/css/resolver/transform_builder.cc b/third_party/blink/renderer/core/css/resolver/transform_builder.cc
index 47bd276..7fffb5b 100644
--- a/third_party/blink/renderer/core/css/resolver/transform_builder.cc
+++ b/third_party/blink/renderer/core/css/resolver/transform_builder.cc
@@ -109,17 +109,9 @@
 
     for (const CSSValue* item : *transform_value) {
       const auto& primitive_value = To<CSSPrimitiveValue>(*item);
-
-      if (primitive_value.IsCalculated()) {
-        // TODO(xiaochengh): Get type from CSSMathFunctionValue directly.
-        CSSPrimitiveValue::UnitType resolved_type =
-            To<CSSMathFunctionValue>(primitive_value)
-                .ExpressionNode()
-                ->TypeWithCalcResolved();
-        if (CSSPrimitiveValue::IsRelativeUnit(resolved_type) ||
-            resolved_type == CSSPrimitiveValue::UnitType::kUnknown) {
-          return true;
-        }
+      if (primitive_value.IsCalculated() &&
+          To<CSSMathFunctionValue>(primitive_value).MayHaveRelativeUnit()) {
+        return true;
       }
 
       if (CSSPrimitiveValue::IsRelativeUnit(
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index a532335fb..fa5ef09 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3860,7 +3860,7 @@
          !fetcher_->BlockingRequestCount() && !IsDelayingLoadEvent() &&
          !javascript_url_task_handle_.IsActive() &&
          load_event_progress_ != kLoadEventInProgress &&
-         AllDescendantsAreComplete(this);
+         AllDescendantsAreComplete(this) && !Fetcher()->IsInRequestResource();
 }
 
 void Document::Abort() {
diff --git a/third_party/blink/renderer/core/editing/selection.idl b/third_party/blink/renderer/core/editing/selection.idl
index d6d5cf0..c789c37 100644
--- a/third_party/blink/renderer/core/editing/selection.idl
+++ b/third_party/blink/renderer/core/editing/selection.idl
@@ -29,6 +29,7 @@
 
 // https://w3c.github.io/selection-api/#selection-interface
 [
+    Exposed=Window,
     ImplementedAs=DOMSelection
 ] interface Selection {
     [MeasureAs=SelectionAnchorNode] readonly attribute Node? anchorNode;
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
index ab60354..82fd9ca 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -224,8 +224,7 @@
     base::TimeTicks finish_time,
     int64_t encoded_data_length,
     int64_t decoded_body_length,
-    bool should_report_corb_blocking,
-    ResponseSource response_source) {
+    bool should_report_corb_blocking) {
   LocalFrame& frame = frame_or_imported_document_->GetFrame();
   DocumentLoader& document_loader =
       frame_or_imported_document_->GetMasterDocumentLoader();
@@ -243,9 +242,7 @@
       idleness_detector->OnDidLoadResource();
     }
   }
-  if (response_source == ResponseSource::kNotFromMemoryCache) {
-    document.CheckCompleted();
-  }
+  document.CheckCompleted();
 }
 
 void ResourceLoadObserverForFrame::DidFailLoading(const KURL&,
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
index aadefc6..f496d3f 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -51,8 +51,7 @@
                         base::TimeTicks finish_time,
                         int64_t encoded_data_length,
                         int64_t decoded_body_length,
-                        bool should_report_corb_blocking,
-                        ResponseSource) override;
+                        bool should_report_corb_blocking) override;
   void DidFailLoading(const KURL&,
                       uint64_t identifier,
                       const ResourceError&,
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
index b44f94ff..75c6bfec 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
@@ -88,8 +88,7 @@
     base::TimeTicks finish_time,
     int64_t encoded_data_length,
     int64_t decoded_body_length,
-    bool should_report_corb_blocking,
-    ResponseSource) {
+    bool should_report_corb_blocking) {
   probe::DidFinishLoading(probe_, identifier, nullptr, finish_time,
                           encoded_data_length, decoded_body_length,
                           should_report_corb_blocking);
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
index b18ad04..534488fe 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
@@ -48,8 +48,7 @@
                         base::TimeTicks finish_time,
                         int64_t encoded_data_length,
                         int64_t decoded_body_length,
-                        bool should_report_corb_blocking,
-                        ResponseSource) override;
+                        bool should_report_corb_blocking) override;
   void DidFailLoading(const KURL&,
                       uint64_t identifier,
                       const ResourceError&,
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
index 0304277b..d2698a5a 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -389,46 +389,7 @@
   std::unique_ptr<ImageRecord> record = CreateImageRecord(
       background_image_id.first, background_image_id.second, visual_size);
   size_ordered_set_.insert(record->AsWeakPtr());
-  InsertVisibleRecord(background_image_id, record);
-}
-
-void ImageRecordsManager::InsertVisibleRecord(
-    const BackgroundImageId& background_image_id,
-    std::unique_ptr<ImageRecord>& record) {
-  visible_background_image_map_
-      .insert(background_image_id.first, Vector<std::unique_ptr<ImageRecord>>())
-      .stored_value->value.push_back(std::move(record));
-}
-
-bool ImageRecordsManager::IsRecordedVisibleNode(
-    const BackgroundImageId& background_image_id) const {
-  if (!visible_background_image_map_.Contains(background_image_id.first))
-    return false;
-  auto it = visible_background_image_map_.find(background_image_id.first);
-  if (it == visible_background_image_map_.end())
-    return false;
-
-  for (auto& record : it->value) {
-    if (background_image_id.second == record->cached_image)
-      return true;
-  }
-  return false;
-}
-
-base::WeakPtr<ImageRecord> ImageRecordsManager::FindVisibleRecord(
-    const BackgroundImageId& background_image_id) const {
-  if (!visible_background_image_map_.Contains(background_image_id.first))
-    return nullptr;
-  auto it = visible_background_image_map_.find(background_image_id.first);
-  if (it == visible_background_image_map_.end())
-    return nullptr;
-
-  for (auto& record : it->value) {
-    if (background_image_id.second == record->cached_image)
-      return record->AsWeakPtr();
-  }
-  NOTREACHED();
-  return nullptr;
+  visible_background_image_map_.insert(background_image_id, std::move(record));
 }
 
 std::unique_ptr<ImageRecord> ImageRecordsManager::CreateImageRecord(
@@ -446,7 +407,7 @@
 }
 
 ImageRecord* ImageRecordsManager::FindLargestPaintCandidate() const {
-  DCHECK_LE(visible_node_map_.size() + visible_background_image_map_.size(),
+  DCHECK_EQ(visible_node_map_.size() + visible_background_image_map_.size(),
             size_ordered_set_.size());
   for (auto it = size_ordered_set_.begin(); it != size_ordered_set_.end();
        ++it) {
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
index c222f52..dd7cafd8 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -89,7 +89,9 @@
     return visible_node_map_.Contains(node_id);
   }
   bool IsRecordedVisibleNode(
-      const BackgroundImageId& background_image_id) const;
+      const BackgroundImageId& background_image_id) const {
+    return visible_background_image_map_.Contains(background_image_id);
+  }
   bool IsRecordedInvisibleNode(const DOMNodeId& node_id) const {
     return invisible_node_ids_.Contains(node_id);
   }
@@ -106,8 +108,8 @@
   }
   inline bool WasVisibleNodeLoaded(
       const BackgroundImageId& background_image_id) const {
-    DCHECK(IsRecordedVisibleNode(background_image_id));
-    return FindVisibleRecord(background_image_id)->loaded;
+    DCHECK(visible_background_image_map_.Contains(background_image_id));
+    return visible_background_image_map_.at(background_image_id)->loaded;
   }
   void OnImageLoaded(const DOMNodeId&, unsigned current_frame_index);
   void OnImageLoaded(const BackgroundImageId&, unsigned current_frame_index);
@@ -138,11 +140,12 @@
     DCHECK(visible_node_map_.Contains(node_id));
     return visible_node_map_.find(node_id)->value->AsWeakPtr();
   }
-  void InsertVisibleRecord(const BackgroundImageId&,
-                           std::unique_ptr<ImageRecord>&);
-
-  base::WeakPtr<ImageRecord> FindVisibleRecord(
-      const BackgroundImageId& background_image_id) const;
+  inline base::WeakPtr<ImageRecord> FindVisibleRecord(
+      const BackgroundImageId& background_image_id) const {
+    DCHECK(visible_background_image_map_.Contains(background_image_id));
+    return visible_background_image_map_.find(background_image_id)
+        ->value->AsWeakPtr();
+  }
   std::unique_ptr<ImageRecord> CreateImageRecord(
       const DOMNodeId&,
       const ImageResourceContent* cached_image,
@@ -160,7 +163,7 @@
   // We will never destroy the pointers within |visible_node_map_|. Once created
   // they will exist for the whole life cycle of |visible_node_map_|.
   HashMap<DOMNodeId, std::unique_ptr<ImageRecord>> visible_node_map_;
-  HashMap<DOMNodeId, Vector<std::unique_ptr<ImageRecord>>>
+  HashMap<BackgroundImageId, std::unique_ptr<ImageRecord>>
       visible_background_image_map_;
   HashSet<DOMNodeId> invisible_node_ids_;
   // Use |DOMNodeId| instead of |ImageRecord|* for the efficiency of inserting
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index e8f18cb..15478c4 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -106,18 +106,9 @@
   }
 
   size_t CountVisibleBackgroundImageRecords() {
-    auto& visible_background_image_map =
-        GetPaintTimingDetector()
-            .GetImagePaintTimingDetector()
-            ->records_manager_.visible_background_image_map_;
-
-    int count = 0;
-    for (auto it = visible_background_image_map.begin();
-         it != visible_background_image_map.end(); ++it) {
-      count += it->value.size();
-    }
-
-    return count;
+    return GetPaintTimingDetector()
+        .GetImagePaintTimingDetector()
+        ->records_manager_.visible_background_image_map_.size();
   }
 
   size_t CountChildFrameRecords() {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 7eb9e44..88805eb 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -1095,11 +1095,6 @@
     current->child_needs_compositing_inputs_update_ = true;
     if (Compositor() &&
         current->GetLayoutObject().ShouldApplyStrictContainment() &&
-        // TODO(rego): Disable CompositingInputsRoot optimization if the
-        // "contain: strict" element has "position: sticky". This was causing
-        // crashes because PaintLayerScrollableArea::sticky_constraints_map_ was
-        // not updated correctly in some cases (see crbug.com/949887).
-        !current->GetLayoutObject().IsStickyPositioned() &&
         // TODO(rego): Disable CompositingInputsRoot optimization for iframes
         // (see crbug.com/953159).
         !current->GetLayoutObject().IsLayoutIFrame())
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 ca59e6d..8111578 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
@@ -996,16 +996,16 @@
   DCHECK(interval_.begin.IsFinite());
 
   double active_time = std::max(elapsed - interval_.begin.Value(), 0.0);
-  double simple_duration_value = simple_duration.Value();
-  double repeating_duration = RepeatingDuration().Value();
+  SMILTime repeating_duration = RepeatingDuration();
   if (elapsed >= interval_.end || active_time > repeating_duration) {
-    unsigned repeat =
-        static_cast<unsigned>(repeating_duration / simple_duration_value);
-    if (!fmod(repeating_duration, simple_duration_value))
+    unsigned repeat = static_cast<unsigned>(repeating_duration.Value() /
+                                            simple_duration.Value());
+    if (!fmod(repeating_duration.Value(), simple_duration.Value()))
       return repeat - 1;
     return repeat;
   }
-  unsigned repeat = static_cast<unsigned>(active_time / simple_duration_value);
+  unsigned repeat =
+      static_cast<unsigned>(active_time / simple_duration.Value());
   return repeat;
 }
 
@@ -1020,9 +1020,8 @@
   DCHECK(simple_duration.IsFinite());
   DCHECK(interval_.begin.IsFinite());
 
+  SMILTime repeating_duration = RepeatingDuration();
   double active_time = elapsed - interval_.begin.Value();
-  double simple_duration_value = simple_duration.Value();
-  double repeating_duration = RepeatingDuration().Value();
   if (elapsed >= interval_.end || active_time > repeating_duration) {
     // Use the interval to compute the interval position if we've passed the
     // interval end, otherwise use the "repeating duration". This prevents a
@@ -1032,16 +1031,16 @@
     if (elapsed >= interval_.end)
       last_active_duration = interval_.end.Value() - interval_.begin.Value();
     else
-      last_active_duration = repeating_duration;
-    double percent = last_active_duration / simple_duration_value;
+      last_active_duration = repeating_duration.Value();
+    double percent = last_active_duration / simple_duration.Value();
     percent = percent - floor(percent);
     float epsilon = std::numeric_limits<float>::epsilon();
     if (percent < epsilon || 1 - percent < epsilon)
       return 1.0f;
     return clampTo<float>(percent);
   }
-  double simple_time = fmod(active_time, simple_duration_value);
-  return clampTo<float>(simple_time / simple_duration_value);
+  double simple_time = fmod(active_time, simple_duration.Value());
+  return clampTo<float>(simple_time / simple_duration.Value());
 }
 
 SMILTime SVGSMILElement::CalculateNextProgressTime(double elapsed) const {
diff --git a/third_party/blink/renderer/core/url/url_search_params.cc b/third_party/blink/renderer/core/url/url_search_params.cc
index fd43bb8..a1cc2fc 100644
--- a/third_party/blink/renderer/core/url/url_search_params.cc
+++ b/third_party/blink/renderer/core/url/url_search_params.cc
@@ -133,8 +133,10 @@
 }
 
 static String DecodeString(String input) {
+  // |DecodeURLMode::kUTF8| is used because "UTF-8 decode without BOM" should
+  // be performed (see https://url.spec.whatwg.org/#concept-urlencoded-parser).
   return DecodeURLEscapeSequences(input.Replace('+', ' '),
-                                  DecodeURLMode::kUTF8OrIsomorphic);
+                                  DecodeURLMode::kUTF8);
 }
 
 void URLSearchParams::SetInputWithoutUpdate(const String& query_string) {
diff --git a/third_party/blink/renderer/core/workers/worklet.cc b/third_party/blink/renderer/core/workers/worklet.cc
index 7dde393..23f73cf 100644
--- a/third_party/blink/renderer/core/workers/worklet.cc
+++ b/third_party/blink/renderer/core/workers/worklet.cc
@@ -31,9 +31,12 @@
 }
 
 Worklet::~Worklet() {
+  DCHECK(!HasPendingTasks());
+}
+
+void Worklet::Dispose() {
   for (const auto& proxy : proxies_)
     proxy->WorkletObjectDestroyed();
-  DCHECK(!HasPendingTasks());
 }
 
 // Implementation of the first half of the "addModule(moduleURL, options)"
diff --git a/third_party/blink/renderer/core/workers/worklet.h b/third_party/blink/renderer/core/workers/worklet.h
index 1d7cbf7..f0a802b 100644
--- a/third_party/blink/renderer/core/workers/worklet.h
+++ b/third_party/blink/renderer/core/workers/worklet.h
@@ -27,13 +27,13 @@
                             public ContextLifecycleObserver {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(Worklet);
-  // Eager finalization is needed to notify parent object destruction of the
-  // GC-managed messaging proxy and to initiate worklet termination.
-  EAGERLY_FINALIZE();
+  USING_PRE_FINALIZER(Worklet, Dispose);
 
  public:
   ~Worklet() override;
 
+  void Dispose();
+
   // Worklet.idl
   // addModule() imports ES6 module scripts.
   ScriptPromise addModule(ScriptState*,
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index daa8cbe..5ae69cd 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -235,8 +235,6 @@
     if (!origin_tainted_by_content_ && !canvas_pattern->OriginClean()) {
       SetOriginTaintedByContent();
     }
-    if (canvas_pattern->GetPattern()->IsTextureBacked())
-      DisableDeferral(kDisableDeferralReasonUsingTextureBackedPattern);
     canvas_style = CanvasStyle::CreateFromPattern(canvas_pattern);
   }
 
diff --git a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
index 9f644349..aa4d235 100644
--- a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
@@ -12,22 +12,6 @@
 static const int kWidth = 50;
 static const int kHeight = 75;
 static const float kZoom = 1.0;
-static const float kDeviceScaleFactor = 1.23;
-
-class PaintRenderingContext2DTest : public testing::Test {
- protected:
-  void SetUp() override;
-
-  Persistent<PaintRenderingContext2D> ctx_;
-};
-
-void PaintRenderingContext2DTest::SetUp() {
-  PaintRenderingContext2DSettings* context_settings =
-      PaintRenderingContext2DSettings::Create();
-  context_settings->setAlpha(false);
-  ctx_ = MakeGarbageCollected<PaintRenderingContext2D>(
-      IntSize(kWidth, kHeight), context_settings, kZoom, kDeviceScaleFactor);
-}
 
 void TrySettingStrokeStyle(PaintRenderingContext2D* ctx,
                            const String& expected,
@@ -41,56 +25,78 @@
   EXPECT_EQ(expected, result.GetAsString());
 }
 
-TEST_F(PaintRenderingContext2DTest, testParseColorOrCurrentColor) {
-  TrySettingStrokeStyle(ctx_.Get(), "#0000ff", "blue");
-  TrySettingStrokeStyle(ctx_.Get(), "#000000", "currentColor");
+TEST(PaintRenderingContext2DTest, testParseColorOrCurrentColor) {
+  PaintRenderingContext2DSettings* context_settings =
+      PaintRenderingContext2DSettings::Create();
+  context_settings->setAlpha(false);
+  PaintRenderingContext2D* ctx = MakeGarbageCollected<PaintRenderingContext2D>(
+      IntSize(kWidth, kHeight), context_settings, kZoom,
+      1.0 /* device_scale_factor */);
+  TrySettingStrokeStyle(ctx, "#0000ff", "blue");
+  TrySettingStrokeStyle(ctx, "#000000", "currentColor");
 }
 
-TEST_F(PaintRenderingContext2DTest, testWidthAndHeight) {
-  EXPECT_EQ(kWidth, ctx_->Width());
-  EXPECT_EQ(kHeight, ctx_->Height());
+TEST(PaintRenderingContext2DTest, testWidthAndHeight) {
+  PaintRenderingContext2DSettings* context_settings =
+      PaintRenderingContext2DSettings::Create();
+  PaintRenderingContext2D* ctx = MakeGarbageCollected<PaintRenderingContext2D>(
+      IntSize(kWidth, kHeight), context_settings, kZoom,
+      1.0 /* device_scale_factor */);
+  EXPECT_EQ(kWidth, ctx->Width());
+  EXPECT_EQ(kHeight, ctx->Height());
 }
 
-TEST_F(PaintRenderingContext2DTest, testBasicState) {
+TEST(PaintRenderingContext2DTest, testBasicState) {
+  PaintRenderingContext2DSettings* context_settings =
+      PaintRenderingContext2DSettings::Create();
+  PaintRenderingContext2D* ctx = MakeGarbageCollected<PaintRenderingContext2D>(
+      IntSize(kWidth, kHeight), context_settings, kZoom,
+      1.0 /* device_scale_factor */);
+
   const double kShadowBlurBefore = 2;
   const double kShadowBlurAfter = 3;
 
   const String line_join_before = "bevel";
   const String line_join_after = "round";
 
-  ctx_->setShadowBlur(kShadowBlurBefore);
-  ctx_->setLineJoin(line_join_before);
-  EXPECT_EQ(kShadowBlurBefore, ctx_->shadowBlur());
-  EXPECT_EQ(line_join_before, ctx_->lineJoin());
+  ctx->setShadowBlur(kShadowBlurBefore);
+  ctx->setLineJoin(line_join_before);
+  EXPECT_EQ(kShadowBlurBefore, ctx->shadowBlur());
+  EXPECT_EQ(line_join_before, ctx->lineJoin());
 
-  ctx_->save();
+  ctx->save();
 
-  ctx_->setShadowBlur(kShadowBlurAfter);
-  ctx_->setLineJoin(line_join_after);
-  EXPECT_EQ(kShadowBlurAfter, ctx_->shadowBlur());
-  EXPECT_EQ(line_join_after, ctx_->lineJoin());
+  ctx->setShadowBlur(kShadowBlurAfter);
+  ctx->setLineJoin(line_join_after);
+  EXPECT_EQ(kShadowBlurAfter, ctx->shadowBlur());
+  EXPECT_EQ(line_join_after, ctx->lineJoin());
 
-  ctx_->restore();
+  ctx->restore();
 
-  EXPECT_EQ(kShadowBlurBefore, ctx_->shadowBlur());
-  EXPECT_EQ(line_join_before, ctx_->lineJoin());
+  EXPECT_EQ(kShadowBlurBefore, ctx->shadowBlur());
+  EXPECT_EQ(line_join_before, ctx->lineJoin());
 }
 
-TEST_F(PaintRenderingContext2DTest, setTransformWithDeviceScaleFactor) {
-  DOMMatrix* matrix = ctx_->getTransform();
+TEST(PaintRenderingContext2DTest, setTransformWithDeviceScaleFactor) {
+  PaintRenderingContext2DSettings* context_settings =
+      PaintRenderingContext2DSettings::Create();
+  float device_scale_factor = 1.23;
+  PaintRenderingContext2D* ctx = MakeGarbageCollected<PaintRenderingContext2D>(
+      IntSize(kWidth, kHeight), context_settings, kZoom, device_scale_factor);
+  DOMMatrix* matrix = ctx->getTransform();
   EXPECT_TRUE(matrix->isIdentity());
-  ctx_->setTransform(2.1, 2.5, 1.4, 2.3, 20, 50);
-  matrix = ctx_->getTransform();
+  ctx->setTransform(2.1, 2.5, 1.4, 2.3, 20, 50);
+  matrix = ctx->getTransform();
   double epsilon = 0.000001;
-  EXPECT_NEAR(matrix->a(), 2.1 / kDeviceScaleFactor, epsilon);
-  EXPECT_NEAR(matrix->b(), 2.5 / kDeviceScaleFactor, epsilon);
-  EXPECT_NEAR(matrix->c(), 1.4 / kDeviceScaleFactor, epsilon);
-  EXPECT_NEAR(matrix->d(), 2.3 / kDeviceScaleFactor, epsilon);
-  EXPECT_NEAR(matrix->e(), 20 / kDeviceScaleFactor, epsilon);
-  EXPECT_NEAR(matrix->f(), 50 / kDeviceScaleFactor, epsilon);
+  EXPECT_NEAR(matrix->a(), 2.1 / device_scale_factor, epsilon);
+  EXPECT_NEAR(matrix->b(), 2.5 / device_scale_factor, epsilon);
+  EXPECT_NEAR(matrix->c(), 1.4 / device_scale_factor, epsilon);
+  EXPECT_NEAR(matrix->d(), 2.3 / device_scale_factor, epsilon);
+  EXPECT_NEAR(matrix->e(), 20 / device_scale_factor, epsilon);
+  EXPECT_NEAR(matrix->f(), 50 / device_scale_factor, epsilon);
 }
 
-TEST_F(PaintRenderingContext2DTest, setTransformWithDefaultDeviceScaleFactor) {
+TEST(PaintRenderingContext2DTest, setTransformWithDefaultDeviceScaleFactor) {
   PaintRenderingContext2DSettings* context_settings =
       PaintRenderingContext2DSettings::Create();
   PaintRenderingContext2D* ctx = MakeGarbageCollected<PaintRenderingContext2D>(
diff --git a/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
index 0ece792..502d9b5 100644
--- a/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
@@ -244,8 +244,8 @@
       return;
     }
     video_frame->AddDestructionObserver(media::BindToCurrentLoop(
-        WTF::BindRepeating(&VEAEncoder::FrameFinished, WrapRefCounted(this),
-                           WTF::Passed(std::move(input_buffer)))));
+        WTF::Bind(&VEAEncoder::FrameFinished, WrapRefCounted(this),
+                  std::move(input_buffer))));
     libyuv::I420Copy(frame->visible_data(media::VideoFrame::kYPlane),
                      frame->stride(media::VideoFrame::kYPlane),
                      frame->visible_data(media::VideoFrame::kUPlane),
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
index 06ee37bb..8091117 100644
--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -264,11 +264,11 @@
         video_frame->natural_size());
   }
   wrapped_frame->AddDestructionObserver(media::BindToCurrentLoop(
-      WTF::BindRepeating(&VideoTrackRecorder::Counter::DecreaseCount,
-                         num_frames_in_encode_->GetWeakPtr())));
-  wrapped_frame->AddDestructionObserver(ConvertToBaseCallback(
-      CrossThreadBindRepeating([](scoped_refptr<VideoFrame> video_frame) {},
-                               std::move(video_frame))));
+      WTF::Bind(&VideoTrackRecorder::Counter::DecreaseCount,
+                num_frames_in_encode_->GetWeakPtr())));
+  wrapped_frame->AddDestructionObserver(ConvertToBaseOnceCallback(
+      CrossThreadBindOnce([](scoped_refptr<VideoFrame> video_frame) {},
+                          std::move(video_frame))));
   num_frames_in_encode_->IncreaseCount();
 
   PostCrossThreadTask(*encoding_task_runner_.get(), FROM_HERE,
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index 9bc0fea..1cedaaea 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -664,6 +664,7 @@
           "native_file_system/file_system_get_directory_options.idl",
           "native_file_system/file_system_get_file_options.idl",
           "native_file_system/file_system_handle_permission_descriptor.idl",
+          "native_file_system/file_system_remove_options.idl",
           "native_file_system/get_system_directory_options.idl",
           "native_file_system/native_file_system_directory_iterator_entry.idl",
           "nfc/ndef_message.idl",
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl b/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl
index 02dbcf2..1e96b32 100644
--- a/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl
+++ b/third_party/blink/renderer/modules/native_file_system/file_system_directory_handle.idl
@@ -12,7 +12,7 @@
     [CallWith=ScriptState] Promise<FileSystemDirectoryHandle> getDirectory(USVString name, optional FileSystemGetDirectoryOptions options);
     [CallWith=ScriptState] object getEntries();
 
-    [CallWith=ScriptState] Promise<void> removeRecursively();
+    [CallWith=ScriptState] Promise<void> removeEntry(USVString name, optional FileSystemRemoveOptions options);
 
     [CallWith=ScriptState]
     static Promise<FileSystemDirectoryHandle> getSystemDirectory(GetSystemDirectoryOptions options);
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl b/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl
index c96dfd6..97d0efd 100644
--- a/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl
+++ b/third_party/blink/renderer/modules/native_file_system/file_system_handle.idl
@@ -16,8 +16,6 @@
 
     readonly attribute USVString name;
 
-    [CallWith=ScriptState] Promise<void> remove();
-
     [CallWith = ScriptState] Promise<PermissionState> queryPermission(
         optional FileSystemHandlePermissionDescriptor descriptor);
     [CallWith = ScriptState] Promise<PermissionState> requestPermission(
diff --git a/third_party/blink/renderer/modules/native_file_system/file_system_remove_options.idl b/third_party/blink/renderer/modules/native_file_system/file_system_remove_options.idl
new file mode 100644
index 0000000..f3f8566
--- /dev/null
+++ b/third_party/blink/renderer/modules/native_file_system/file_system_remove_options.idl
@@ -0,0 +1,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.
+
+// https://wicg.github.io/native-file-system/#dictdef-filesystemremoveoptions
+dictionary FileSystemRemoveOptions {
+  boolean recursive = false;
+};
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
index d10d1d3..29ce19b 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/fileapi/file_error.h"
 #include "third_party/blink/renderer/modules/native_file_system/file_system_get_directory_options.h"
 #include "third_party/blink/renderer/modules/native_file_system/file_system_get_file_options.h"
+#include "third_party/blink/renderer/modules/native_file_system/file_system_remove_options.h"
 #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h"
 #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -111,13 +112,15 @@
   return ScriptValue(script_state, result);
 }
 
-ScriptPromise NativeFileSystemDirectoryHandle::removeRecursively(
-    ScriptState* script_state) {
+ScriptPromise NativeFileSystemDirectoryHandle::removeEntry(
+    ScriptState* script_state,
+    const String& name,
+    const FileSystemRemoveOptions* options) {
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise result = resolver->Promise();
 
-  mojo_ptr_->Remove(
-      true,
+  mojo_ptr_->RemoveEntry(
+      name, options->recursive(),
       WTF::Bind(
           [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result) {
             if (result->error_code == base::File::FILE_OK) {
@@ -177,11 +180,6 @@
   return result;
 }
 
-void NativeFileSystemDirectoryHandle::RemoveImpl(
-    base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr)> callback) {
-  mojo_ptr_->Remove(/*recursive=*/false, std::move(callback));
-}
-
 void NativeFileSystemDirectoryHandle::QueryPermissionImpl(
     bool writable,
     base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) {
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
index 9c2b199c..8af1c6f 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
@@ -11,6 +11,7 @@
 namespace blink {
 class FileSystemGetDirectoryOptions;
 class FileSystemGetFileOptions;
+class FileSystemRemoveOptions;
 class GetSystemDirectoryOptions;
 
 class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
@@ -30,7 +31,9 @@
                              const String& name,
                              const FileSystemGetDirectoryOptions*);
   ScriptValue getEntries(ScriptState*);
-  ScriptPromise removeRecursively(ScriptState*);
+  ScriptPromise removeEntry(ScriptState*,
+                            const String& name,
+                            const FileSystemRemoveOptions*);
 
   static ScriptPromise getSystemDirectory(ScriptState*,
                                           const GetSystemDirectoryOptions*);
@@ -42,9 +45,6 @@
   }
 
  private:
-  void RemoveImpl(
-      base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr)>)
-      override;
   void QueryPermissionImpl(
       bool writable,
       base::OnceCallback<void(mojom::blink::PermissionStatus)>) override;
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
index 4644a34..efd2d85 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
@@ -94,11 +94,6 @@
   return result;
 }
 
-void NativeFileSystemFileHandle::RemoveImpl(
-    base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr)> callback) {
-  mojo_ptr_->Remove(std::move(callback));
-}
-
 void NativeFileSystemFileHandle::QueryPermissionImpl(
     bool writable,
     base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) {
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
index 296e385..53a13fc 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
@@ -30,9 +30,6 @@
   }
 
  private:
-  void RemoveImpl(
-      base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr)>)
-      override;
   void QueryPermissionImpl(
       bool writable,
       base::OnceCallback<void(mojom::blink::PermissionStatus)>) override;
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
index 5b528237b..dfa2fc518 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
@@ -33,23 +33,6 @@
                    std::move(e->entry_handle->get_directory())));
 }
 
-ScriptPromise NativeFileSystemHandle::remove(ScriptState* script_state) {
-  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise result = resolver->Promise();
-
-  RemoveImpl(WTF::Bind(
-      [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result) {
-        if (result->error_code == base::File::FILE_OK) {
-          resolver->Resolve();
-        } else {
-          resolver->Reject(file_error::CreateDOMException(result->error_code));
-        }
-      },
-      WrapPersistent(resolver)));
-
-  return result;
-}
-
 namespace {
 String MojoPermissionStatusToString(mojom::blink::PermissionStatus status) {
   switch (status) {
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h b/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
index 2422b03..b07a83c 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
@@ -30,7 +30,6 @@
   virtual bool isDirectory() const { return false; }
   const String& name() const { return name_; }
 
-  ScriptPromise remove(ScriptState*);
   ScriptPromise queryPermission(ScriptState*,
                                 const FileSystemHandlePermissionDescriptor*);
   ScriptPromise requestPermission(ScriptState*,
@@ -39,8 +38,6 @@
   virtual mojom::blink::NativeFileSystemTransferTokenPtr Transfer() = 0;
 
  private:
-  virtual void RemoveImpl(
-      base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr)>) = 0;
   virtual void QueryPermissionImpl(
       bool writable,
       base::OnceCallback<void(mojom::blink::PermissionStatus)>) = 0;
diff --git a/third_party/blink/renderer/platform/bindings/name_client.h b/third_party/blink/renderer/platform/bindings/name_client.h
index 5ffde8b..222ea1b 100644
--- a/third_party/blink/renderer/platform/bindings/name_client.h
+++ b/third_party/blink/renderer/platform/bindings/name_client.h
@@ -11,8 +11,31 @@
 
 namespace blink {
 
-// Provides classes with a human-readable name that can be used for inspecting
-// the object graph.
+// NameClient provides classes with a human-readable name that can be used for
+// inspecting the object graph.
+//
+// NameClient is aimed to provide web developers better idea about what object
+// instances (or the object reference subgraph held by the instances) is
+// consuming heap. It should provide actionable guidance for reducing memory for
+// a given website.
+//
+// NameClient should be inherited for classes which:
+// - is likely to be in a reference chain that is likely to hold a consierable
+//   amount of memory,
+// - Web developers would have a rough idea what it would mean, and
+//   (The name is exposed to DevTools)
+// - not ScriptWrappable (ScriptWrappable implements NameClient).
+//
+// Caveat:
+//   NameClient should be inherited near the root of the inheritance graph
+//   for Member<BaseClass> edges to be attributed correctly.
+//
+//   Do:
+//     class Foo : public GarbageCollected<Foo>, public NameClient {...};
+//
+//   Don't:
+//     class Bar : public GarbageCollected<Bar> {...};
+//     class Baz : public Bar, public NameClient {...};
 class PLATFORM_EXPORT NameClient {
  public:
   static constexpr bool HideInternalName() {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 79f80fa..dbb7f45 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -92,8 +92,13 @@
     const gpu::SyncToken& sync_token,
     bool lost_resource) {
   resource->WaitSyncToken(sync_token);
+
+  // TODO(khushalsagar): If multiple readers had access to this resource, losing
+  // it once should make sure subsequent releases don't try to recycle this
+  // resource.
+  // Also what about single buffered canvas?
   if (lost_resource)
-    resource->Abandon();
+    resource->NotifyResourceLost();
   if (resource_provider && !lost_resource && resource->IsRecycleable())
     resource_provider->RecycleResource(std::move(resource));
 }
@@ -932,6 +937,16 @@
   return sync_token();
 }
 
+void CanvasResourceSharedImage::NotifyResourceLost() {
+  owning_thread_data().is_lost = true;
+
+  // Since the texture params are in an unknown state, reset the cached tex
+  // params state for the resource.
+  owning_thread_data().needs_gl_filter_reset = true;
+  if (WeakProvider())
+    Provider()->NotifyTexParamsModified(this);
+}
+
 base::WeakPtr<WebGraphicsContext3DProviderWrapper>
 CanvasResourceSharedImage::ContextProviderWrapper() const {
   DCHECK(!is_cross_thread());
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h
index adf9df20..19735fd 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -52,7 +52,6 @@
     : public WTF::ThreadSafeRefCounted<CanvasResource> {
  public:
   virtual ~CanvasResource();
-  virtual void Abandon() { TearDown(); }
   virtual bool IsRecycleable() const = 0;
   virtual bool IsAccelerated() const = 0;
   virtual bool SupportsAcceleratedCompositing() const = 0;
@@ -94,11 +93,33 @@
     return 0;
   }
 
+  // Called when the resource is marked lost. Losing a resource does not mean
+  // that the backing memory has been destroyed, since the resource itself keeps
+  // a ref on that memory.
+  // It means that the consumer (commonly the compositor) can not provide a sync
+  // token for the resource to be safely recycled and its the GL state may be
+  // inconsistent with when the resource was given to the compositor. So it
+  // should not be recycled for writing again but can be safely read from.
+  virtual void NotifyResourceLost() {
+    // TODO(khushalsagar): Some implementations respect the don't write again
+    // policy but some don't. Fix that once shared images replace all
+    // accelerated use-cases.
+    Abandon();
+  }
+
  protected:
   CanvasResource(base::WeakPtr<CanvasResourceProvider>,
                  SkFilterQuality,
                  const CanvasColorParams&);
 
+  // Called during resource destruction if the resource is destroyed on a thread
+  // other than where it was created. This implies that no context associated
+  // cleanup can be done and any resources tied to the context may be leaked. As
+  // such, a resource must be deleted on the owning thread and this should only
+  // be called when the owning thread and its associated context was torn down
+  // before this resource could be deleted.
+  virtual void Abandon() { TearDown(); }
+
   virtual bool IsOverlayCandidate() const { return false; }
   virtual bool HasGpuMailbox() const = 0;
   virtual void TearDown() = 0;
@@ -336,6 +357,8 @@
     return nullptr;
   }
   void TakeSkImage(sk_sp<SkImage> image) final { NOTREACHED(); }
+  void NotifyResourceLost() final;
+
   GLuint GetTextureIdForBackendTexture() const {
     return owning_thread_data().texture_id;
   }
@@ -346,6 +369,7 @@
   bool has_read_access() const {
     return owning_thread_data().bitmap_image_read_refs > 0u;
   }
+  bool is_lost() const { return owning_thread_data().is_lost; }
 
  private:
   // These members are either only accessed on the owning thread, or are only
@@ -360,6 +384,7 @@
     size_t bitmap_image_read_refs = 0u;
     GLuint texture_id = 0u;
     MailboxSyncMode mailbox_sync_mode = kVerifiedSyncToken;
+    bool is_lost = false;
   };
 
   static void OnBitmapImageDestroyed(
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index a02cc968..7a7fb7c 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -566,7 +566,7 @@
     // If |resource_| is still being used by the compositor we need to create
     // a new resource or reuse a previously recycled one. This class holds one
     // reference so we check if there is more than one.
-    if (!resource_->HasOneRef()) {
+    if (!resource_->HasOneRef() || resource()->is_lost()) {
       DCHECK(!current_resource_has_write_access_)
           << "Write access must be released before sharing the resource";
 
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
index 2baad54..94b58217 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
@@ -154,7 +154,10 @@
 // checking the color classifiers.
 bool DarkModeFilter::ShouldApplyToColor(const Color& color, ElementRole role) {
   if (role == ElementRole::kBackground) {
-    DCHECK_NE(background_classifier_, nullptr);
+    // Calling get() is necessary below because operator<< in std::unique_ptr is
+    // a C++20 feature.
+    // TODO(https://crbug.com/980914): Drop .get() once we move to C++20.
+    DCHECK_NE(background_classifier_.get(), nullptr);
     return background_classifier_->ShouldInvertColor(color) ==
            DarkModeClassification::kApplyFilter;
   }
diff --git a/third_party/blink/renderer/platform/graphics/graphics_types.h b/third_party/blink/renderer/platform/graphics/graphics_types.h
index 4aeecec..9ff349d 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_types.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_types.h
@@ -128,7 +128,6 @@
 enum DisableDeferralReason {
   kDisableDeferralReasonUnknown =
       0,  // Should not appear in production histograms
-  kDisableDeferralReasonUsingTextureBackedPattern = 2,
   kDisableDeferralReasonLowEndDevice = 7,
   kDisableDeferralReasonCount,
 };
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index c459e1f3e..b7009907 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -31,6 +31,7 @@
 #include <limits>
 #include <utility>
 
+#include "base/auto_reset.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
@@ -619,8 +620,7 @@
 
   resource_load_observer_->DidFinishLoading(
       identifier, base::TimeTicks(), 0,
-      resource->GetResponse().DecodedBodyLength(), false,
-      ResourceLoadObserver::ResponseSource::kFromMemoryCache);
+      resource->GetResponse().DecodedBodyLength(), false);
 
   if (!is_static_data) {
     // Resources loaded from memory cache should be reported the first time
@@ -908,6 +908,8 @@
 Resource* ResourceFetcher::RequestResource(FetchParameters& params,
                                            const ResourceFactory& factory,
                                            ResourceClient* client) {
+  base::AutoReset<bool> r(&is_in_request_resource_, true);
+
   // If detached, we do very early return here to skip all processing below.
   if (properties_->IsDetached()) {
     return ResourceForBlockedRequest(
@@ -1816,8 +1818,7 @@
     resource_load_observer_->DidFinishLoading(
         resource->InspectorId(), response_end, encoded_data_length,
         resource->GetResponse().DecodedBodyLength(),
-        should_report_corb_blocking,
-        ResourceLoadObserver::ResponseSource::kNotFromMemoryCache);
+        should_report_corb_blocking);
   }
   resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadIfNeeded);
 }
@@ -2014,6 +2015,7 @@
     const KURL& url,
     mojom::RequestContextType request_context,
     const AtomicString& initiator_name) {
+  base::AutoReset<bool> r(&is_in_request_resource_, true);
   if (CachedResource(url))
     return;
   ResourceRequest resource_request(url);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 7cb73749..bea3bbfe 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -116,6 +116,10 @@
   // Returns whether this fetcher is detached from the associated context.
   bool IsDetached() const;
 
+  // Returns whether RequestResource or EmulateLoadStartedForInspector are being
+  // called.
+  bool IsInRequestResource() const { return is_in_request_resource_; }
+
   // Returns the observer object associated with this fetcher.
   ResourceLoadObserver* GetResourceLoadObserver() {
     // When detached, we must have a null observer.
@@ -406,6 +410,9 @@
 
   mojom::blink::BlobRegistryPtr blob_registry_ptr_;
 
+  // This is not in the bit field below because we want to use AutoReset.
+  bool is_in_request_resource_ = false;
+
   // 27 bits left
   bool auto_load_images_ : 1;
   bool images_enabled_ : 1;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index 59f9ef0..68b1978 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -143,8 +143,7 @@
                           base::TimeTicks finish_time,
                           int64_t encoded_data_length,
                           int64_t decoded_body_length,
-                          bool should_report_corb_blocking,
-                          ResponseSource) override {}
+                          bool should_report_corb_blocking) override {}
     void DidFailLoading(const KURL&,
                         uint64_t identifier,
                         const ResourceError&,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
index 9447676..17eb64dc2 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -85,8 +85,7 @@
                                 base::TimeTicks finish_time,
                                 int64_t encoded_data_length,
                                 int64_t decoded_body_length,
-                                bool should_report_corb_blocking,
-                                ResponseSource) = 0;
+                                bool should_report_corb_blocking) = 0;
 
   // Called when a request fails.
   virtual void DidFailLoading(const KURL&,
diff --git a/third_party/blink/web_tests/FlagExpectations/use-vulkan=native b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
new file mode 100644
index 0000000..92a68d1
--- /dev/null
+++ b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
@@ -0,0 +1,155 @@
+# Tests fail even with a fuzzy pixel diff. They require a re-baseline.
+crbug.com/954328 compositing/lots-of-img-layers.html [ Failure ]
+crbug.com/954328 css3/filters/effect-blur-hw.html [ Failure ]
+crbug.com/954328 media/video-layer-crash.html [ Failure ]
+crbug.com/954328 transforms/3d/point-mapping/3d-point-mapping-deep.html [ Failure ]
+
+# Native Failures
+# Backing Failure
+crbug.com/978628 media/remoteplayback/prompt-twice-throws.html [ Skip ]
+crbug.com/978628 media/video-controls-fullscreen.html [ Skip ]
+crbug.com/978628 media/audio-delete-while-slider-thumb-clicked.html [ Skip ]
+crbug.com/978628 media/video-controls-overflow-menu-fullscreen-button.html [ Skip ]
+crbug.com/978628 media/video-persistence.html [ Skip ]
+crbug.com/978628 media/video-src-blob.html [ Skip ]
+
+# Blur
+crbug.com/972621 compositing/culling/scrolled-within-boxshadow.html [ Skip ]
+crbug.com/972621 compositing/culling/translated-boxshadow.html [ Skip ]
+crbug.com/972621 compositing/culling/unscrolled-within-boxshadow.html [ Skip ]
+crbug.com/972621 compositing/geometry/clipping-foreground.html [ Skip ]
+crbug.com/972621 compositing/geometry/foreground-layer.html [ Skip ]
+crbug.com/972621 compositing/geometry/vertical-scroll-composited.html [ Skip ]
+crbug.com/972621 compositing/iframes/composited-iframe-alignment.html [ Skip ]
+crbug.com/972621 compositing/overflow/border-radius-above-composited-subframe.html [ Skip ]
+crbug.com/972621 compositing/overflow/border-radius-composited-subframe.html [ Skip ]
+crbug.com/972621 compositing/overflow/mask-with-filter.html [ Skip ]
+crbug.com/972621 compositing/overflow/scrollbar-layer-placement-negative-z-index-child-positioned.html [ Skip ]
+crbug.com/972621 compositing/overflow/scrollbar-layer-placement.html [ Skip ]
+crbug.com/972621 compositing/shadows/shadow-drawing.html [ Skip ]
+crbug.com/972621 css2.1/t090501-c414-flt-02-d-g.html [ Skip ]
+crbug.com/972621 css2.1/t090501-c414-flt-03-b-g.html [ Skip ]
+crbug.com/972621 css2.1/t100304-c43-rpl-bbx-00-d-g.html [ Skip ]
+crbug.com/972621 css2.1/t100304-c43-rpl-bbx-01-d-g.html [ Skip ]
+crbug.com/972621 css3/background/background-repeat-round-auto1.html [ Skip ]
+crbug.com/972621 css3/background/background-repeat-round-border.html [ Skip ]
+crbug.com/972621 css3/background/background-repeat-round-content.html [ Skip ]
+crbug.com/972621 css3/background/background-repeat-round-padding.html [ Skip ]
+crbug.com/972621 css3/filters/blur-filter-page-scroll-parents.html [ Skip ]
+crbug.com/972621 css3/filters/blur-filter-page-scroll.html [ Skip ]
+crbug.com/972621 css3/filters/crash-filter-change.html [ Skip ]
+crbug.com/972621 css3/filters/effect-blur.html [ Skip ]
+crbug.com/972621 css3/filters/effect-brightness-clamping.html [ Skip ]
+crbug.com/972621 css3/filters/effect-combined.html [ Skip ]
+crbug.com/972621 css3/filters/effect-drop-shadow.html [ Skip ]
+crbug.com/972621 css3/filters/filter-change-repaint.html [ Skip ]
+crbug.com/972621 css3/filters/filter-repaint-blur.html [ Skip ]
+crbug.com/972621 css3/filters/filter-repaint-child-layers.html [ Skip ]
+crbug.com/972621 css3/filters/filter-repaint-shadow.html [ Skip ]
+crbug.com/972621 css3/filters/filter-repaint.html [ Skip ]
+crbug.com/972621 css3/filters/regions-expanding.html [ Skip ]
+crbug.com/972621 css3/masking/mask-repeat-round-auto1.html [ Skip ]
+crbug.com/972621 css3/masking/mask-repeat-round-border.html [ Skip ]
+crbug.com/972621 css3/masking/mask-repeat-round-content.html [ Skip ]
+crbug.com/972621 css3/masking/mask-repeat-round-padding.html [ Skip ]
+crbug.com/972621 images/optimize-contrast-canvas.html [ Skip ]
+crbug.com/972621 images/optimize-contrast-image.html [ Skip ]
+crbug.com/972621 images/rgb-png-with-cmyk-color-profile.html [ Skip ]
+crbug.com/972621 images/ycbcr-with-cmyk-color-profile.html [ Skip ]
+crbug.com/972621 media/color-profile-video-poster-image.html [ Skip ]
+crbug.com/972621 transforms/shadows.html [ Skip ]
+crbug.com/972621 transforms/svg-vs-css.xhtml [ Skip ]
+
+# Filter Rebaseline
+crbug.com/978605 compositing/masks/mask-with-added-filters.html [ Skip ]
+crbug.com/978605 compositing/masks/mask-with-removed-filters.html [ Skip ]
+
+# Input timing doesn't match screenshots
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-img-and-text.html [ Skip ]
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-multicol.html [ Skip ]
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-nested-cursor.html [ Skip ]
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-nested-cursor3.html [ Skip ]
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-simple-scaled-document.html [ Skip ]
+crbug.com/935970 compositing/gestures/gesture-tapHighlight-with-squashing.html [ Skip ]
+crbug.com/935970 compositing/iframes/layout-on-compositing-change.html [ Skip ]
+crbug.com/935970 compositing/squashing/squash-compositing-hover.html [ Skip ]
+crbug.com/935970 compositing/squashing/squash-transform-repainting-child.html [ Skip ]
+crbug.com/935970 compositing/squashing/squash-transform-repainting-transformed-child.html [ Skip ]
+crbug.com/935970 css3/viewport-percentage-lengths/vh-resize.html [ Skip ]
+crbug.com/935970 images/drag-image-2.html [ Skip ]
+crbug.com/935970 images/drag-image-descendant-iframe-composited.html [ Skip ]
+crbug.com/935970 images/drag-image-descendant-painting-sibling.html [ Skip ]
+crbug.com/935970 images/drag-image-transformed-child.html [ Skip ]
+crbug.com/935970 images/drag-image-transformed-parent.html [ Skip ]
+crbug.com/935970 images/drag-image.html [ Skip ]
+crbug.com/935970 images/huge-image-viewport-scale.html [ Skip ]
+crbug.com/935970 images/image-map-multiple-xhtml.xhtml [ Skip ]
+crbug.com/935970 images/image-map-multiple.html [ Skip ]
+crbug.com/935970 images/server-side-imagemap.html [ Skip ]
+crbug.com/935970 media/controls-drag-timebar.html [ Skip ]
+crbug.com/935970 media/controls-timeline.html [ Skip ]
+crbug.com/935970 media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Skip ]
+crbug.com/935970 media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Skip ]
+crbug.com/935970 media/media-controls-tap-show-controls-without-activating.html [ Skip ]
+crbug.com/935970 media/video-controls-always-visible-when-control-hovered.html [ Skip ]
+crbug.com/935970 media/video-controls-auto-hide-after-play-by-touch.html [ Skip ]
+crbug.com/935970 media/video-controls-hide-after-touch-on-control.html [ Skip ]
+crbug.com/935970 media/video-controls-hide-on-move-outside-controls.html [ Skip ]
+crbug.com/935970 media/video-controls-mouse-events-captured.html [ Skip ]
+crbug.com/935970 media/video-controls-overflow-menu-closed-captions-button.html [ Skip ]
+crbug.com/935970 media/video-controls-overflow-menu-mute-button.html [ Skip ]
+crbug.com/935970 media/video-controls-overflow-menu-play-button.html [ Skip ]
+crbug.com/935970 media/video-controls-transformed.html [ Skip ]
+crbug.com/935970 media/video-controls-visibility-multimodal-mouse-after-touch.html [ Skip ]
+crbug.com/935970 media/video-controls-visibility-multimodal-touch-after-mouse.html [ Skip ]
+crbug.com/935970 media/video-controls-visible-audio-only.html [ Skip ]
+
+# Pixel Dump Crash
+crbug.com/963542 images/color-profile-layer-filter.html [ Skip ]
+crbug.com/963542 media/alpha-video-playback.html [ Skip ]
+
+# Rebaseline
+crbug.com/972637 compositing/fixed-background-after-style-recalc.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-crossfade-image-gradient.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-default-value.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-gradient-gradient.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-gradient-image.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-image-color.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-image-image.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-image-svg.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-multiple-background-layers.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-single-layer-no-blending.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-svg-color.html [ Skip ]
+crbug.com/972637 css3/blending/background-blend-mode-tiled-gradient.html [ Skip ]
+crbug.com/972637 css3/blending/effect-background-blend-mode-stacking.html [ Skip ]
+crbug.com/972637 css3/blending/effect-background-blend-mode-tiled.html [ Skip ]
+crbug.com/972637 css3/blending/effect-background-blend-mode.html [ Skip ]
+crbug.com/972637 css3/blending/mix-blend-mode-isolated-group-1.html [ Skip ]
+crbug.com/972637 css3/blending/mix-blend-mode-isolated-group-2.html [ Skip ]
+crbug.com/972637 css3/blending/mix-blend-mode-isolated-group-3.html [ Skip ]
+crbug.com/972637 css3/masking/mask-luminance-png.html [ Skip ]
+crbug.com/972637 css3/masking/mask-repeat-space-border.html [ Skip ]
+crbug.com/972637 images/color-profile-animate-rotate.html [ Skip ]
+crbug.com/972637 images/color-profile-animate.html [ Skip ]
+crbug.com/972637 images/color-profile-background-image-cover.html [ Skip ]
+crbug.com/972637 images/color-profile-background-image-cross-fade-png.html [ Skip ]
+crbug.com/972637 images/color-profile-background-image-cross-fade.html [ Skip ]
+crbug.com/972637 images/color-profile-background-image-repeat.html [ Skip ]
+crbug.com/972637 images/color-profile-background-image-space.html [ Skip ]
+crbug.com/972637 images/color-profile-border-fade.html [ Skip ]
+crbug.com/972637 images/color-profile-border-image.html [ Skip ]
+crbug.com/972637 images/color-profile-border-radius.html [ Skip ]
+crbug.com/972637 images/color-profile-filter.html [ Skip ]
+crbug.com/972637 images/color-profile-group.html [ Skip ]
+crbug.com/972637 images/color-profile-image-canvas-pattern.html [ Skip ]
+crbug.com/972637 images/color-profile-image-canvas.html [ Skip ]
+crbug.com/972637 images/color-profile-image-filter-all.html [ Skip ]
+crbug.com/972637 images/color-profile-image-profile-match.html [ Skip ]
+crbug.com/972637 images/color-profile-image.html [ Skip ]
+crbug.com/972637 images/color-profile-mask-image-svg.html [ Skip ]
+crbug.com/972637 images/color-profile-object.html [ Skip ]
+crbug.com/972637 images/color-profile-svg-fill-text.html [ Skip ]
+crbug.com/972637 images/color-profile-svg.html [ Skip ]
+crbug.com/972637 images/webp-color-profile-lossy.html [ Skip ]
+crbug.com/972637 media/video-poster-scale.html [ Skip ]
+
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index cf9e5bd0..154e845e 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -138179,6 +138179,9 @@
    "css/css-masking/parsing/clip-path-valid-expected.txt": [
     []
    ],
+   "css/css-masking/parsing/mask-position-valid-expected.txt": [
+    []
+   ],
    "css/css-masking/test-mask-ref.html": [
     []
    ],
@@ -160160,9 +160163,6 @@
    "infrastructure/metadata/infrastructure/server/title.any.js.ini": [
     []
    ],
-   "infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini": [
-    []
-   ],
    "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [
     []
    ],
@@ -203113,6 +203113,18 @@
      {}
     ]
    ],
+   "css/css-masking/parsing/mask-position-invalid.html": [
+    [
+     "css/css-masking/parsing/mask-position-invalid.html",
+     {}
+    ]
+   ],
+   "css/css-masking/parsing/mask-position-valid.html": [
+    [
+     "css/css-masking/parsing/mask-position-valid.html",
+     {}
+    ]
+   ],
    "css/css-multicol/abspos-in-multicol-with-spanner-crash.html": [
     [
      "css/css-multicol/abspos-in-multicol-with-spanner-crash.html",
@@ -246592,14 +246604,6 @@
      {}
     ]
    ],
-   "infrastructure/testdriver/actions/actionsWithKeyPressed.html": [
-    [
-     "infrastructure/testdriver/actions/actionsWithKeyPressed.html",
-     {
-      "testdriver": true
-     }
-    ]
-   ],
    "infrastructure/testdriver/actions/elementPosition.html": [
     [
      "infrastructure/testdriver/actions/elementPosition.html",
@@ -302003,6 +302007,12 @@
      }
     ]
    ],
+   "xhr/sync-xhr-and-window-onload.html": [
+    [
+     "xhr/sync-xhr-and-window-onload.html",
+     {}
+    ]
+   ],
    "xhr/sync-xhr-supported-by-feature-policy.html": [
     [
      "xhr/sync-xhr-supported-by-feature-policy.html",
@@ -363512,6 +363522,18 @@
    "bd14dfd1b5c9acb697dc4f7afc21e1fb656a377a",
    "testharness"
   ],
+  "css/css-masking/parsing/mask-position-invalid.html": [
+   "c246a1e795eea6a9e31fe1155d55ceb8532d6032",
+   "testharness"
+  ],
+  "css/css-masking/parsing/mask-position-valid-expected.txt": [
+   "76693ca51a98fec1fa733225577e26e7e1f746c1",
+   "support"
+  ],
+  "css/css-masking/parsing/mask-position-valid.html": [
+   "efdf55a0182ae701d459c1206b18ba74625e5f95",
+   "testharness"
+  ],
   "css/css-masking/test-mask-ref.html": [
    "938235acbd36309fb969c55f161239bcd5ab969e",
    "support"
@@ -437332,10 +437354,6 @@
    "cbae6b15410e13433c4a9fadd8c2a8cc5fbc4fdc",
    "support"
   ],
-  "infrastructure/metadata/infrastructure/testdriver/actions/actionsWithKeyPressed.html.ini": [
-   "c83e8ff9261b78084f75fb584a8b5236cc28c3fd",
-   "support"
-  ],
   "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [
    "49e4a40016e0eb2304a5e6e61b19556818c4ef3d",
    "support"
@@ -437536,10 +437554,6 @@
    "ea7973a62e0ee9cdc874879fd844b2309e944e61",
    "testharness"
   ],
-  "infrastructure/testdriver/actions/actionsWithKeyPressed.html": [
-   "74e939f5fde4773aade6ce4f7bbee573e39ae8ec",
-   "testharness"
-  ],
   "infrastructure/testdriver/actions/elementPosition.html": [
    "145852e7b51bd0cdc9e7b4ef5ebddcbf1c0235c5",
    "testharness"
@@ -437717,7 +437731,7 @@
    "support"
   ],
   "interfaces/WebIDL.idl": [
-   "aa8d5bad16a971b09d74914865f7db3115c7d836",
+   "a9157a955904c29b362dc1527f66c531ef6429ca",
    "support"
   ],
   "interfaces/accelerometer.idl": [
@@ -438229,7 +438243,7 @@
    "support"
   ],
   "interfaces/webxr.idl": [
-   "c78683ef6bf6822b0320fe4c16bc9630a63884de",
+   "2c9eac510672513e611f565fc31d2c7d8a3820da",
    "support"
   ],
   "interfaces/worklets.idl": [
@@ -438649,11 +438663,11 @@
    "testharness"
   ],
   "layout-instability/buffer-layout-shift.html": [
-   "25677852ca3f6bd1a0fedab54031f940cb90ef59",
+   "c55f1e88d4cd7084322813102bfe82dc1d14c7a7",
    "testharness"
   ],
   "layout-instability/observe-layout-shift.html": [
-   "297441beeb9c8a68e86129e5d8ba85d894711ff9",
+   "a522b49034e58c7aafd98eacae12353bc3476d06",
    "testharness"
   ],
   "layout-instability/resources/slow-image.py": [
@@ -443521,15 +443535,15 @@
    "testharness"
   ],
   "native-file-system/FileSystemBaseHandle-remove.tentative.window.js": [
-   "5a8e67b8478caa022dccb10c14f64103e329e5c9",
+   "a4eb2871104f924347f9ec8791a6381313a54483",
    "testharness"
   ],
   "native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js": [
-   "0f8c1b13fa01d6fb5c88455eac86c969b4d04c0a",
+   "2064fc46f05f5e30c14f77c14c5751b411d1c5e0",
    "testharness"
   ],
   "native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js": [
-   "0b27027f4eddb752b465ccfa5b3843689eb280ea",
+   "473cad4c9c36660584c07d7b53dfc68c7f734cb4",
    "testharness"
   ],
   "native-file-system/FileSystemWriter.tentative.window.js": [
@@ -443545,7 +443559,7 @@
    "support"
   ],
   "native-file-system/resources/test-helpers.js": [
-   "e29927b85247d55d6dfd6d04838d3587158aadf2",
+   "56c93b597508a5be23da31c9a9cb89d3cb470aa7",
    "support"
   ],
   "navigation-timing/META.yml": [
@@ -476929,11 +476943,11 @@
    "testharness"
   ],
   "url/urlencoded-parser-expected.txt": [
-   "4e3b49f95825bded0fb3ce619b2a87c020f2aaf3",
+   "6410d44042152a42ec4bae697a4a168295c5a462",
    "support"
   ],
   "url/urlencoded-parser.any-expected.txt": [
-   "4e3b49f95825bded0fb3ce619b2a87c020f2aaf3",
+   "6410d44042152a42ec4bae697a4a168295c5a462",
    "support"
   ],
   "url/urlencoded-parser.any.js": [
@@ -476941,7 +476955,7 @@
    "testharness"
   ],
   "url/urlencoded-parser.any.worker-expected.txt": [
-   "4e3b49f95825bded0fb3ce619b2a87c020f2aaf3",
+   "6410d44042152a42ec4bae697a4a168295c5a462",
    "support"
   ],
   "url/urlsearchparams-append.any.js": [
@@ -481885,7 +481899,7 @@
    "testharness"
   ],
   "webrtc/RTCStats-helper.js": [
-   "e91b40b6854f1cc6c59f7d81bf06a40e6dc0d31f",
+   "5cd7d2c9e0e1f6c5c10afe529be8489dec4dd5ad",
    "support"
   ],
   "webrtc/RTCTrackEvent-constructor-expected.txt": [
@@ -490384,6 +490398,10 @@
    "d23fbb8c66def47e31ad01aa7a311064ba8fddbd",
    "testharness"
   ],
+  "xhr/sync-xhr-and-window-onload.html": [
+   "3ba9e7ab2e8c772cfe4673b61ad8b4a4582d851d",
+   "testharness"
+  ],
   "xhr/sync-xhr-supported-by-feature-policy.html": [
    "45588bf6af54b0136c72068544bc908378f286a2",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-invalid.html
new file mode 100644
index 0000000..c246a1e79
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-invalid.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Masking Module Level 1: parsing mask-position with invalid values</title>
+<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-position">
+<meta name="assert" content="mask-position supports only the '<position>#' grammar.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value("mask-position", "auto");
+test_invalid_value("mask-position", "1px 2px 3px");
+test_invalid_value("mask-position", "left right");
+test_invalid_value("mask-position", "bottom 10%");
+test_invalid_value("mask-position", "bottom 10% top 20%");
+
+test_invalid_value("mask-position", "center left 1px");
+test_invalid_value("mask-position", "center top 2px");
+test_invalid_value("mask-position", "right 3% center");
+test_invalid_value("mask-position", "left 4px top");
+test_invalid_value("mask-position", "right top 5px");
+test_invalid_value("mask-position", "bottom 6% center");
+test_invalid_value("mask-position", "bottom 7% left");
+test_invalid_value("mask-position", "bottom right 8%");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid-expected.txt
new file mode 100644
index 0000000..76693ca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+FAIL e.style['mask-position'] = "10%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "right 30% top 60px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "-20% -30px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "30px center" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "40px top" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "bottom 10% right 20%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "bottom right" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "center 50px" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "center bottom" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "center left" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "left" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "left bottom" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "right 40%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "top" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "top center" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "center" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "bottom left, right 20%" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['mask-position'] = "top, center, left" should set the property value assert_not_equals: property should be set got disallowed value ""
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid.html b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid.html
new file mode 100644
index 0000000..efdf55a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/parsing/mask-position-valid.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Masking Module Level 1: parsing mask-position with valid values</title>
+<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask-position">
+<meta name="assert" content="mask-position supports the full '<position>#' grammar.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("mask-position", "10%", "10% center");
+test_valid_value("mask-position", "right 30% top 60px");
+test_valid_value("mask-position", "-20% -30px");
+test_valid_value("mask-position", "30px center");
+test_valid_value("mask-position", "40px top");
+test_valid_value("mask-position", "bottom 10% right 20%", "right 20% bottom 10%");
+test_valid_value("mask-position", "bottom right", "right bottom");
+test_valid_value("mask-position", "center 50px");
+test_valid_value("mask-position", "center bottom");
+test_valid_value("mask-position", "center left", "left center");
+test_valid_value("mask-position", "left", "left center");
+test_valid_value("mask-position", "left bottom");
+test_valid_value("mask-position", "right 40%");
+test_valid_value("mask-position", "top", "center top");
+test_valid_value("mask-position", "top center", "center top");
+test_valid_value("mask-position", "center", "center center");
+
+test_valid_value("mask-position", "bottom left, right 20%", "left bottom, right 20%");
+test_valid_value("mask-position", "top, center, left", "center top, center center, left center");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
index c78683ef..2c9eac5 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
@@ -10,7 +10,7 @@
 [SecureContext, Exposed=Window] interface XR : EventTarget {
   // Methods
   Promise<void> supportsSession(XRSessionMode mode);
-  Promise<XRSession> requestSession(XRSessionMode mode);
+  Promise<XRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
 
   // Events
   attribute EventHandler ondevicechange;
@@ -22,6 +22,11 @@
   "immersive-ar"
 };
 
+dictionary XRSessionInit {
+  sequence<DOMString> requiredFeatures;
+  sequence<DOMString> optionalFeatures;
+};
+
 enum XREnvironmentBlendMode {
   "opaque",
   "additive",
@@ -239,13 +244,11 @@
 interface XRInputSourceEvent : Event {
   [SameObject] readonly attribute XRFrame frame;
   [SameObject] readonly attribute XRInputSource inputSource;
-  [SameObject] readonly attribute long? buttonIndex;
 };
 
 dictionary XRInputSourceEventInit : EventInit {
   required XRFrame frame;
   required XRInputSource inputSource;
-  long? buttonIndex = null;
 };
 
 [SecureContext, Exposed=Window, Constructor(DOMString type, XRInputSourcesChangeEventInit eventInitDict)]
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js
index 5a8e67b..a4eb287 100644
--- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js
+++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.window.js
@@ -3,39 +3,74 @@
     'Cleanup to setup test environment');
 
 promise_test(async t => {
-    const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
-    const handle = await createFileWithContents(t, 'file-to-remove', '12345', dir);
-    await createFileWithContents(t, 'file-to-keep', 'abc');
-    await handle.remove();
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+    const handle = await createFileWithContents(t, 'file-to-remove', '12345', root);
+    await createFileWithContents(t, 'file-to-keep', 'abc', root);
+    await root.removeEntry('file-to-remove');
 
-    assert_array_equals(await getSortedDirectoryEntries(dir), ['file-to-keep']);
+    assert_array_equals(await getSortedDirectoryEntries(root), ['file-to-keep']);
     await promise_rejects(t, 'NotFoundError', getFileContents(handle));
-}, 'remove() to remove a file');
+}, 'removeEntry() to remove a file');
 
 promise_test(async t => {
-    const handle = await createFileWithContents(t, 'file-to-remove', '12345');
-    await handle.remove();
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+    const handle = await createFileWithContents(t, 'file-to-remove', '12345', root);
+    await root.removeEntry('file-to-remove');
 
-    await promise_rejects(t, 'NotFoundError', handle.remove());
-}, 'remove() on an already removed file should fail');
+    await promise_rejects(t, 'NotFoundError', root.removeEntry('file-to-remove'));
+}, 'removeEntry() on an already removed file should fail');
 
 promise_test(async t => {
     const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const dir = await root.getDirectory('dir-to-remove', { create: true });
-    await createFileWithContents(t, 'file-to-keep', 'abc');
-    await dir.remove();
+    await createFileWithContents(t, 'file-to-keep', 'abc', root);
+    await root.removeEntry('dir-to-remove');
 
     assert_array_equals(await getSortedDirectoryEntries(root), ['file-to-keep']);
     await promise_rejects(t, 'NotFoundError', getSortedDirectoryEntries(dir));
-}, 'remove() to remove an empty directory');
+}, 'removeEntry() to remove an empty directory');
 
 promise_test(async t => {
     const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const dir = await root.getDirectory('dir-to-remove', { create: true });
-    t.add_cleanup(() => dir.removeRecursively());
+    t.add_cleanup(() => root.removeEntry('dir-to-remove', { recursive: true }));
     await createEmptyFile(t, 'file-in-dir', dir);
 
-    await promise_rejects(t, 'InvalidModificationError', dir.remove());
+    await promise_rejects(t, 'InvalidModificationError', root.removeEntry('dir-to-remove'));
     assert_array_equals(await getSortedDirectoryEntries(root), ['dir-to-remove/']);
     assert_array_equals(await getSortedDirectoryEntries(dir), ['file-in-dir']);
-}, 'remove() on a non-empty directory should fail');
+}, 'removeEntry() on a non-empty directory should fail');
+
+promise_test(async t => {
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+    const dir = await createDirectory(t, 'dir', root);
+    await promise_rejects(t, 'NotFoundError', dir.removeEntry(""));
+}, 'removeEntry() with empty name should fail');
+
+promise_test(async t => {
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+    const dir = await createDirectory(t, 'dir', root);
+    await promise_rejects(t, 'SecurityError', dir.removeEntry(kCurrentDirectory));
+}, `removeEntry() with "${kCurrentDirectory}" name should fail`);
+
+promise_test(async t => {
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+    const dir = await createDirectory(t, 'dir', root);
+    await promise_rejects(t, 'SecurityError', dir.removeEntry(kParentDirectory));
+}, `removeEntry() with "${kParentDirectory}" name should fail`);
+
+promise_test(async t => {
+    const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
+
+    const dir_name = 'dir-name';
+    const dir = await createDirectory(t, dir_name, root);
+
+    const file_name = 'file-name';
+    await createEmptyFile(t, file_name, dir);
+
+    for (let i = 0; i < kPathSeparators.length; ++i) {
+        const path_with_separator = `${dir_name}${kPathSeparators[i]}${file_name}`;
+        await promise_rejects(t, 'SecurityError', root.removeEntry(path_with_separator),
+            `removeEntry() must reject names containing "${kPathSeparators[i]}"`);
+    }
+}, 'removeEntry() with a path separator should fail.');
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js
index 0f8c1b1..2064fc4 100644
--- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js
+++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.window.js
@@ -10,7 +10,7 @@
 promise_test(async t => {
     const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const handle = await root.getDirectory('non-existing-dir', { create: true });
-    t.add_cleanup(() => handle.removeRecursively());
+    t.add_cleanup(() => root.removeEntry('non-existing-dir', { recursive: true }));
 
     assert_false(handle.isFile);
     assert_true(handle.isDirectory);
@@ -22,7 +22,7 @@
 promise_test(async t => {
     const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const existing_handle = await root.getDirectory('dir-with-contents', { create: true });
-    t.add_cleanup(() => existing_handle.removeRecursively());
+    t.add_cleanup(() => root.removeEntry('dir-with-contents', { recursive: true }));
     const file_handle = await createEmptyFile(t, 'test-file', existing_handle);
 
     const handle = await root.getDirectory('dir-with-contents', { create: false });
@@ -36,7 +36,7 @@
 promise_test(async t => {
     const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const existing_handle = await root.getDirectory('dir-with-contents', { create: true });
-    t.add_cleanup(() => existing_handle.removeRecursively());
+    t.add_cleanup(() => root.removeEntry('dir-with-contents', { recursive: true }));
     const file_handle = await existing_handle.getFile('test-file', { create: true });
 
     const handle = await root.getDirectory('dir-with-contents', { create: true });
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js
index 0b27027..473cad4 100644
--- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js
+++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.window.js
@@ -10,7 +10,7 @@
 promise_test(async t => {
     const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const handle = await dir.getFile('non-existing-file', { create: true });
-    t.add_cleanup(() => handle.remove());
+    t.add_cleanup(() => dir.removeEntry('non-existing-file'));
 
     assert_true(handle.isFile);
     assert_false(handle.isDirectory);
@@ -48,7 +48,7 @@
 promise_test(async t => {
     const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const dir_handle = await dir.getDirectory('dir-name', { create: true });
-    t.add_cleanup(() => dir_handle.removeRecursively());
+    t.add_cleanup(() => dir.removeEntry('dir-name', { recursive: true }));
 
     await promise_rejects(t, 'TypeMismatchError', dir.getFile('dir-name'));
 }, 'getFile(create=false) when a directory already exists with the same name');
@@ -56,7 +56,7 @@
 promise_test(async t => {
     const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
     const dir_handle = await dir.getDirectory('dir-name', { create: true });
-    t.add_cleanup(() => dir_handle.removeRecursively());
+    t.add_cleanup(() => dir.removeEntry('dir-name', { recursive: true }));
 
     await promise_rejects(t, 'TypeMismatchError', dir.getFile('dir-name', { create: true }));
 }, 'getFile(create=true) when a directory already exists with the same name');
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js b/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js
index e29927b8..56c93b5 100644
--- a/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js
+++ b/third_party/blink/web_tests/external/wpt/native-file-system/resources/test-helpers.js
@@ -15,12 +15,8 @@
 
 async function cleanupSandboxedFileSystem() {
     const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' });
-    for await (let entry of dir.getEntries()) {
-        if (entry.isDirectory)
-            await entry.removeRecursively();
-        else
-            await entry.remove();
-   }
+    for await (let entry of dir.getEntries())
+        dir.removeEntry(entry.name, { recursive: entry.isDirectory });
 }
 
 async function getFileSize(handle) {
@@ -60,7 +56,7 @@
   const new_dir_handle = await parent_dir_handle.getDirectory(name, { create: true });
   test.add_cleanup(async () => {
         try {
-            await new_dir_handle.removeRecursively();
+            await parent_dir_handle.removeEntry(name, { recursive: true });
         } catch (e) {
             // Ignore any errors when removing directories, as tests might
             // have already removed the directory.
@@ -74,7 +70,7 @@
     const handle = await dir.getFile(name, { create: true });
     test.add_cleanup(async () => {
         try {
-            await handle.remove();
+            await dir.removeEntry(name);
         } catch (e) {
             // Ignore any errors when removing files, as tests might already remove the file.
         }
diff --git a/third_party/blink/web_tests/external/wpt/preload/subresource-integrity-expected.txt b/third_party/blink/web_tests/external/wpt/preload/subresource-integrity-expected.txt
new file mode 100644
index 0000000..a754027
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/subresource-integrity-expected.txt
@@ -0,0 +1,69 @@
+This is a testharness.js-based test.
+Found 65 tests; 59 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Same-origin script with correct sha256 hash.
+PASS Same-origin script with correct sha384 hash.
+PASS Same-origin script with correct sha512 hash.
+PASS Same-origin script with empty integrity.
+PASS Same-origin script with incorrect hash.
+PASS Same-origin script with multiple sha256 hashes, including correct.
+PASS Same-origin script with multiple sha256 hashes, including unknown algorithm.
+PASS Same-origin script with sha256 mismatch, sha512 match
+PASS Same-origin script with sha256 match, sha512 mismatch
+PASS <crossorigin='anonymous'> script with correct hash, ACAO: *
+PASS <crossorigin='anonymous'> script with incorrect hash, ACAO: *
+PASS <crossorigin='use-credentials'> script with correct hash, CORS-eligible
+PASS <crossorigin='use-credentials'> script with incorrect hash CORS-eligible
+PASS <crossorigin='anonymous'> script with CORS-ineligible resource
+PASS Cross-origin script, not CORS request, with correct hash
+PASS Cross-origin script, not CORS request, with hash mismatch
+PASS Cross-origin script, empty integrity
+PASS Same-origin script with correct hash, options.
+PASS Same-origin script with unknown algorithm only.
+PASS Same-origin script with matching digest re-uses preload with matching digest.
+PASS Same-origin script with non-matching digest does not re-use preload with matching digest.
+PASS Same-origin script with matching digest does not re-use preload with non-matching digest.
+PASS Same-origin script with non-matching digest does not re-use preload with non-matching digest.
+PASS Same-origin style with correct sha256 hash.
+PASS Same-origin style with correct sha384 hash.
+PASS Same-origin style with correct sha512 hash.
+PASS Same-origin style with empty integrity.
+PASS Same-origin style with incorrect hash.
+PASS Same-origin style with multiple sha256 hashes, including correct.
+PASS Same-origin style with multiple sha256 hashes, including unknown algorithm.
+PASS Same-origin style with sha256 mismatch, sha512 match
+PASS Same-origin style with sha256 match, sha512 mismatch
+PASS <crossorigin='anonymous'> style with correct hash, ACAO: *
+PASS <crossorigin='anonymous'> style with incorrect hash, ACAO: *
+PASS <crossorigin='use-credentials'> style with correct hash, CORS-eligible
+PASS <crossorigin='use-credentials'> style with incorrect hash CORS-eligible
+PASS <crossorigin='anonymous'> style with CORS-ineligible resource
+PASS Cross-origin style, not CORS request, with correct hash
+PASS Cross-origin style, not CORS request, with hash mismatch
+PASS Cross-origin style, empty integrity
+PASS Same-origin style with correct hash, options.
+PASS Same-origin style with unknown algorithm only.
+PASS Same-origin style with matching digest re-uses preload with matching digest.
+PASS Same-origin style with non-matching digest does not re-use preload with matching digest.
+PASS Same-origin style with matching digest does not re-use preload with non-matching digest.
+PASS Same-origin style with non-matching digest does not re-use preload with non-matching digest.
+PASS Same-origin image with correct sha256 hash.
+PASS Same-origin image with correct sha384 hash.
+PASS Same-origin image with correct sha512 hash.
+PASS Same-origin image with empty integrity.
+FAIL Same-origin image with incorrect hash. assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+PASS Same-origin image with multiple sha256 hashes, including correct.
+PASS Same-origin image with multiple sha256 hashes, including unknown algorithm.
+PASS Same-origin image with sha256 mismatch, sha512 match
+FAIL Same-origin image with sha256 match, sha512 mismatch assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+PASS <crossorigin='anonymous'> image with correct hash, ACAO: *
+FAIL <crossorigin='anonymous'> image with incorrect hash, ACAO: * assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+PASS <crossorigin='use-credentials'> image with correct hash, CORS-eligible
+FAIL <crossorigin='use-credentials'> image with incorrect hash CORS-eligible assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+PASS <crossorigin='anonymous'> image with CORS-ineligible resource
+FAIL Cross-origin image, not CORS request, with correct hash assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+FAIL Cross-origin image, not CORS request, with hash mismatch assert_unreached: Invalid subresource load succeeded. Reached unreachable code
+PASS Cross-origin image, empty integrity
+PASS Same-origin image with correct hash, options.
+PASS Same-origin image with unknown algorithm only.
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/preload/subresource-integrity.html b/third_party/blink/web_tests/external/wpt/preload/subresource-integrity.html
index 08c7854a..52ec0f6 100644
--- a/third_party/blink/web_tests/external/wpt/preload/subresource-integrity.html
+++ b/third_party/blink/web_tests/external/wpt/preload/subresource-integrity.html
@@ -27,6 +27,12 @@
       sha384: 'sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX',
       sha512: 'sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w=='
     },
+    {
+      destination: 'image', ext: '.png', supports_sri: false,
+      sha256: 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
+      sha384: 'sha384-OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb',
+      sha512: 'sha512-z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg=='
+    },
     // TODO(domfarolino): Add more destinations.
   ];
 
diff --git a/third_party/blink/web_tests/external/wpt/resources/sriharness.js b/third_party/blink/web_tests/external/wpt/resources/sriharness.js
index fe8ad2b..d30d483 100644
--- a/third_party/blink/web_tests/external/wpt/resources/sriharness.js
+++ b/third_party/blink/web_tests/external/wpt/resources/sriharness.js
@@ -34,6 +34,13 @@
     document.body.appendChild(e);
 };
 
+function set_extra_attributes(element, attrs) {
+  // Apply the rest of the attributes, if any.
+  for (const [attr_name, attr_val] of Object.entries(attrs)) {
+    element[attr_name] = attr_val;
+  }
+}
+
 function buildElementFromDestination(resource_url, destination, attrs) {
   // Assert: |destination| is a valid destination.
   let element;
@@ -45,26 +52,24 @@
   switch (destination) {
     case "script":
       element = document.createElement(destination);
+      set_extra_attributes(element, attrs);
       element.src = resource_url;
       break;
     case "style":
       element = document.createElement('link');
+      set_extra_attributes(element, attrs);
       element.rel = 'stylesheet';
       element.href = resource_url;
       break;
     case "image":
       element = document.createElement('img');
+      set_extra_attributes(element, attrs);
       element.src = resource_url;
       break;
     default:
       assert_unreached("INVALID DESTINATION");
   }
 
-  // Apply the rest of the attributes, if any.
-  for (const [attr_name, attr_val] of Object.entries(attrs)) {
-    element[attr_name] = attr_val;
-  }
-
   return element;
 }
 
diff --git a/third_party/blink/web_tests/external/wpt/subresource-integrity/image.png b/third_party/blink/web_tests/external/wpt/subresource-integrity/image.png
new file mode 100644
index 0000000..01c9666a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/subresource-integrity/image.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser-expected.txt b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser-expected.txt
index 4e3b49f..6410d44 100644
--- a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 90 tests; 73 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 90 tests; 88 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS URLSearchParams constructed with: test
 PASS request.formData() with input: test
 PASS response.formData() with input: test
@@ -9,24 +9,24 @@
 PASS URLSearchParams constructed with: %EF%BB%BFtest=%EF%BB%BF
 PASS request.formData() with input: %EF%BB%BFtest=%EF%BB%BF
 PASS response.formData() with input: %EF%BB%BFtest=%EF%BB%BF
-FAIL URLSearchParams constructed with: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL request.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL response.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL URLSearchParams constructed with: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL request.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL response.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
+PASS URLSearchParams constructed with: %FE%FF
+PASS request.formData() with input: %FE%FF
+PASS response.formData() with input: %FE%FF
+PASS URLSearchParams constructed with: %FF%FE
+PASS request.formData() with input: %FF%FE
+PASS response.formData() with input: %FF%FE
 PASS URLSearchParams constructed with: †&†=x
 PASS request.formData() with input: †&†=x
 PASS response.formData() with input: †&†=x
-FAIL URLSearchParams constructed with: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL request.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL response.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL URLSearchParams constructed with: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL URLSearchParams constructed with: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
+PASS URLSearchParams constructed with: %C2
+PASS request.formData() with input: %C2
+PASS response.formData() with input: %C2
+PASS URLSearchParams constructed with: %C2x
+PASS request.formData() with input: %C2x
+PASS response.formData() with input: %C2x
+PASS URLSearchParams constructed with: _charset_=windows-1252&test=%C2x
+PASS request.formData() with input: _charset_=windows-1252&test=%C2x
+PASS response.formData() with input: _charset_=windows-1252&test=%C2x
 PASS URLSearchParams constructed with: 
 PASS request.formData() with input: 
 PASS response.formData() with input: 
diff --git a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any-expected.txt b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any-expected.txt
index 4e3b49f..6410d44 100644
--- a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 90 tests; 73 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 90 tests; 88 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS URLSearchParams constructed with: test
 PASS request.formData() with input: test
 PASS response.formData() with input: test
@@ -9,24 +9,24 @@
 PASS URLSearchParams constructed with: %EF%BB%BFtest=%EF%BB%BF
 PASS request.formData() with input: %EF%BB%BFtest=%EF%BB%BF
 PASS response.formData() with input: %EF%BB%BFtest=%EF%BB%BF
-FAIL URLSearchParams constructed with: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL request.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL response.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL URLSearchParams constructed with: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL request.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL response.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
+PASS URLSearchParams constructed with: %FE%FF
+PASS request.formData() with input: %FE%FF
+PASS response.formData() with input: %FE%FF
+PASS URLSearchParams constructed with: %FF%FE
+PASS request.formData() with input: %FF%FE
+PASS response.formData() with input: %FF%FE
 PASS URLSearchParams constructed with: †&†=x
 PASS request.formData() with input: †&†=x
 PASS response.formData() with input: †&†=x
-FAIL URLSearchParams constructed with: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL request.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL response.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL URLSearchParams constructed with: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL URLSearchParams constructed with: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
+PASS URLSearchParams constructed with: %C2
+PASS request.formData() with input: %C2
+PASS response.formData() with input: %C2
+PASS URLSearchParams constructed with: %C2x
+PASS request.formData() with input: %C2x
+PASS response.formData() with input: %C2x
+PASS URLSearchParams constructed with: _charset_=windows-1252&test=%C2x
+PASS request.formData() with input: _charset_=windows-1252&test=%C2x
+PASS response.formData() with input: _charset_=windows-1252&test=%C2x
 PASS URLSearchParams constructed with: 
 PASS request.formData() with input: 
 PASS response.formData() with input: 
diff --git a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any.worker-expected.txt
index 4e3b49f..6410d44 100644
--- a/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/url/urlencoded-parser.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 90 tests; 73 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 90 tests; 88 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS URLSearchParams constructed with: test
 PASS request.formData() with input: test
 PASS response.formData() with input: test
@@ -9,24 +9,24 @@
 PASS URLSearchParams constructed with: %EF%BB%BFtest=%EF%BB%BF
 PASS request.formData() with input: %EF%BB%BFtest=%EF%BB%BF
 PASS response.formData() with input: %EF%BB%BFtest=%EF%BB%BF
-FAIL URLSearchParams constructed with: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL request.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL response.formData() with input: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got "þÿ"
-FAIL URLSearchParams constructed with: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL request.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
-FAIL response.formData() with input: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got "ÿþ"
+PASS URLSearchParams constructed with: %FE%FF
+PASS request.formData() with input: %FE%FF
+PASS response.formData() with input: %FE%FF
+PASS URLSearchParams constructed with: %FF%FE
+PASS request.formData() with input: %FF%FE
+PASS response.formData() with input: %FF%FE
 PASS URLSearchParams constructed with: †&†=x
 PASS request.formData() with input: †&†=x
 PASS response.formData() with input: †&†=x
-FAIL URLSearchParams constructed with: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL request.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL response.formData() with input: %C2 assert_array_equals: property 0, expected "\ufffd" but got "Â"
-FAIL URLSearchParams constructed with: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: %C2x assert_array_equals: property 0, expected "\ufffdx" but got "Âx"
-FAIL URLSearchParams constructed with: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL request.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
-FAIL response.formData() with input: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got "Âx"
+PASS URLSearchParams constructed with: %C2
+PASS request.formData() with input: %C2
+PASS response.formData() with input: %C2
+PASS URLSearchParams constructed with: %C2x
+PASS request.formData() with input: %C2x
+PASS response.formData() with input: %C2x
+PASS URLSearchParams constructed with: _charset_=windows-1252&test=%C2x
+PASS request.formData() with input: _charset_=windows-1252&test=%C2x
+PASS response.formData() with input: _charset_=windows-1252&test=%C2x
 PASS URLSearchParams constructed with: 
 PASS request.formData() with input: 
 PASS response.formData() with input: 
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
index bf29a9f..aeb7fdc 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 203 tests; 198 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 202 tests; 197 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Navigator: original interface defined
 PASS Partial dictionary WebGLContextAttributes: original dictionary defined
@@ -11,14 +11,14 @@
 PASS XR interface: existence and properties of interface prototype object's "constructor" property
 PASS XR interface: existence and properties of interface prototype object's @@unscopables property
 PASS XR interface: operation supportsSession(XRSessionMode)
-PASS XR interface: operation requestSession(XRSessionMode)
+PASS XR interface: operation requestSession(XRSessionMode, XRSessionInit)
 PASS XR interface: attribute ondevicechange
 PASS XR must be primary interface of navigator.xr
 PASS Stringification of navigator.xr
 PASS XR interface: navigator.xr must inherit property "supportsSession(XRSessionMode)" with the proper type
 PASS XR interface: calling supportsSession(XRSessionMode) on navigator.xr with too few arguments must throw TypeError
-PASS XR interface: navigator.xr must inherit property "requestSession(XRSessionMode)" with the proper type
-PASS XR interface: calling requestSession(XRSessionMode) on navigator.xr with too few arguments must throw TypeError
+PASS XR interface: navigator.xr must inherit property "requestSession(XRSessionMode, XRSessionInit)" with the proper type
+PASS XR interface: calling requestSession(XRSessionMode, XRSessionInit) on navigator.xr with too few arguments must throw TypeError
 PASS XR interface: navigator.xr must inherit property "ondevicechange" with the proper type
 PASS XRSession interface: existence and properties of interface object
 PASS XRSession interface object length
@@ -182,7 +182,6 @@
 PASS XRInputSourceEvent interface: existence and properties of interface prototype object's @@unscopables property
 PASS XRInputSourceEvent interface: attribute frame
 PASS XRInputSourceEvent interface: attribute inputSource
-PASS XRInputSourceEvent interface: attribute buttonIndex
 PASS XRInputSourcesChangeEvent interface: existence and properties of interface object
 PASS XRInputSourcesChangeEvent interface object length
 PASS XRInputSourcesChangeEvent interface object name
diff --git a/third_party/blink/web_tests/external/wpt/xhr/sync-xhr-and-window-onload.html b/third_party/blink/web_tests/external/wpt/xhr/sync-xhr-and-window-onload.html
new file mode 100644
index 0000000..3ba9e7a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/xhr/sync-xhr-and-window-onload.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test((t) => {
+  let onloadIsCalled = false;
+  window.addEventListener('load', () => {
+    onloadIsCalled = true;
+  }, {once: true});
+  document.addEventListener('readystatechange', t.step_func(() => {
+    if (document.readyState !== 'complete') {
+      return;
+    }
+    const xhr = new XMLHttpRequest();
+    xhr.open('GET', 'resources/pass.txt', false /* async */);
+    xhr.send();
+    assert_false(onloadIsCalled);
+    // The load event eventually arrives.
+    window.addEventListener('load', t.step_func_done(() => {
+    }), {once: 'true'});
+  }));
+}, 'sync XHR should not fire window.onload synchronously');
+</script>
+</body>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c86ed51e..6733d7af 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -27653,7 +27653,6 @@
   <int value="6" label="kGLImplementationMockGL)"/>
   <int value="7" label="kGLImplementationStubGL"/>
   <int value="8" label="kGLImplementationDisabled"/>
-  <int value="9" label="kGLImplementationEGLANGLE"/>
 </enum>
 
 <enum name="GoogleCaptchaEvent">
@@ -34968,6 +34967,7 @@
   <int value="-67616014" label="PDFAnnotations:enabled"/>
   <int value="-67297229" label="OfflinePagesDescriptivePendingStatus:disabled"/>
   <int value="-64839201" label="SyncUSSAutofillWalletData:disabled"/>
+  <int value="-64824628" label="VizHitTestSurfaceLayer:disabled"/>
   <int value="-59530055" label="ChromeVoxArcSupport:enabled"/>
   <int value="-59401847" label="ContentSuggestionsLargeThumbnail:disabled"/>
   <int value="-58242474" label="ash-disable-swipe-to-close-in-overview-mode"/>
@@ -35925,6 +35925,7 @@
   <int value="1353113954" label="EnableMDRoundedCornersOnDialogs:enabled"/>
   <int value="1353629763" label="MediaSessionAccelerators:enabled"/>
   <int value="1355923367" label="CrOSContainer:disabled"/>
+  <int value="1356161410" label="VizHitTestSurfaceLayer:enabled"/>
   <int value="1359972809" label="enable-gesture-deletion"/>
   <int value="1360969228" label="RevampedContextMenu:enabled"/>
   <int value="1361047396" label="disable-click-delay"/>
@@ -62653,6 +62654,9 @@
 </enum>
 
 <enum name="YouTubeRewriteStatus">
+  <obsolete>
+    Removed from code 07/2019.
+  </obsolete>
   <int value="0" label="Success">Embed was properly rewritten.</int>
   <int value="1" label="Success, params were rewritten">
     Embed was rewritten but the params had to be fixed.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 33618b5b..6512dc7 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -31417,6 +31417,9 @@
 
 <histogram name="Drive.BatchUploadResponseCode" enum="HttpResponseCode"
     expires_after="M77">
+  <obsolete>
+    Obsolete 07/2019 as DriveFS implementation obsoletes this metric.
+  </obsolete>
   <owner>hirono@chromium.org</owner>
   <summary>Respose code of batch upload request.</summary>
 </histogram>
@@ -99521,6 +99524,9 @@
 
 <histogram name="Plugin.Flash.YouTubeRewrite" enum="YouTubeRewriteStatus"
     expires_after="M77">
+  <obsolete>
+    Removed from code 07/2019.
+  </obsolete>
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
diff --git a/ui/accessibility/ax_language_info.cc b/ui/accessibility/ax_language_info.cc
index 622a8eb..72c091a2 100644
--- a/ui/accessibility/ax_language_info.cc
+++ b/ui/accessibility/ax_language_info.cc
@@ -261,11 +261,11 @@
   }
 }
 
-std::vector<LanguageSpan>
+std::vector<AXLanguageSpan>
 AXLanguageInfoStats::GetLanguageAnnotationForStringAttribute(
     const AXNode& node,
     ax::mojom::StringAttribute attr) {
-  std::vector<LanguageSpan> language_annotation;
+  std::vector<AXLanguageSpan> language_annotation;
   if (!node.HasStringAttribute(attr))
     return language_annotation;
 
@@ -274,11 +274,11 @@
   // Use author-provided language if present.
   if (node.HasStringAttribute(ax::mojom::StringAttribute::kLanguage)) {
     // Use author-provided language if present.
-    language_annotation.push_back(
-        LanguageSpan{0 /* start_index */, attr_value.length() /* end_index */,
-                     node.GetStringAttribute(
-                         ax::mojom::StringAttribute::kLanguage) /* language */,
-                     1 /* probability */});
+    language_annotation.push_back(AXLanguageSpan{
+        0 /* start_index */, attr_value.length() /* end_index */,
+        node.GetStringAttribute(
+            ax::mojom::StringAttribute::kLanguage) /* language */,
+        1 /* probability */});
     return language_annotation;
   }
   // Calculate top 3 languages.
@@ -287,23 +287,24 @@
   std::vector<chrome_lang_id::NNetLanguageIdentifier::Result> top_languages =
       short_text_language_identifier_.FindTopNMostFreqLangs(
           attr_value, kMaxDetectedLanguagesPerPage);
-  // Create vector of LanguageSpans.
+  // Create vector of AXLanguageSpans.
   for (const auto& result : top_languages) {
     std::vector<chrome_lang_id::NNetLanguageIdentifier::SpanInfo> ranges =
         result.byte_ranges;
     for (const auto& span_info : ranges) {
       language_annotation.push_back(
-          LanguageSpan{span_info.start_index, span_info.end_index,
-                       result.language, span_info.probability});
+          AXLanguageSpan{span_info.start_index, span_info.end_index,
+                         result.language, span_info.probability});
     }
   }
   // Sort Language Annotations by increasing start index. LanguageAnnotations
   // with lower start index should appear earlier in the vector.
-  std::sort(language_annotation.begin(), language_annotation.end(),
-            [](const LanguageSpan& left, const LanguageSpan& right) -> bool {
-              return left.start_index <= right.start_index;
-            });
-  // Ensure that LanguageSpans do not overlap.
+  std::sort(
+      language_annotation.begin(), language_annotation.end(),
+      [](const AXLanguageSpan& left, const AXLanguageSpan& right) -> bool {
+        return left.start_index <= right.start_index;
+      });
+  // Ensure that AXLanguageSpans do not overlap.
   for (size_t i = 0; i < language_annotation.size(); ++i) {
     if (i > 0) {
       DCHECK(language_annotation[i].start_index <=
diff --git a/ui/accessibility/ax_language_info.h b/ui/accessibility/ax_language_info.h
index 32e10308..9b6d485 100644
--- a/ui/accessibility/ax_language_info.h
+++ b/ui/accessibility/ax_language_info.h
@@ -93,14 +93,14 @@
   std::vector<std::string> detected_languages;
 };
 
-// Each LanguageSpan contains a language, a probability, and start and end
+// Each AXLanguageSpan contains a language, a probability, and start and end
 // indices. The indices are used to specify the substring that contains the
 // associated language. The string which the indices are relative to is not
 // included in this structure.
 // Also, the indices are relative to a Utf8 string.
 // See documentation on GetLanguageAnnotationForStringAttribute for details
 // on how to associate this object with a string.
-struct AX_EXPORT LanguageSpan {
+struct AX_EXPORT AXLanguageSpan {
   int start_index;
   int end_index;
   std::string language;
@@ -135,7 +135,7 @@
   // For example, if a node has name: "My name is Fred", then calling
   // GetLanguageAnnotationForStringAttribute(*node, ax::mojom::StringAttribute::
   // kName) would return language detection information about "My name is Fred".
-  std::vector<LanguageSpan> GetLanguageAnnotationForStringAttribute(
+  std::vector<AXLanguageSpan> GetLanguageAnnotationForStringAttribute(
       const AXNode& node,
       ax::mojom::StringAttribute attr);
 
diff --git a/ui/accessibility/ax_language_info_unittest.cc b/ui/accessibility/ax_language_info_unittest.cc
index bd0c712..440c96a 100644
--- a/ui/accessibility/ax_language_info_unittest.cc
+++ b/ui/accessibility/ax_language_info_unittest.cc
@@ -695,18 +695,18 @@
   AXTree tree(initial_state);
 
   AXNode* item = tree.GetFromId(2);
-  std::vector<LanguageSpan> annotation;
+  std::vector<AXLanguageSpan> annotation;
   // Empty output.
   annotation =
       tree.language_info_stats->GetLanguageAnnotationForStringAttribute(
           *item, ax::mojom::StringAttribute::kInnerHtml);
   ASSERT_EQ(0, (int)annotation.size());
-  // Returns single LanguageSpan.
+  // Returns single AXLanguageSpan.
   annotation =
       tree.language_info_stats->GetLanguageAnnotationForStringAttribute(
           *item, ax::mojom::StringAttribute::kName);
   ASSERT_EQ(1, (int)annotation.size());
-  LanguageSpan* lang_span = &annotation[0];
+  AXLanguageSpan* lang_span = &annotation[0];
   ASSERT_EQ("en", lang_span->language);
   std::string name =
       item->GetStringAttribute(ax::mojom::StringAttribute::kName);
@@ -729,13 +729,13 @@
   AXTree tree(initial_state);
 
   AXNode* item = tree.GetFromId(2);
-  std::vector<LanguageSpan> annotation;
-  // Returns single LanguageSpan.
+  std::vector<AXLanguageSpan> annotation;
+  // Returns single AXLanguageSpan.
   annotation =
       tree.language_info_stats->GetLanguageAnnotationForStringAttribute(
           *item, ax::mojom::StringAttribute::kName);
   ASSERT_EQ(1, (int)annotation.size());
-  LanguageSpan* lang_span = &annotation[0];
+  AXLanguageSpan* lang_span = &annotation[0];
   ASSERT_EQ("el", lang_span->language);
   std::string name =
       item->GetStringAttribute(ax::mojom::StringAttribute::kName);
@@ -759,13 +759,13 @@
   AXTree tree(initial_state);
 
   AXNode* item = tree.GetFromId(2);
-  std::vector<LanguageSpan> annotation =
+  std::vector<AXLanguageSpan> annotation =
       tree.language_info_stats->GetLanguageAnnotationForStringAttribute(
           *item, ax::mojom::StringAttribute::kName);
   ASSERT_EQ(3, (int)annotation.size());
   std::string name =
       item->GetStringAttribute(ax::mojom::StringAttribute::kName);
-  LanguageSpan* lang_span = &annotation[0];
+  AXLanguageSpan* lang_span = &annotation[0];
   ASSERT_EQ("This text should be read in English. ",
             name.substr(lang_span->start_index,
                         lang_span->end_index - lang_span->start_index));
@@ -793,13 +793,13 @@
   AXTree tree(initial_state);
 
   AXNode* item = tree.GetFromId(1);
-  std::vector<LanguageSpan> annotation =
+  std::vector<AXLanguageSpan> annotation =
       tree.language_info_stats->GetLanguageAnnotationForStringAttribute(
           *item, ax::mojom::StringAttribute::kValue);
   ASSERT_EQ(1, (int)annotation.size());
   std::string value =
       item->GetStringAttribute(ax::mojom::StringAttribute::kValue);
-  LanguageSpan* lang_span = &annotation[0];
+  AXLanguageSpan* lang_span = &annotation[0];
   ASSERT_EQ("どうぞよろしくお願いします.",
             value.substr(lang_span->start_index,
                          lang_span->end_index - lang_span->start_index));
diff --git a/ui/base/cocoa/menu_controller.mm b/ui/base/cocoa/menu_controller.mm
index 2dfefc53..43a13a3 100644
--- a/ui/base/cocoa/menu_controller.mm
+++ b/ui/base/cocoa/menu_controller.mm
@@ -166,37 +166,33 @@
   ui::MenuModel::ItemType type = model->GetTypeAt(index);
   if (type == ui::MenuModel::TYPE_SUBMENU && model->IsVisibleAt(index)) {
     ui::MenuModel* submenuModel = model->GetSubmenuModelAt(index);
-
     // If there are visible items, recursively build the submenu.
     NSMenu* submenu = MenuHasVisibleItems(submenuModel)
                           ? [self menuFromModel:submenuModel]
                           : MakeEmptySubmenu();
-
-    [item setTarget:nil];
-    [item setAction:nil];
     [item setSubmenu:submenu];
-  } else {
-    // The MenuModel works on indexes so we can't just set the command id as the
-    // tag like we do in other menus. Also set the represented object to be
-    // the model so hierarchical menus check the correct index in the correct
-    // model. Setting the target to |self| allows this class to participate
-    // in validation of the menu items.
-    [item setTag:index];
-    [item setTarget:self];
-    NSValue* modelObject = [NSValue valueWithPointer:model];
-    [item setRepresentedObject:modelObject];  // Retains |modelObject|.
-    // On the Mac, context menus never have accelerators. Menus constructed
-    // for context use have useWithPopUpButtonCell_ set to NO.
-    if (useWithPopUpButtonCell_) {
-      ui::Accelerator accelerator;
-      if (model->GetAcceleratorAt(index, &accelerator)) {
-        NSString* key_equivalent;
-        NSUInteger modifier_mask;
-        GetKeyEquivalentAndModifierMaskFromAccelerator(
-            accelerator, &key_equivalent, &modifier_mask);
-        [item setKeyEquivalent:key_equivalent];
-        [item setKeyEquivalentModifierMask:modifier_mask];
-      }
+  }
+
+  // The MenuModel works on indexes so we can't just set the command id as the
+  // tag like we do in other menus. Also set the represented object to be
+  // the model so hierarchical menus check the correct index in the correct
+  // model. Setting the target to |self| allows this class to participate
+  // in validation of the menu items.
+  [item setTag:index];
+  [item setTarget:self];
+  NSValue* modelObject = [NSValue valueWithPointer:model];
+  [item setRepresentedObject:modelObject];  // Retains |modelObject|.
+  // On the Mac, context menus never have accelerators. Menus constructed
+  // for context use have useWithPopUpButtonCell_ set to NO.
+  if (useWithPopUpButtonCell_) {
+    ui::Accelerator accelerator;
+    if (model->GetAcceleratorAt(index, &accelerator)) {
+      NSString* key_equivalent;
+      NSUInteger modifier_mask;
+      GetKeyEquivalentAndModifierMaskFromAccelerator(
+          accelerator, &key_equivalent, &modifier_mask);
+      [item setKeyEquivalent:key_equivalent];
+      [item setKeyEquivalentModifierMask:modifier_mask];
     }
   }
   [menu insertItem:item atIndex:index];
diff --git a/ui/base/cocoa/menu_controller_unittest.mm b/ui/base/cocoa/menu_controller_unittest.mm
index c104f9ea..87d84c40 100644
--- a/ui/base/cocoa/menu_controller_unittest.mm
+++ b/ui/base/cocoa/menu_controller_unittest.mm
@@ -423,6 +423,49 @@
   EXPECT_TRUE(delegate.did_close_);
 }
 
+TEST_F(MenuControllerTest, DisabledSubmenu) {
+  // SimpleMenuModel posts a task that calls Delegate::MenuClosed. Create
+  // a MessageLoop for that purpose.
+  base::MessageLoopForUI message_loop;
+
+  // Create the model.
+  Delegate delegate;
+  SimpleMenuModel model(&delegate);
+  model.AddItem(1, ASCIIToUTF16("one"));
+  SimpleMenuModel submodel(&delegate);
+  submodel.AddItem(2, ASCIIToUTF16("sub"));
+  model.AddSubMenuWithStringId(3, kTestLabelResourceId, &submodel);
+
+  // Disable the submenu entry.
+  model.SetEnabledAt(1, false);
+
+  // Create the controller.
+  base::scoped_nsobject<MenuControllerCocoa> menu_controller(
+      [[MenuControllerCocoa alloc] initWithModel:&model
+                          useWithPopUpButtonCell:NO]);
+  delegate.menu_to_close_ = [menu_controller menu];
+
+  // Show the menu.
+  CFRunLoopPerformBlock(CFRunLoopGetCurrent(), NSEventTrackingRunLoopMode, ^{
+    EXPECT_TRUE([menu_controller isMenuOpen]);
+    // Ensure that the submenu is disabled.
+    NSMenuItem* item = [[menu_controller menu] itemAtIndex:1];
+    EXPECT_FALSE([item isEnabled]);
+  });
+
+  // Pop open the menu, which will spin an event-tracking run loop.
+  [NSMenu popUpContextMenu:[menu_controller menu]
+                 withEvent:cocoa_test_event_utils::RightMouseDownAtPoint(
+                               NSZeroPoint)
+                   forView:[test_window() contentView]];
+  EXPECT_FALSE([menu_controller isMenuOpen]);
+
+  // Pump the task that notifies the delegate.
+  base::RunLoop().RunUntilIdle();
+  // Expect that the delegate got notified properly.
+  EXPECT_TRUE(delegate.did_close_);
+}
+
 TEST_F(MenuControllerTest, PopUpButton) {
   Delegate delegate;
   SimpleMenuModel model(&delegate);
diff --git a/ui/base/ime/chromeos/BUILD.gn b/ui/base/ime/chromeos/BUILD.gn
index a76249de..b2ce01d 100644
--- a/ui/base/ime/chromeos/BUILD.gn
+++ b/ui/base/ime/chromeos/BUILD.gn
@@ -58,6 +58,6 @@
     "//third_party/icu",
     "//ui/base",
     "//ui/chromeos/strings",
-    "//ui/ozone",
+    "//ui/ozone:ozone_base",
   ]
 }
diff --git a/ui/base/ime/chromeos/ime_keyboard_impl.cc b/ui/base/ime/chromeos/ime_keyboard_impl.cc
index 5a35b01..2f5db43b 100644
--- a/ui/base/ime/chromeos/ime_keyboard_impl.cc
+++ b/ui/base/ime/chromeos/ime_keyboard_impl.cc
@@ -5,14 +5,12 @@
 #include "ui/base/ime/chromeos/ime_keyboard_impl.h"
 
 #include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
 
 namespace chromeos {
 namespace input_method {
 
-ImeKeyboardImpl::ImeKeyboardImpl()
-    : input_controller_(
-          ui::OzonePlatform::GetInstance()->GetInputController()) {}
+ImeKeyboardImpl::ImeKeyboardImpl(ui::InputController* input_controller)
+    : input_controller_(input_controller) {}
 
 ImeKeyboardImpl::~ImeKeyboardImpl() = default;
 
diff --git a/ui/base/ime/chromeos/ime_keyboard_impl.h b/ui/base/ime/chromeos/ime_keyboard_impl.h
index a06dcef..33edf34 100644
--- a/ui/base/ime/chromeos/ime_keyboard_impl.h
+++ b/ui/base/ime/chromeos/ime_keyboard_impl.h
@@ -20,7 +20,7 @@
 class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) ImeKeyboardImpl
     : public ImeKeyboard {
  public:
-  ImeKeyboardImpl();
+  ImeKeyboardImpl(ui::InputController* input_controller);
   ~ImeKeyboardImpl() override;
 
   // ImeKeyboard:
@@ -35,7 +35,7 @@
   bool CapsLockIsEnabled() override;
 
  private:
-  ui::InputController* input_controller_;
+  ui::InputController* const input_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(ImeKeyboardImpl);
 };
diff --git a/ui/base/ime/init/BUILD.gn b/ui/base/ime/init/BUILD.gn
index f054326..57c1503 100644
--- a/ui/base/ime/init/BUILD.gn
+++ b/ui/base/ime/init/BUILD.gn
@@ -33,13 +33,10 @@
   if (is_mac) {
     deps += [ "//ui/base/ime/mac" ]
   }
-  if (is_chromeos) {
-    deps += [ "//ui/base/ime/chromeos" ]
-  }
-  if (is_fuchsia) {
-    deps += [ "//ui/base/ime/fuchsia" ]
-  }
   if (is_linux && !is_chromeos) {
     deps += [ "//ui/base/ime/linux" ]
   }
+  if (use_ozone) {
+    deps += [ "//ui/ozone" ]
+  }
 }
diff --git a/ui/base/ime/init/DEPS b/ui/base/ime/init/DEPS
new file mode 100644
index 0000000..4127e4e5
--- /dev/null
+++ b/ui/base/ime/init/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ui/ozone/public"
+]
diff --git a/ui/base/ime/init/input_method_factory.cc b/ui/base/ime/init/input_method_factory.cc
index 81f7f8a9..e12ee43 100644
--- a/ui/base/ime/init/input_method_factory.cc
+++ b/ui/base/ime/init/input_method_factory.cc
@@ -12,17 +12,15 @@
 #include "ui/base/ui_base_features.h"
 #include "ui/gfx/switches.h"
 
-#if defined(OS_CHROMEOS)
-#include "ui/base/ime/chromeos/input_method_chromeos.h"
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
 #include "ui/base/ime/win/input_method_win_imm32.h"
 #include "ui/base/ime/win/input_method_win_tsf.h"
 #elif defined(OS_MACOSX)
 #include "ui/base/ime/mac/input_method_mac.h"
-#elif defined(OS_FUCHSIA)
-#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
-#elif defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
+#elif defined(USE_X11)
 #include "ui/base/ime/linux/input_method_auralinux.h"
+#elif defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
 #else
 #include "ui/base/ime/input_method_minimal.h"
 #endif
@@ -57,9 +55,7 @@
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
     return base::WrapUnique(new MockInputMethod(delegate));
 
-#if defined(OS_CHROMEOS)
-  return std::make_unique<InputMethodChromeOS>(delegate);
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
   if (base::FeatureList::IsEnabled(features::kTSFImeSupport) &&
       base::win::GetVersion() >= base::win::Version::WIN10_RS3) {
     return std::make_unique<InputMethodWinTSF>(delegate, widget);
@@ -67,10 +63,10 @@
   return std::make_unique<InputMethodWinImm32>(delegate, widget);
 #elif defined(OS_MACOSX)
   return std::make_unique<InputMethodMac>(delegate);
-#elif defined(OS_FUCHSIA)
-  return std::make_unique<InputMethodFuchsia>(delegate);
-#elif defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
+#elif defined(USE_X11)
   return std::make_unique<InputMethodAuraLinux>(delegate);
+#elif defined(USE_OZONE)
+  return ui::OzonePlatform::GetInstance()->CreateInputMethod(delegate);
 #else
   return std::make_unique<InputMethodMinimal>(delegate);
 #endif
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 7ac8af38..60c9ed4d 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -40,9 +40,10 @@
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/interpolated_transform.h"
 
+namespace ui {
 namespace {
 
-const ui::Layer* GetRoot(const ui::Layer* layer) {
+const Layer* GetRoot(const Layer* layer) {
   // Parent walk cannot be done on a layer that is being used as a mask. Get the
   // layer to which this layer is a mask of.
   if (layer->layer_mask_back_link())
@@ -65,8 +66,6 @@
 
 }  // namespace
 
-namespace ui {
-
 class Layer::LayerMirror : public LayerDelegate, LayerObserver {
  public:
   LayerMirror(Layer* source, Layer* dest)
@@ -300,20 +299,24 @@
   return mirror;
 }
 
-void Layer::MirrorLayer(Layer* mirrored_layer) {
+void Layer::SetShowReflectedLayerSubtree(Layer* subtree_reflected_layer) {
+  DCHECK(subtree_reflected_layer);
   DCHECK_EQ(type_, LAYER_SOLID_COLOR);
 
-  if (!mirrored_layer) {
-    SetShowSolidColorContent();
+  if (subtree_reflected_layer_ == subtree_reflected_layer)
     return;
-  }
 
-  auto new_layer = cc::MirrorLayer::Create(mirrored_layer->cc_layer_);
+  scoped_refptr<cc::MirrorLayer> new_layer =
+      cc::MirrorLayer::Create(subtree_reflected_layer->cc_layer_);
   SwitchToLayer(new_layer);
-  mirror_layer_ = new_layer;
-  gfx::Rect bounds = bounds_;
-  bounds.set_size(mirrored_layer->bounds().size());
-  SetBounds(bounds);
+  mirror_layer_ = std::move(new_layer);
+
+  subtree_reflected_layer_ = subtree_reflected_layer;
+  auto insert_pair =
+      subtree_reflected_layer_->subtree_reflecting_layers_.insert(this);
+  DCHECK(insert_pair.second);
+
+  MatchLayerSize(subtree_reflected_layer_);
 
   RecomputeDrawsContentAndUVRect();
 }
@@ -740,6 +743,13 @@
     animator_->SwitchToLayer(new_layer);
   }
 
+  if (subtree_reflected_layer_) {
+    size_t result =
+        subtree_reflected_layer_->subtree_reflecting_layers_.erase(this);
+    DCHECK_EQ(1u, result);
+    subtree_reflected_layer_ = nullptr;
+  }
+
   if (texture_layer_.get())
     texture_layer_->ClearClient();
 
@@ -1360,6 +1370,9 @@
     if (mirror_dest->sync_bounds_with_source_)
       mirror_dest->SetBounds(bounds);
   }
+
+  for (auto* reflecting_layer : subtree_reflecting_layers_)
+    reflecting_layer->MatchLayerSize(this);
 }
 
 void Layer::SetTransformFromAnimation(const gfx::Transform& transform,
@@ -1583,4 +1596,11 @@
   surface_layer_ = new_layer;
 }
 
+void Layer::MatchLayerSize(const Layer* layer) {
+  gfx::Rect new_bounds = bounds_;
+  gfx::Size new_size = layer->bounds().size();
+  new_bounds.set_size(new_size);
+  SetBounds(new_bounds);
+}
+
 }  // namespace ui
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 3579e9a..1453a06 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
@@ -80,13 +81,10 @@
   // Returns a new layer that mirrors this layer and is optionally synchronized
   // with the bounds thereof. Note that children are not mirrored, and that the
   // content is only mirrored if painted by a delegate or backed by a surface.
+  // As the mirror layer rasterizes its contents separately, this might have
+  // some negative impact on performance.
   std::unique_ptr<Layer> Mirror();
 
-  // Sets up this layer to mirror contents of |mirrored_layer|. This layer
-  // should be of type |LAYER_SOLID_COLOR| and should not be a descendant of the
-  // |mirrored_layer|.
-  void MirrorLayer(Layer* mirrored_layer);
-
   // This method is relevant only if this layer is a mirror destination layer.
   // Sets whether this mirror layer's bounds are synchronized with the source
   // layer's bounds.
@@ -94,6 +92,14 @@
     sync_bounds_with_source_ = sync_bounds;
   }
 
+  // Sets up this layer to mirror output of |subtree_reflected_layer|, including
+  // its entire hierarchy. |this| should be of type LAYER_SOLID_COLOR and should
+  // not be a descendant of |subtree_reflected_layer|. This is achieved by using
+  // cc::MirrorLayer which forces a render surface for |subtree_reflected_layer|
+  // to be able to embed it. This might cause extra GPU memory bandwidth and/or
+  // read/writes which can impact performance negatively.
+  void SetShowReflectedLayerSubtree(Layer* subtree_reflected_layer);
+
   // Retrieves the Layer's compositor. The Layer will walk up its parent chain
   // to locate it. Returns NULL if the Layer is not attached to a compositor.
   Compositor* GetCompositor() {
@@ -583,6 +589,9 @@
 
   void CreateSurfaceLayerIfNecessary();
 
+  // Changes the size of |this| to match that of |layer|.
+  void MatchLayerSize(const Layer* layer);
+
   const LayerType type_;
 
   Compositor* compositor_;
@@ -594,6 +603,12 @@
 
   std::vector<std::unique_ptr<LayerMirror>> mirrors_;
 
+  // The layer being reflected with its subtree by this one, if any.
+  Layer* subtree_reflected_layer_ = nullptr;
+
+  // List of layers reflecting this layer and its subtree, if any.
+  base::flat_set<Layer*> subtree_reflecting_layers_;
+
   // If true, and this is a destination mirror layer, changes to the bounds of
   // the source layer are propagated to this mirror layer.
   bool sync_bounds_with_source_ = false;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 5ec002c..7c6aaf0 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -1512,67 +1512,72 @@
   EXPECT_EQ(mask->damaged_region_for_testing().bounds(), gfx::Rect());
 }
 
-// Verifies that when a layer is mirroring other layers, mirror count
-// of mirrored layers is updated properly.
-TEST_F(LayerWithNullDelegateTest, MirrorLayer) {
-  std::unique_ptr<Layer> mirrored_layer_1(CreateLayer(LAYER_SOLID_COLOR));
-  auto* mirrored_layer_1_cc = mirrored_layer_1->cc_layer_for_testing();
+// Verifies that when a layer is reflecting other layers, mirror counts of
+// reflected layers are updated properly.
+TEST_F(LayerWithNullDelegateTest, SetShowReflectedLayerSubtree) {
+  std::unique_ptr<Layer> reflected_layer_1(CreateLayer(LAYER_SOLID_COLOR));
+  auto* reflected_layer_1_cc = reflected_layer_1->cc_layer_for_testing();
 
-  std::unique_ptr<Layer> mirrored_layer_2(CreateLayer(LAYER_SOLID_COLOR));
-  auto* mirrored_layer_2_cc = mirrored_layer_2->cc_layer_for_testing();
+  std::unique_ptr<Layer> reflected_layer_2(CreateLayer(LAYER_SOLID_COLOR));
+  auto* reflected_layer_2_cc = reflected_layer_2->cc_layer_for_testing();
 
-  std::unique_ptr<Layer> mirror_layer(CreateLayer(LAYER_SOLID_COLOR));
+  std::unique_ptr<Layer> reflecting_layer(CreateLayer(LAYER_SOLID_COLOR));
 
   // Originally, mirror counts should be zero.
-  auto* mirror_layer_cc = mirror_layer->mirror_layer_for_testing();
-  EXPECT_EQ(nullptr, mirror_layer_cc);
-  EXPECT_EQ(0, mirrored_layer_1_cc->mirror_count());
-  EXPECT_EQ(0, mirrored_layer_2_cc->mirror_count());
+  auto* reflecting_layer_cc = reflecting_layer->mirror_layer_for_testing();
+  EXPECT_EQ(nullptr, reflecting_layer_cc);
+  EXPECT_EQ(0, reflected_layer_1_cc->mirror_count());
+  EXPECT_EQ(0, reflected_layer_2_cc->mirror_count());
 
   // Mirror the first layer. Its mirror count should be increased.
-  mirror_layer->MirrorLayer(mirrored_layer_1.get());
-  mirror_layer_cc = mirror_layer->mirror_layer_for_testing();
-  ASSERT_NE(nullptr, mirror_layer_cc);
-  EXPECT_EQ(mirror_layer->cc_layer_for_testing(), mirror_layer_cc);
-  EXPECT_EQ(mirrored_layer_1_cc, mirror_layer_cc->mirrored_layer());
-  EXPECT_EQ(1, mirrored_layer_1_cc->mirror_count());
-  EXPECT_EQ(0, mirrored_layer_2_cc->mirror_count());
+  reflecting_layer->SetShowReflectedLayerSubtree(reflected_layer_1.get());
+  reflecting_layer_cc = reflecting_layer->mirror_layer_for_testing();
+  ASSERT_NE(nullptr, reflecting_layer_cc);
+  EXPECT_EQ(reflecting_layer->cc_layer_for_testing(), reflecting_layer_cc);
+  EXPECT_EQ(reflected_layer_1_cc, reflecting_layer_cc->mirrored_layer());
+  EXPECT_EQ(1, reflected_layer_1_cc->mirror_count());
+  EXPECT_EQ(0, reflected_layer_2_cc->mirror_count());
 
   // Mirror the second layer. Its mirror count should be increased, but mirror
   // count for the first mirrored layer should be set back to zero.
-  mirror_layer->MirrorLayer(mirrored_layer_2.get());
-  mirror_layer_cc = mirror_layer->mirror_layer_for_testing();
-  ASSERT_NE(nullptr, mirror_layer_cc);
-  EXPECT_EQ(mirror_layer->cc_layer_for_testing(), mirror_layer_cc);
-  EXPECT_EQ(mirrored_layer_2_cc, mirror_layer_cc->mirrored_layer());
-  EXPECT_EQ(0, mirrored_layer_1_cc->mirror_count());
-  EXPECT_EQ(1, mirrored_layer_2_cc->mirror_count());
+  reflecting_layer->SetShowReflectedLayerSubtree(reflected_layer_2.get());
+  reflecting_layer_cc = reflecting_layer->mirror_layer_for_testing();
+  ASSERT_NE(nullptr, reflecting_layer_cc);
+  EXPECT_EQ(reflecting_layer->cc_layer_for_testing(), reflecting_layer_cc);
+  EXPECT_EQ(reflected_layer_2_cc, reflecting_layer_cc->mirrored_layer());
+  EXPECT_EQ(0, reflected_layer_1_cc->mirror_count());
+  EXPECT_EQ(1, reflected_layer_2_cc->mirror_count());
 
   // Un-mirror the layer. All mirror counts should be set to zero.
-  mirror_layer->MirrorLayer(nullptr);
-  mirror_layer_cc = mirror_layer->mirror_layer_for_testing();
-  EXPECT_EQ(nullptr, mirror_layer_cc);
-  EXPECT_EQ(0, mirrored_layer_1_cc->mirror_count());
-  EXPECT_EQ(0, mirrored_layer_2_cc->mirror_count());
+  reflecting_layer->SetShowSolidColorContent();
+  reflecting_layer_cc = reflecting_layer->mirror_layer_for_testing();
+  EXPECT_EQ(nullptr, reflecting_layer_cc);
+  EXPECT_EQ(0, reflected_layer_1_cc->mirror_count());
+  EXPECT_EQ(0, reflected_layer_2_cc->mirror_count());
 }
 
-// Verifies that when a layer is mirroring another layer, its size matches the
-// size of the mirrored layer.
-TEST_F(LayerWithNullDelegateTest, MirrorLayerBounds) {
-  const gfx::Rect mirrored_bounds(0, 0, 50, 50);
-  const gfx::Rect mirror_bounds(0, 50, 10, 10);
+// Verifies that when a layer is reflecting another layer, its size matches the
+// size of the reflected layer.
+TEST_F(LayerWithNullDelegateTest, SetShowReflectedLayerSubtreeBounds) {
+  const gfx::Rect reflected_bounds(0, 0, 50, 50);
+  const gfx::Rect reflecting_bounds(0, 50, 10, 10);
 
-  std::unique_ptr<Layer> mirrored_layer(CreateLayer(LAYER_SOLID_COLOR));
-  mirrored_layer->SetBounds(mirrored_bounds);
+  std::unique_ptr<Layer> reflected_layer(CreateLayer(LAYER_SOLID_COLOR));
+  reflected_layer->SetBounds(reflected_bounds);
 
-  std::unique_ptr<Layer> mirror_layer(CreateLayer(LAYER_SOLID_COLOR));
-  mirror_layer->SetBounds(mirror_bounds);
+  std::unique_ptr<Layer> reflecting_layer(CreateLayer(LAYER_SOLID_COLOR));
+  reflecting_layer->SetBounds(reflecting_bounds);
 
-  EXPECT_EQ(mirror_bounds, mirror_layer->bounds());
+  EXPECT_EQ(reflecting_bounds, reflecting_layer->bounds());
 
-  mirror_layer->MirrorLayer(mirrored_layer.get());
-  EXPECT_EQ(mirror_bounds.origin(), mirror_layer->bounds().origin());
-  EXPECT_EQ(mirrored_bounds.size(), mirror_layer->bounds().size());
+  reflecting_layer->SetShowReflectedLayerSubtree(reflected_layer.get());
+  EXPECT_EQ(reflecting_bounds.origin(), reflecting_layer->bounds().origin());
+  EXPECT_EQ(reflected_bounds.size(), reflecting_layer->bounds().size());
+
+  const gfx::Rect new_reflected_bounds(10, 10, 30, 30);
+  reflected_layer->SetBounds(new_reflected_bounds);
+  EXPECT_EQ(reflecting_bounds.origin(), reflecting_layer->bounds().origin());
+  EXPECT_EQ(new_reflected_bounds.size(), reflecting_layer->bounds().size());
 }
 
 void ExpectRgba(int x, int y, SkColor expected_color, SkColor actual_color) {
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index 294ecbf..b89f035 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -272,8 +272,7 @@
       compositor->frame_sink_id(), GetHostFrameSinkManager(),
       GetFrameSinkManager(), display, nullptr /* display_client */,
       context_provider, shared_worker_context_provider_,
-      compositor->task_runner(), &gpu_memory_buffer_manager_,
-      false /* use_viz_hit_test */);
+      compositor->task_runner(), &gpu_memory_buffer_manager_);
   compositor->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink));
 
   data->display->Resize(compositor->size());
diff --git a/ui/file_manager/base/js/volume_manager_types.js b/ui/file_manager/base/js/volume_manager_types.js
index f0d9cf8..2e74b938 100644
--- a/ui/file_manager/base/js/volume_manager_types.js
+++ b/ui/file_manager/base/js/volume_manager_types.js
@@ -43,8 +43,9 @@
  * @const
  */
 VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit = {
-  VFAT: 11,
-  EXFAT: 15,
+  [VolumeManagerCommon.FileSystemType.VFAT]: 11,
+  [VolumeManagerCommon.FileSystemType.EXFAT]: 15,
+  [VolumeManagerCommon.FileSystemType.NTFS]: 32,
 };
 
 /**
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js
index f8709a15..a4c27f0 100644
--- a/ui/file_manager/file_manager/common/js/util.js
+++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1299,21 +1299,13 @@
 
   const fileSystem = volumeInfo.diskFileSystemType;
   const nameLength = name.length;
+  const lengthLimit = VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit;
 
   // Verify length for the target file system type
-  if (fileSystem == VolumeManagerCommon.FileSystemType.VFAT &&
-      nameLength >
-          VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit.VFAT) {
-    return Promise.reject(strf(
-        'ERROR_EXTERNAL_DRIVE_LONG_NAME',
-        VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit.VFAT));
-  } else if (
-      fileSystem == VolumeManagerCommon.FileSystemType.EXFAT &&
-      nameLength >
-          VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit.EXFAT) {
-    return Promise.reject(strf(
-        'ERROR_EXTERNAL_DRIVE_LONG_NAME',
-        VolumeManagerCommon.FileSystemTypeVolumeNameLengthLimit.EXFAT));
+  if (lengthLimit.hasOwnProperty(fileSystem) &&
+      nameLength > lengthLimit[fileSystem]) {
+    return Promise.reject(
+        strf('ERROR_EXTERNAL_DRIVE_LONG_NAME', lengthLimit[fileSystem]));
   }
 
   // Checks if name contains only printable ASCII (from ' ' to '~')
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index e551089..c2e7eff 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -454,9 +454,10 @@
  * Supported disk file system types for renaming.
  * @private @const {!Array<!VolumeManagerCommon.FileSystemType>}
  */
-CommandHandler.RENAME_DISK_FILE_SYSYTEM_SUPPORT_ = [
+CommandHandler.RENAME_DISK_FILE_SYSTEM_SUPPORT_ = [
   VolumeManagerCommon.FileSystemType.EXFAT,
-  VolumeManagerCommon.FileSystemType.VFAT
+  VolumeManagerCommon.FileSystemType.VFAT,
+  VolumeManagerCommon.FileSystemType.NTFS,
 ];
 
 /**
@@ -1223,7 +1224,7 @@
           const removable =
               location.rootType === VolumeManagerCommon.RootType.REMOVABLE;
           event.canExecute = removable && writable &&
-              CommandHandler.RENAME_DISK_FILE_SYSYTEM_SUPPORT_.indexOf(
+              CommandHandler.RENAME_DISK_FILE_SYSTEM_SUPPORT_.indexOf(
                   volumeInfo.diskFileSystemType) > -1;
           event.command.setHidden(!removable);
           return removable;
diff --git a/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js b/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
index c20e0aff..3609d7c 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata_box_controller.js
@@ -72,17 +72,19 @@
  * @param{!FilesQuickView} quickView
  */
 MetadataBoxController.prototype.init = function(quickView) {
+  this.metadataBox_ = quickView.getFilesMetadataBox();
+  this.quickView_ = quickView;
+
   this.fileMetadataFormatter_.addEventListener(
       'date-time-format-changed', this.updateView_.bind(this));
 
-  quickView.addEventListener(
+  this.quickView_.addEventListener(
       'metadata-box-active-changed', this.updateView_.bind(this));
 
   this.quickViewModel_.addEventListener(
       'selected-entry-changed', this.updateView_.bind(this));
 
-  this.metadataBox_ = quickView.getFilesMetadataBox();
-  this.quickView_ = quickView;
+  this.metadataBox_.clear(false);
 };
 
 /**
@@ -108,8 +110,7 @@
   this.previousEntry_ = entry;
 
   if (!entry) {
-    // Do not clear isSizeLoading and size fields when the entry is not changed.
-    this.metadataBox_.clear(isSameEntry);
+    this.metadataBox_.clear(false);
     return;
   }
 
@@ -144,16 +145,13 @@
   const type = FileType.getType(entry).type;
   const item = items[0];
 
-  this.metadataBox_.type = type;
-  // For directory, item.size is always -1.
-  if (item.size && !entry.isDirectory) {
+  if (entry.isDirectory) {
+    const directory = /** @type {!DirectoryEntry} */ (entry);
+    this.setDirectorySize_(directory, isSameEntry);
+  } else if (item.size) {
     this.metadataBox_.size =
         this.fileMetadataFormatter_.formatSize(item.size, item.hosted);
   }
-  if (entry.isDirectory) {
-    this.setDirectorySize_(
-        /** @type {!DirectoryEntry} */ (entry), isSameEntry);
-  }
 
   this.updateModificationTime_(entry, isSameEntry, items);
 
@@ -169,6 +167,8 @@
     });
   }
 
+  this.metadataBox_.type = type;
+
   if (['image', 'video', 'audio'].includes(type)) {
     if (item.externalFileUrl || item.alternateUrl) {
       this.metadataModel_.get([entry], ['imageHeight', 'imageWidth'])
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
index 94c98f2..8fe197e 100644
--- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
+++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -895,12 +895,18 @@
    * Tests context menu for USB root (single and multiple partitions).
    */
   testcase.dirContextMenuUsbs = async () => {
-    const singleUsbMenus = [
+    const ext4UsbMenus = [
       ['#unmount', true],
       ['#format', true],
       ['#rename', false],
       ['#share-with-linux', true],
     ];
+    const ntfsUsbMenus = [
+      ['#unmount', true],
+      ['#format', true],
+      ['#rename', true],
+      ['#share-with-linux', true],
+    ];
     const partitionsRootMenus = [
       ['#unmount', true],
       ['#format', false],
@@ -932,7 +938,7 @@
 
     // Check the context menu for single partition ext4 USB.
     await checkContextMenu(
-        appId, '/fake-usb', singleUsbMenus, true /* rootMenu */);
+        appId, '/fake-usb', ext4UsbMenus, true /* rootMenu */);
 
     // Check the context menu for a folder inside a single USB partition.
     await checkContextMenu(
@@ -950,6 +956,14 @@
     // Check the context menu for a folder inside a partition1.
     await checkContextMenu(
         appId, '/Drive Label/partition-1/A', folderMenus, false /* rootMenu */);
+
+    // Remount the single partition ext4 USB as NTFS
+    await sendTestMessage({name: 'unmountUsb'});
+    await sendTestMessage({name: 'mountFakeUsb', filesystem: 'ntfs'});
+
+    // Check the context menu for a single partition NTFS USB.
+    await checkContextMenu(
+        appId, '/fake-usb', ntfsUsbMenus, true /* rootMenu */);
   };
 
   /**
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 5251812..78cdbc9 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -85,8 +85,6 @@
     "gl_enums.h",
     "gl_enums_implementation_autogen.h",
     "gl_export.h",
-    "gl_features.cc",
-    "gl_features.h",
     "gl_fence.cc",
     "gl_fence.h",
     "gl_fence_arb.cc",
diff --git a/ui/gl/egl_api_unittest.cc b/ui/gl/egl_api_unittest.cc
index 045b8c9..bbf2ce1e 100644
--- a/ui/gl/egl_api_unittest.cc
+++ b/ui/gl/egl_api_unittest.cc
@@ -4,7 +4,6 @@
 
 #include <memory>
 
-#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gl/gl_egl_api_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
@@ -27,11 +26,7 @@
     g_driver_egl.fn.eglGetErrorFn = &FakeGetError;
     g_driver_egl.fn.eglGetProcAddressFn = &FakeGetProcAddress;
 
-#if defined(OS_WIN)
-    SetGLImplementation(kGLImplementationEGLANGLE);
-#else
     SetGLImplementation(kGLImplementationEGLGLES2);
-#endif
   }
 
   void TearDown() override {
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index deb062b..a42e2f08 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -227,7 +227,6 @@
     case kGLImplementationDesktopGL:
       return false;
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
     case kGLImplementationSwiftShaderGL:
       return true;
     case kGLImplementationAppleGL:
diff --git a/ui/gl/gl_features.cc b/ui/gl/gl_features.cc
deleted file mode 100644
index fb21871..0000000
--- a/ui/gl/gl_features.cc
+++ /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.
-
-#include "ui/gl/gl_features.h"
-
-namespace features {
-
-// Use the passthrough command decoder by default.  This can be overridden with
-// the --use-cmd-decoder=passthrough or --use-cmd-decoder=validating flags.
-// Feature lives in ui/gl because it affects the GL binding initialization on
-// platforms that would otherwise not default to using EGL bindings.
-const base::Feature kDefaultPassthroughCommandDecoder{
-    "DefaultPassthroughCommandDecoder", base::FEATURE_DISABLED_BY_DEFAULT};
-
-}  // namespace features
\ No newline at end of file
diff --git a/ui/gl/gl_features.h b/ui/gl/gl_features.h
deleted file mode 100644
index 3513df1..0000000
--- a/ui/gl/gl_features.h
+++ /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.
-
-#ifndef UI_GL_GL_FEATURES_H_
-#define UI_GL_GL_FEATURES_H_
-
-#include "base/feature_list.h"
-#include "build/build_config.h"
-#include "ui/gl/gl_export.h"
-
-namespace features {
-
-// All features in alphabetical order. The features should be documented
-// alongside the definition of their values in the .cc file.
-GL_EXPORT extern const base::Feature kDefaultPassthroughCommandDecoder;
-
-}  // namespace features
-
-#endif  // UI_GL_GL_FEATURES_H_
diff --git a/ui/gl/gl_image_native_pixmap_unittest.cc b/ui/gl/gl_image_native_pixmap_unittest.cc
index efaddc4..83fe0f3 100644
--- a/ui/gl/gl_image_native_pixmap_unittest.cc
+++ b/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/gl/gl_image_native_pixmap.h"
 
-#include "build/build_config.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/test/gl_image_test_template.h"
 
@@ -34,11 +33,7 @@
  public:
   base::Optional<GLImplementation> GetPreferedGLImplementation()
       const override {
-#if defined(OS_WIN)
-    return base::Optional<GLImplementation>(kGLImplementationEGLANGLE);
-#else
     return base::Optional<GLImplementation>(kGLImplementationEGLGLES2);
-#endif
   }
 
   bool SkipTest() const override {
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index 8ade2d1..68d8a5d6 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -37,7 +37,6 @@
     {kGLImplementationAppleName, kGLImplementationAppleGL},
 #endif
     {kGLImplementationEGLName, kGLImplementationEGLGLES2},
-    {kGLImplementationANGLEName, kGLImplementationEGLANGLE},
     {kGLImplementationMockName, kGLImplementationMockGL},
     {kGLImplementationStubName, kGLImplementationStubGL},
     {kGLImplementationDisabledName, kGLImplementationDisabled}};
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
index 91036f59..8a2b295 100644
--- a/ui/gl/gl_implementation.h
+++ b/ui/gl/gl_implementation.h
@@ -30,12 +30,11 @@
   kGLImplementationDesktopGLCoreProfile = 2,
   kGLImplementationSwiftShaderGL = 3,
   kGLImplementationAppleGL = 4,
-  kGLImplementationEGLGLES2 = 5,  // Native EGL/GLES2
+  kGLImplementationEGLGLES2 = 5,
   kGLImplementationMockGL = 6,
   kGLImplementationStubGL = 7,
   kGLImplementationDisabled = 8,
-  kGLImplementationEGLANGLE = 9,  // EGL/GL implemented using ANGLE
-  kMaxValue = kGLImplementationEGLANGLE,
+  kMaxValue = kGLImplementationDisabled,
 };
 
 struct GL_EXPORT GLWindowSystemBindingInfo {
diff --git a/ui/gl/gl_surface_egl_unittest.cc b/ui/gl/gl_surface_egl_unittest.cc
index 8d9af305..58e3d42 100644
--- a/ui/gl/gl_surface_egl_unittest.cc
+++ b/ui/gl/gl_surface_egl_unittest.cc
@@ -30,13 +30,8 @@
 class GLSurfaceEGLTest : public testing::Test {
  protected:
   void SetUp() override {
-#if defined(OS_WIN)
-    GLSurfaceTestSupport::InitializeOneOffImplementation(
-        GLImplementation::kGLImplementationEGLANGLE, true);
-#else
     GLSurfaceTestSupport::InitializeOneOffImplementation(
         GLImplementation::kGLImplementationEGLGLES2, true);
-#endif
   }
 
   void TearDown() override { gl::init::ShutdownGL(false); }
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index bb154dd..d87c5fd 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -32,10 +32,6 @@
 const char kANGLEImplementationOpenGLESNULLName[] = "gles-null";
 const char kANGLEImplementationVulkanNULLName[] = "vulkan-null";
 
-// The command decoder names that can be passed to --use-cmd-decoder.
-const char kCmdDecoderValidatingName[] = "validating";
-const char kCmdDecoderPassthroughName[] = "passthrough";
-
 }  // namespace gl
 
 namespace switches {
@@ -70,12 +66,6 @@
 //  gles: GLES renderer, ES2 and ES3.
 const char kUseANGLE[]                      = "use-angle";
 
-// Use the Pass-through command decoder, skipping all validation and state
-// tracking. Switch lives in ui/gl because it affects the GL binding
-// initialization on platforms that would otherwise not default to using
-// EGL bindings.
-const char kUseCmdDecoder[] = "use-cmd-decoder";
-
 // ANGLE features are defined per-backend in third_party/angle/include/platform
 // Enables specified comma separated ANGLE features if found.
 const char kEnableANGLEFeatures[] = "enable-angle-features";
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index 97e7ff4..5f234aa 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -36,9 +36,6 @@
 GL_EXPORT extern const char kANGLEImplementationOpenGLESNULLName[];
 GL_EXPORT extern const char kANGLEImplementationVulkanNULLName[];
 
-GL_EXPORT extern const char kCmdDecoderValidatingName[];
-GL_EXPORT extern const char kCmdDecoderPassthroughName[];
-
 }  // namespace gl
 
 namespace switches {
@@ -52,7 +49,6 @@
 GL_EXPORT extern const char kGpuNoContextLost[];
 
 GL_EXPORT extern const char kUseANGLE[];
-GL_EXPORT extern const char kUseCmdDecoder[];
 GL_EXPORT extern const char kEnableANGLEFeatures[];
 GL_EXPORT extern const char kDisableANGLEFeatures[];
 GL_EXPORT extern const char kUseGL[];
diff --git a/ui/gl/gl_utils.cc b/ui/gl/gl_utils.cc
index 62589b4..31eefc4 100644
--- a/ui/gl/gl_utils.cc
+++ b/ui/gl/gl_utils.cc
@@ -8,8 +8,6 @@
 
 #include "base/logging.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_features.h"
-#include "ui/gl/gl_switches.h"
 
 #if defined(OS_ANDROID)
 #include "base/posix/eintr_wrapper.h"
@@ -40,21 +38,4 @@
   return merged;
 }
 #endif
-
-bool UsePassthroughCommandDecoder(const base::CommandLine* command_line) {
-  std::string switch_value;
-  if (command_line->HasSwitch(switches::kUseCmdDecoder)) {
-    switch_value = command_line->GetSwitchValueASCII(switches::kUseCmdDecoder);
-  }
-
-  if (switch_value == kCmdDecoderPassthroughName) {
-    return true;
-  } else if (switch_value == kCmdDecoderValidatingName) {
-    return false;
-  } else {
-    // Unrecognized or missing switch, use the default.
-    return base::FeatureList::IsEnabled(
-        features::kDefaultPassthroughCommandDecoder);
-  }
-}
 }
diff --git a/ui/gl/gl_utils.h b/ui/gl/gl_utils.h
index 84303c6..4dce955 100644
--- a/ui/gl/gl_utils.h
+++ b/ui/gl/gl_utils.h
@@ -7,7 +7,6 @@
 #ifndef UI_GL_GL_UTILS_H_
 #define UI_GL_GL_UTILS_H_
 
-#include "base/command_line.h"
 #include "build/build_config.h"
 #include "ui/gl/gl_export.h"
 
@@ -21,10 +20,6 @@
 #if defined(OS_ANDROID)
 GL_EXPORT base::ScopedFD MergeFDs(base::ScopedFD a, base::ScopedFD b);
 #endif
-
-GL_EXPORT bool UsePassthroughCommandDecoder(
-    const base::CommandLine* command_line);
-
 }  // namespace gl
 
 #endif  // UI_GL_GL_UTILS_H_
diff --git a/ui/gl/init/gl_factory.cc b/ui/gl/init/gl_factory.cc
index e204ecd..9d71f34 100644
--- a/ui/gl/init/gl_factory.cc
+++ b/ui/gl/init/gl_factory.cc
@@ -13,7 +13,6 @@
 #include "base/trace_event/trace_event.h"
 #include "ui/gl/gl_share_group.h"
 #include "ui/gl/gl_surface.h"
-#include "ui/gl/gl_utils.h"
 #include "ui/gl/gl_version_info.h"
 #include "ui/gl/init/gl_initializer.h"
 
@@ -45,16 +44,6 @@
     GLVersionInfo::DisableES3ForTesting();
   }
 
-  // If the passthrough command decoder is enabled, put ANGLE first if allowed
-  if (gl::UsePassthroughCommandDecoder(cmd)) {
-    auto iter = std::find(allowed_impls.begin(), allowed_impls.end(),
-                          kGLImplementationEGLANGLE);
-    if (iter != allowed_impls.end()) {
-      allowed_impls.erase(iter);
-      allowed_impls.insert(allowed_impls.begin(), kGLImplementationEGLANGLE);
-    }
-  }
-
   if (allowed_impls.empty()) {
     LOG(ERROR) << "List of allowed GL implementations is empty.";
     return false;
@@ -73,6 +62,8 @@
                (requested_implementation_name ==
                 kGLImplementationSwiftShaderForWebGLName)) {
       impl = kGLImplementationSwiftShaderGL;
+    } else if (requested_implementation_name == kGLImplementationANGLEName) {
+      impl = kGLImplementationEGLGLES2;
     } else {
       impl = GetNamedGLImplementation(requested_implementation_name);
       if (!base::Contains(allowed_impls, impl)) {
diff --git a/ui/gl/init/gl_factory_win.cc b/ui/gl/init/gl_factory_win.cc
index 8631402..973fc4f 100644
--- a/ui/gl/init/gl_factory_win.cc
+++ b/ui/gl/init/gl_factory_win.cc
@@ -25,7 +25,7 @@
 
 std::vector<GLImplementation> GetAllowedGLImplementations() {
   std::vector<GLImplementation> impls;
-  impls.push_back(kGLImplementationEGLANGLE);
+  impls.push_back(kGLImplementationEGLGLES2);
   impls.push_back(kGLImplementationDesktopGL);
   impls.push_back(kGLImplementationSwiftShaderGL);
   return impls;
@@ -36,7 +36,7 @@
   switch (GetGLImplementation()) {
     case kGLImplementationDesktopGL:
       return GetGLWindowSystemBindingInfoWGL(info);
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       return GetGLWindowSystemBindingInfoEGL(info);
     default:
       return false;
@@ -49,7 +49,7 @@
   TRACE_EVENT0("gpu", "gl::init::CreateGLContext");
   switch (GetGLImplementation()) {
     case kGLImplementationSwiftShaderGL:
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       return InitializeGLContext(new GLContextEGL(share_group),
                                  compatible_surface, attribs);
     case kGLImplementationDesktopGL:
@@ -73,7 +73,7 @@
   TRACE_EVENT0("gpu", "gl::init::CreateViewGLSurface");
   switch (GetGLImplementation()) {
     case kGLImplementationSwiftShaderGL:
-    case kGLImplementationEGLANGLE: {
+    case kGLImplementationEGLGLES2: {
       DCHECK_NE(window, gfx::kNullAcceleratedWidget);
       return InitializeGLSurface(base::MakeRefCounted<NativeViewGLSurfaceEGL>(
           window, std::make_unique<VSyncProviderWin>(window)));
@@ -95,7 +95,7 @@
   TRACE_EVENT0("gpu", "gl::init::CreateOffscreenGLSurface");
   switch (GetGLImplementation()) {
     case kGLImplementationSwiftShaderGL:
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
           size.width() == 0 && size.height() == 0) {
         return InitializeGLSurfaceWithFormat(new SurfacelessEGL(size), format);
@@ -122,7 +122,7 @@
     case kGLImplementationDesktopGL:
       SetDisabledExtensionsWGL(disabled_extensions);
       break;
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       SetDisabledExtensionsEGL(disabled_extensions);
       break;
     case kGLImplementationSwiftShaderGL:
@@ -140,7 +140,7 @@
   switch (implementation) {
     case kGLImplementationDesktopGL:
       return InitializeExtensionSettingsOneOffWGL();
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       return InitializeExtensionSettingsOneOffEGL();
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationMockGL:
diff --git a/ui/gl/init/gl_factory_x11.cc b/ui/gl/init/gl_factory_x11.cc
index 576f2d2..f6efd5d10 100644
--- a/ui/gl/init/gl_factory_x11.cc
+++ b/ui/gl/init/gl_factory_x11.cc
@@ -27,7 +27,6 @@
   std::vector<GLImplementation> impls;
   impls.push_back(kGLImplementationDesktopGL);
   impls.push_back(kGLImplementationEGLGLES2);
-  impls.push_back(kGLImplementationEGLANGLE);
   impls.push_back(kGLImplementationSwiftShaderGL);
   return impls;
 }
@@ -38,7 +37,6 @@
     case kGLImplementationDesktopGL:
       return GetGLWindowSystemBindingInfoGLX(gl_info, info);
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       return GetGLWindowSystemBindingInfoEGL(info);
     default:
       return false;
@@ -55,7 +53,6 @@
                                  compatible_surface, attribs);
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       return InitializeGLContext(new GLContextEGL(share_group),
                                  compatible_surface, attribs);
     case kGLImplementationMockGL:
@@ -79,7 +76,6 @@
       return InitializeGLSurface(new GLSurfaceGLXX11(window));
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       DCHECK(window != gfx::kNullAcceleratedWidget);
       return InitializeGLSurface(new NativeViewGLSurfaceEGLX11(window));
     case kGLImplementationMockGL:
@@ -100,7 +96,6 @@
           new UnmappedNativeViewGLSurfaceGLX(size), format);
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
           size.width() == 0 && size.height() == 0) {
         return InitializeGLSurfaceWithFormat(new SurfacelessEGL(size), format);
@@ -125,7 +120,6 @@
       SetDisabledExtensionsGLX(disabled_extensions);
       break;
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       SetDisabledExtensionsEGL(disabled_extensions);
       break;
     case kGLImplementationSwiftShaderGL:
@@ -144,7 +138,6 @@
     case kGLImplementationDesktopGL:
       return InitializeExtensionSettingsOneOffGLX();
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       return InitializeExtensionSettingsOneOffEGL();
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationMockGL:
diff --git a/ui/gl/init/gl_initializer_win.cc b/ui/gl/init/gl_initializer_win.cc
index b3a41e0..37489a1 100644
--- a/ui/gl/init/gl_initializer_win.cc
+++ b/ui/gl/init/gl_initializer_win.cc
@@ -105,7 +105,7 @@
   SetGLGetProcAddressProc(get_proc_address);
   AddGLNativeLibrary(egl_library);
   AddGLNativeLibrary(gles_library);
-  SetGLImplementation(kGLImplementationEGLANGLE);
+  SetGLImplementation(kGLImplementationEGLGLES2);
 
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
@@ -191,7 +191,7 @@
       }
       break;
     case kGLImplementationSwiftShaderGL:
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       if (!GLSurfaceEGL::InitializeOneOff(GetDC(nullptr))) {
         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
         return false;
@@ -220,7 +220,7 @@
 
   switch (implementation) {
     case kGLImplementationSwiftShaderGL:
-    case kGLImplementationEGLANGLE:
+    case kGLImplementationEGLGLES2:
       return InitializeStaticEGLInternal(implementation);
     case kGLImplementationDesktopGL:
       return InitializeStaticWGLInternal();
diff --git a/ui/gl/init/gl_initializer_x11.cc b/ui/gl/init/gl_initializer_x11.cc
index 3fc37d1c..e3c481b 100644
--- a/ui/gl/init/gl_initializer_x11.cc
+++ b/ui/gl/init/gl_initializer_x11.cc
@@ -83,6 +83,8 @@
   base::FilePath glesv2_path(kGLESv2LibraryName);
   base::FilePath egl_path(kEGLLibraryName);
 
+  const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+
   if (implementation == kGLImplementationSwiftShaderGL) {
 #if BUILDFLAG(ENABLE_SWIFTSHADER)
     base::FilePath module_path;
@@ -95,7 +97,8 @@
 #else
     return false;
 #endif
-  } else if (implementation == kGLImplementationEGLANGLE) {
+  } else if (cmd->GetSwitchValueASCII(switches::kUseGL) ==
+             kGLImplementationANGLEName) {
     base::FilePath module_path;
     if (!base::PathService::Get(base::DIR_MODULE, &module_path))
       return false;
@@ -127,11 +130,7 @@
   SetGLGetProcAddressProc(get_proc_address);
   AddGLNativeLibrary(egl_library);
   AddGLNativeLibrary(gles_library);
-  if (implementation == kGLImplementationEGLANGLE) {
-    SetGLImplementation(kGLImplementationEGLANGLE);
-  } else {
-    SetGLImplementation(kGLImplementationEGLGLES2);
-  }
+  SetGLImplementation(kGLImplementationEGLGLES2);
 
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
@@ -151,7 +150,6 @@
       return true;
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       if (!GLSurfaceEGL::InitializeOneOff(gfx::GetXDisplay())) {
         LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
         return false;
@@ -179,7 +177,6 @@
       return InitializeStaticGLXInternal();
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLGLES2:
-    case kGLImplementationEGLANGLE:
       return InitializeStaticEGLInternal(implementation);
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index 6edc889..daa2f76 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -132,6 +132,7 @@
     "//ui/ozone/common/*",
     "//ui/ozone/public/interfaces",
     "//ui/ozone/platform/*",
+    "//ui/base/ime/chromeos/*",
   ]
 
   # Out of tree platforms can depend on this.
diff --git a/ui/ozone/demo/vulkan_renderer.cc b/ui/ozone/demo/vulkan_renderer.cc
index 2650398f..214f959 100644
--- a/ui/ozone/demo/vulkan_renderer.cc
+++ b/ui/ozone/demo/vulkan_renderer.cc
@@ -209,9 +209,9 @@
 
   DestroyFramebuffers();
 
-  vulkan_surface_->SetSize(size_);
+  vulkan_surface_->Reshape(size_, gfx::OVERLAY_TRANSFORM_NONE);
 
-  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface_->GetSwapChain();
+  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface_->swap_chain();
   const uint32_t num_images = vulkan_swap_chain->num_images();
   framebuffers_.resize(num_images);
 }
@@ -222,7 +222,7 @@
   VkClearValue clear_value = {
       /* .color = */ {/* .float32 = */ {.5f, 1.f - NextFraction(), .5f, 1.f}}};
 
-  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface_->GetSwapChain();
+  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface_->swap_chain();
   gpu::VulkanSwapChain::ScopedWrite scoped_write(vulkan_swap_chain);
   const uint32_t image = scoped_write.image_index();
   {
@@ -332,7 +332,7 @@
                                     VkRenderPass vk_render_pass,
                                     gpu::VulkanSurface* vulkan_surface,
                                     VkImage image) {
-  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface->GetSwapChain();
+  gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface->swap_chain();
   const VkDevice vk_device = vulkan_device_queue->GetVulkanDevice();
   VkImageViewCreateInfo vk_image_view_create_info = {
       /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
diff --git a/ui/ozone/platform/cast/BUILD.gn b/ui/ozone/platform/cast/BUILD.gn
index ade393a..9940dee 100644
--- a/ui/ozone/platform/cast/BUILD.gn
+++ b/ui/ozone/platform/cast/BUILD.gn
@@ -43,6 +43,7 @@
     "//chromecast:chromecast_buildflags",
     "//chromecast/base:base",
     "//chromecast/graphics:libcast_graphics_1.0",
+    "//ui/base/ime",
     "//ui/events/ozone:events_ozone",
     "//ui/events/ozone:events_ozone_evdev",
     "//ui/events/ozone:events_ozone_layout",
diff --git a/ui/ozone/platform/cast/ozone_platform_cast.cc b/ui/ozone/platform/cast/ozone_platform_cast.cc
index 5eca91a..fc04766 100644
--- a/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -14,6 +14,7 @@
 #include "chromecast/chromecast_buildflags.h"
 #include "chromecast/public/cast_egl_platform.h"
 #include "chromecast/public/cast_egl_platform_shlib.h"
+#include "ui/base/ime/input_method_minimal.h"
 #include "ui/display/types/native_display_delegate.h"
 #include "ui/events/ozone/device/device_manager.h"
 #include "ui/events/ozone/evdev/event_factory_evdev.h"
@@ -103,6 +104,11 @@
     // On Cast platform the display is initialized by low-level non-Ozone code.
     return nullptr;
   }
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+    return std::make_unique<InputMethodMinimal>(delegate);
+  }
+
   bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
                                      gfx::BufferUsage usage) const override {
     return format == gfx::BufferFormat::BGRA_8888 &&
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn
index 55e26c2..c195b2d 100644
--- a/ui/ozone/platform/drm/BUILD.gn
+++ b/ui/ozone/platform/drm/BUILD.gn
@@ -134,6 +134,7 @@
     "//third_party/libsync",
     "//third_party/minigbm",
     "//ui/base",
+    "//ui/base/ime",
     "//ui/display",
     "//ui/display/types",
     "//ui/display/util",
@@ -154,6 +155,10 @@
     "//ui/platform_window",
   ]
 
+  if (is_chromeos) {
+    deps += [ "//ui/base/ime/chromeos" ]
+  }
+
   if (enable_vulkan) {
     sources += [
       "gpu/vulkan_implementation_gbm.cc",
@@ -195,6 +200,7 @@
     "//build/config/linux/libdrm",
     "//skia",
     "//testing/gtest",
+    "//ui/base/ime",
     "//ui/gfx",
     "//ui/ozone:platform",
     "//ui/ozone/common",
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index d762d447..5b40dfc 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -57,6 +57,12 @@
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
+#else
+#include "ui/base/ime/input_method_minimal.h"
+#endif
+
 namespace ui {
 
 namespace {
@@ -155,6 +161,14 @@
       override {
     return std::make_unique<DrmNativeDisplayDelegate>(display_manager_.get());
   }
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+#if defined(OS_CHROMEOS)
+    return std::make_unique<InputMethodChromeOS>(delegate);
+#else
+    return std::make_unique<InputMethodMinimal>(delegate);
+#endif
+  }
 
   bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
                                      gfx::BufferUsage usage) const override {
diff --git a/ui/ozone/platform/headless/BUILD.gn b/ui/ozone/platform/headless/BUILD.gn
index 64198049..635cc8f 100644
--- a/ui/ozone/platform/headless/BUILD.gn
+++ b/ui/ozone/platform/headless/BUILD.gn
@@ -26,6 +26,7 @@
     "//base",
     "//skia",
     "//ui/base",
+    "//ui/base/ime",
     "//ui/events",
     "//ui/events/ozone:events_ozone_layout",
     "//ui/events/platform",
@@ -35,4 +36,8 @@
     "//ui/platform_window",
     "//ui/platform_window/stub",
   ]
+
+  if (is_fuchsia) {
+    deps += [ "//ui/base/ime/fuchsia" ]
+  }
 }
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 1bf25803..7a2a1c2 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -9,7 +9,9 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "build/build_config.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/ime/input_method_minimal.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/events/platform/platform_event_source.h"
@@ -26,6 +28,10 @@
 #include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
+#if defined(OS_FUCHSIA)
+#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
+#endif
+
 namespace ui {
 
 namespace {
@@ -78,6 +84,14 @@
       override {
     return std::make_unique<HeadlessNativeDisplayDelegate>();
   }
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+#if defined(OS_FUCHSIA)
+    return std::make_unique<InputMethodFuchsia>(delegate);
+#else
+    return std::make_unique<InputMethodMinimal>(delegate);
+#endif
+  }
 
   void InitializeUI(const InitParams& params) override {
     window_manager_ = std::make_unique<HeadlessWindowManager>();
diff --git a/ui/ozone/platform/magma/BUILD.gn b/ui/ozone/platform/magma/BUILD.gn
index 6afd9d7..e4873406 100644
--- a/ui/ozone/platform/magma/BUILD.gn
+++ b/ui/ozone/platform/magma/BUILD.gn
@@ -24,6 +24,7 @@
     "//base",
     "//skia",
     "//ui/base",
+    "//ui/base/ime",
     "//ui/display/fake",
     "//ui/events",
     "//ui/events/ozone:events_ozone_layout",
diff --git a/ui/ozone/platform/magma/ozone_platform_magma.cc b/ui/ozone/platform/magma/ozone_platform_magma.cc
index e5b661b..12367d5 100644
--- a/ui/ozone/platform/magma/ozone_platform_magma.cc
+++ b/ui/ozone/platform/magma/ozone_platform_magma.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/ime/input_method_minimal.h"
 #include "ui/display/fake/fake_display_delegate.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
@@ -77,6 +78,10 @@
       override {
     return std::make_unique<display::FakeDisplayDelegate>();
   }
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+    return std::make_unique<InputMethodMinimal>(delegate);
+  }
 
   void InitializeUI(const InitParams& params) override {
     window_manager_ = std::make_unique<MagmaWindowManager>();
diff --git a/ui/ozone/platform/scenic/BUILD.gn b/ui/ozone/platform/scenic/BUILD.gn
index 59d1d8ae..39e7355 100644
--- a/ui/ozone/platform/scenic/BUILD.gn
+++ b/ui/ozone/platform/scenic/BUILD.gn
@@ -53,6 +53,7 @@
     "//third_party/fuchsia-sdk/sdk:ui_gfx",
     "//third_party/fuchsia-sdk/sdk:ui_scenic",
     "//ui/base",
+    "//ui/base/ime/fuchsia",
     "//ui/display/fake",
     "//ui/events:dom_keycode_converter",
     "//ui/events/ozone:events_ozone_layout",
diff --git a/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
index 237f106..45e47d3 100644
--- a/ui/ozone/platform/scenic/ozone_platform_scenic.cc
+++ b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -13,6 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop_current.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/ime/fuchsia/input_method_fuchsia.h"
 #include "ui/display/fake/fake_display_delegate.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
@@ -112,6 +113,11 @@
     return window_manager_->CreateScreen();
   }
 
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+    return std::make_unique<InputMethodFuchsia>(delegate);
+  }
+
   void InitializeUI(const InitParams& params) override {
     if (!PlatformEventSource::GetInstance())
       platform_event_source_ = std::make_unique<ScenicPlatformEventSource>();
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 17bb667..0e442dd 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -13,6 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "ui/base/buildflags.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/ime/linux/input_method_auralinux.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
@@ -97,16 +98,6 @@
   std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
-    // Some unit tests may try to set custom input method context factory
-    // after InitializeUI. Thus instead of creating factory in InitializeUI
-    // it is set at this point if none exists
-    if (!LinuxInputMethodContextFactory::instance() &&
-        !input_method_context_factory_) {
-      auto* factory = new WaylandInputMethodContextFactory(connection_.get());
-      input_method_context_factory_.reset(factory);
-      LinuxInputMethodContextFactory::SetInstance(factory);
-    }
-
     auto window = std::make_unique<WaylandWindow>(delegate, connection_.get());
     if (!window->Initialize(std::move(properties)))
       return nullptr;
@@ -131,6 +122,21 @@
     return connection_->clipboard();
   }
 
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+    // Some unit tests may try to set custom input method context factory
+    // after InitializeUI. Thus instead of creating factory in InitializeUI
+    // it is set at this point if none exists
+    if (!LinuxInputMethodContextFactory::instance() &&
+        !input_method_context_factory_) {
+      auto* factory = new WaylandInputMethodContextFactory(connection_.get());
+      input_method_context_factory_.reset(factory);
+      LinuxInputMethodContextFactory::SetInstance(factory);
+    }
+
+    return std::make_unique<InputMethodAuraLinux>(delegate);
+  }
+
   bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
                                      gfx::BufferUsage usage) const override {
     // If there is no drm render node device available, native pixmaps are not
diff --git a/ui/ozone/platform/windows/ozone_platform_windows.cc b/ui/ozone/platform/windows/ozone_platform_windows.cc
index 5d7a8e746..702dcb9 100644
--- a/ui/ozone/platform/windows/ozone_platform_windows.cc
+++ b/ui/ozone/platform/windows/ozone_platform_windows.cc
@@ -76,6 +76,11 @@
       override {
     return std::make_unique<display::FakeDisplayDelegate>();
   }
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+    NOTREACHED();
+    return nullptr;
+  }
 
   void InitializeUI(const InitParams& params) override {
     window_manager_ = std::make_unique<WindowsWindowManager>();
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn
index 07ee634..42637c3 100644
--- a/ui/ozone/platform/x11/BUILD.gn
+++ b/ui/ozone/platform/x11/BUILD.gn
@@ -41,6 +41,7 @@
     "//gpu/vulkan:buildflags",
     "//skia",
     "//ui/base",
+    "//ui/base/ime",
     "//ui/base/x",
     "//ui/display/fake",
     "//ui/events",
@@ -59,6 +60,10 @@
     "//ui/platform_window/x11",
   ]
 
+  if (is_chromeos) {
+    deps += [ "//ui/base/ime/chromeos" ]
+  }
+
   if (enable_vulkan) {
     deps += [ "//gpu/vulkan/x" ]
   }
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 7aa963e0..e5f7197f 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -28,6 +28,12 @@
 #include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
+#if defined(OS_CHROMEOS)
+#include "ui/base/ime/chromeos/input_method_chromeos.h"
+#else
+#include "ui/base/ime/input_method_minimal.h"
+#endif
+
 namespace ui {
 
 namespace {
@@ -79,13 +85,25 @@
   }
 
   std::unique_ptr<PlatformScreen> CreateScreen() override {
-    return std::make_unique<X11ScreenOzone>();
+    DCHECK(window_manager_);
+    return std::make_unique<X11ScreenOzone>(window_manager_.get());
   }
 
   PlatformClipboard* GetPlatformClipboard() override {
     return clipboard_.get();
   }
 
+  std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) override {
+#if defined(OS_CHROMEOS)
+    return std::make_unique<InputMethodChromeOS>(delegate);
+#else
+    // TODO(spang): Fix InputMethodAuraLinux which requires another level
+    // of initization.
+    return std::make_unique<InputMethodMinimal>(delegate);
+#endif
+  }
+
   void InitializeUI(const InitParams& params) override {
     InitializeCommon(params);
     CreatePlatformEventSource();
diff --git a/ui/ozone/platform/x11/x11_screen_ozone.cc b/ui/ozone/platform/x11/x11_screen_ozone.cc
index 4523ab21..13cedfb 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone.cc
@@ -6,6 +6,7 @@
 
 #include "ui/base/x/x11_display_util.h"
 #include "ui/base/x/x11_util.h"
+#include "ui/display/display_finder.h"
 #include "ui/display/util/display_util.h"
 #include "ui/display/util/x11/edid_parser_x11.h"
 #include "ui/events/platform/platform_event_source.h"
@@ -13,6 +14,8 @@
 #include "ui/gfx/font_render_params.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/x/x11.h"
+#include "ui/ozone/platform/x11/x11_window_manager_ozone.h"
+#include "ui/ozone/platform/x11/x11_window_ozone.h"
 
 namespace ui {
 
@@ -36,11 +39,16 @@
 
 }  // namespace
 
-X11ScreenOzone::X11ScreenOzone()
-    : xdisplay_(gfx::GetXDisplay()),
+X11ScreenOzone::X11ScreenOzone(X11WindowManagerOzone* wm, bool fetch)
+    : window_manager_(wm),
+      xdisplay_(gfx::GetXDisplay()),
       x_root_window_(DefaultRootWindow(xdisplay_)),
       xrandr_version_(GetXrandrVersion(xdisplay_)) {
-  FetchDisplayList();
+  DCHECK(window_manager_);
+
+  // TODO(nickdiego): Factor this out from ctor
+  if (fetch)
+    FetchDisplayList();
 }
 
 X11ScreenOzone::~X11ScreenOzone() {
@@ -63,8 +71,18 @@
 
 display::Display X11ScreenOzone::GetDisplayForAcceleratedWidget(
     gfx::AcceleratedWidget widget) const {
-  // TODO(crbug.com/891175): Implement PlatformScreen for X11
-  NOTIMPLEMENTED_LOG_ONCE();
+  if (widget == gfx::kNullAcceleratedWidget)
+    return GetPrimaryDisplay();
+
+  X11WindowOzone* window = window_manager_->GetWindow(widget);
+  if (window) {
+    const gfx::Rect pixel_rect = window->GetBounds();
+    const display::Display* matching_display =
+        display::FindDisplayWithBiggestIntersection(
+            display_list_.displays(),
+            gfx::ConvertRectToDIP(GetDeviceScaleFactor(), pixel_rect));
+    return matching_display ? *matching_display : GetPrimaryDisplay();
+  }
   return GetPrimaryDisplay();
 }
 
@@ -120,6 +138,9 @@
   return ui::POST_DISPATCH_NONE;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// X11ScreenOzone, private:
+
 void X11ScreenOzone::AddDisplay(const display::Display& display,
                                 bool is_primary) {
   display_list_.AddDisplay(
diff --git a/ui/ozone/platform/x11/x11_screen_ozone.h b/ui/ozone/platform/x11/x11_screen_ozone.h
index 2abe458..586eb6e 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone.h
+++ b/ui/ozone/platform/x11/x11_screen_ozone.h
@@ -18,10 +18,12 @@
 
 namespace ui {
 
+class X11WindowManagerOzone;
+
 // A PlatformScreen implementation for X11.
 class X11ScreenOzone : public PlatformScreen, public PlatformEventDispatcher {
  public:
-  X11ScreenOzone();
+  explicit X11ScreenOzone(X11WindowManagerOzone* wm, bool fetch = true);
   ~X11ScreenOzone() override;
 
   // PlatformScreen:
@@ -44,11 +46,14 @@
   uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
 
  private:
+  friend class X11ScreenOzoneTest;
+
   void AddDisplay(const display::Display& display, bool is_primary);
   void RemoveDisplay(const display::Display& display);
   void FetchDisplayList();
   gfx::Point GetCursorLocation() const;
 
+  X11WindowManagerOzone* window_manager_;
   display::DisplayList display_list_;
 
   base::ObserverList<display::DisplayObserver> observers_;
diff --git a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
index 9e40bdb..0e25b1a7 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
@@ -6,19 +6,148 @@
 
 #include <memory>
 
+#include "base/test/scoped_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/display.h"
+#include "ui/events/platform/x11/x11_event_source_libevent.h"
+#include "ui/ozone/platform/x11/x11_window_manager_ozone.h"
+#include "ui/ozone/platform/x11/x11_window_ozone.h"
+#include "ui/ozone/test/mock_platform_window_delegate.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+using ::testing::_;
 
 namespace ui {
 
-// This test ensures that PlatformScreen fetches display.
-TEST(X11ScreenOzoneTest, FetchDisplay) {
-  constexpr uint32_t kMinNumberOfDisplays = 1;
-  X11ScreenOzone platform_screen;
+namespace {
 
-  // Ensure there is only one display, which is the primary one.
-  auto& all_displays = platform_screen.GetAllDisplays();
-  EXPECT_GE(all_displays.size(), kMinNumberOfDisplays);
+constexpr gfx::Rect kPrimaryDisplayBounds(0, 0, 800, 600);
+
+ACTION_P(StoreWidget, widget_ptr) {
+  if (widget_ptr)
+    *widget_ptr = arg0;
+}
+
+int64_t NextDisplayId() {
+  static int64_t next_id = 0;
+  return next_id++;
+}
+
+}  // namespace
+
+class X11ScreenOzoneTest : public testing::Test {
+ public:
+  X11ScreenOzoneTest()
+      : task_env_(std::make_unique<base::test::ScopedTaskEnvironment>(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI)) {}
+  ~X11ScreenOzoneTest() override = default;
+
+  void SetUp() override {
+    XDisplay* display = gfx::GetXDisplay();
+    event_source_ = std::make_unique<X11EventSourceLibevent>(display);
+    window_manager_ = std::make_unique<X11WindowManagerOzone>();
+    primary_display_ = std::make_unique<display::Display>(
+        NextDisplayId(), kPrimaryDisplayBounds);
+    screen_.reset(new X11ScreenOzone(window_manager_.get(), false));
+    screen_->AddDisplay(*primary_display_, true);
+  }
+
+ protected:
+  X11ScreenOzone* screen() const { return screen_.get(); }
+  const display::Display& primary_display() const { return *primary_display_; }
+
+  std::unique_ptr<display::Display> CreateDisplay(gfx::Rect bounds) const {
+    return std::make_unique<display::Display>(NextDisplayId(), bounds);
+  }
+
+  void AddDisplayForTest(const display::Display& display) {
+    screen_->AddDisplay(display, false);
+  }
+
+  void RemoveDisplayForTest(const display::Display& display) {
+    screen_->RemoveDisplay(display);
+  }
+
+  std::unique_ptr<X11WindowOzone> CreatePlatformWindow(
+      MockPlatformWindowDelegate* delegate,
+      const gfx::Rect& bounds,
+      gfx::AcceleratedWidget* widget = nullptr) {
+    EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_))
+        .WillOnce(StoreWidget(widget));
+    X11WindowManagerOzone* wm = window_manager_.get();
+    return std::make_unique<X11WindowOzone>(wm, delegate, bounds);
+  }
+
+ private:
+  std::unique_ptr<X11WindowManagerOzone> window_manager_;
+  std::unique_ptr<display::Display> primary_display_;
+  std::unique_ptr<X11ScreenOzone> screen_;
+  std::unique_ptr<X11EventSourceLibevent> event_source_;
+  std::unique_ptr<base::test::ScopedTaskEnvironment> task_env_;
+
+  DISALLOW_COPY_AND_ASSIGN(X11ScreenOzoneTest);
+};
+
+// This test case ensures that PlatformScreen correctly provides the display
+// list as they are added/removed.
+TEST_F(X11ScreenOzoneTest, AddRemoveListDisplays) {
+  // Initially only primary display is expected to be in place
+  EXPECT_EQ(1u, screen()->GetAllDisplays().size());
+
+  auto display_2 = CreateDisplay(gfx::Rect(800, 0, 1280, 720));
+  AddDisplayForTest(*display_2);
+  EXPECT_EQ(2u, screen()->GetAllDisplays().size());
+
+  auto display_3 = CreateDisplay(gfx::Rect(0, 720, 800, 600));
+  AddDisplayForTest(*display_3);
+  EXPECT_EQ(3u, screen()->GetAllDisplays().size());
+
+  RemoveDisplayForTest(*display_3);
+  EXPECT_EQ(2u, screen()->GetAllDisplays().size());
+  RemoveDisplayForTest(*display_2);
+  EXPECT_EQ(1u, screen()->GetAllDisplays().size());
+  RemoveDisplayForTest(primary_display());
+  EXPECT_EQ(0u, screen()->GetAllDisplays().size());
+}
+
+// This test case exercises GetDisplayForAcceleratedWidget when simple cases
+// for platform windows in a single-display setup.
+TEST_F(X11ScreenOzoneTest, GetDisplayForWidgetSingleDisplay) {
+  auto primary = primary_display();
+  MockPlatformWindowDelegate delegate;
+  gfx::AcceleratedWidget widget;
+  constexpr gfx::Rect bounds(100, 100, 400, 300);
+  auto window = CreatePlatformWindow(&delegate, bounds, &widget);
+  EXPECT_EQ(primary, screen()->GetDisplayForAcceleratedWidget(widget));
+  EXPECT_EQ(primary, screen()->GetDisplayForAcceleratedWidget(
+                         gfx::kNullAcceleratedWidget));
+
+  MockPlatformWindowDelegate delegate_1;
+  gfx::AcceleratedWidget widget_1;
+  constexpr gfx::Rect bounds_1(kPrimaryDisplayBounds.width() + 100,
+                               kPrimaryDisplayBounds.height() + 100, 200, 200);
+  auto window_1 = CreatePlatformWindow(&delegate_1, bounds_1, &widget_1);
+  EXPECT_EQ(primary, screen()->GetDisplayForAcceleratedWidget(widget_1));
+}
+
+// This test case exercises GetDisplayForAcceleratedWidget when simple cases
+// for platform windows in a 2 side-by-side displays setup.
+TEST_F(X11ScreenOzoneTest, GetDisplayForWidgetTwoDisplays) {
+  auto display_2 =
+      CreateDisplay(gfx::Rect(kPrimaryDisplayBounds.width(), 0, 1280, 720));
+  AddDisplayForTest(*display_2);
+
+  MockPlatformWindowDelegate delegate;
+  gfx::AcceleratedWidget widget;
+  constexpr gfx::Rect bounds(kPrimaryDisplayBounds.width() + 10, 100, 400, 300);
+  auto window = CreatePlatformWindow(&delegate, bounds, &widget);
+  EXPECT_EQ(*display_2, screen()->GetDisplayForAcceleratedWidget(widget));
+
+  EXPECT_CALL(delegate, OnBoundsChanged(_)).Times(1);
+  window->SetBounds(
+      gfx::Rect(kPrimaryDisplayBounds.width() - 250, 0, 400, 300));
+  EXPECT_EQ(primary_display(),
+            screen()->GetDisplayForAcceleratedWidget(widget));
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_window_manager_ozone.cc b/ui/ozone/platform/x11/x11_window_manager_ozone.cc
index 100bc2e..577fc4eb 100644
--- a/ui/ozone/platform/x11/x11_window_manager_ozone.cc
+++ b/ui/ozone/platform/x11/x11_window_manager_ozone.cc
@@ -30,4 +30,26 @@
   event_grabber_ = nullptr;
 }
 
+void X11WindowManagerOzone::AddWindow(X11WindowOzone* window) {
+  DCHECK(window);
+  DCHECK_NE(gfx::kNullAcceleratedWidget, window->widget());
+  DCHECK(!base::Contains(windows_, window->widget()));
+  windows_.emplace(window->widget(), window);
+}
+
+void X11WindowManagerOzone::RemoveWindow(X11WindowOzone* window) {
+  DCHECK(window);
+  DCHECK_NE(gfx::kNullAcceleratedWidget, window->widget());
+  auto it = windows_.find(window->widget());
+  DCHECK(it != windows_.end());
+  windows_.erase(it);
+}
+
+X11WindowOzone* X11WindowManagerOzone::GetWindow(
+    gfx::AcceleratedWidget widget) const {
+  DCHECK_NE(gfx::kNullAcceleratedWidget, widget);
+  auto it = windows_.find(widget);
+  return it != windows_.end() ? it->second : nullptr;
+}
+
 }  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_window_manager_ozone.h b/ui/ozone/platform/x11/x11_window_manager_ozone.h
index 81250ddf..05051a6 100644
--- a/ui/ozone/platform/x11/x11_window_manager_ozone.h
+++ b/ui/ozone/platform/x11/x11_window_manager_ozone.h
@@ -5,7 +5,9 @@
 #ifndef UI_OZONE_PLATFORM_X11_X11_WINDOW_MANAGER_OZONE_H_
 #define UI_OZONE_PLATFORM_X11_X11_WINDOW_MANAGER_OZONE_H_
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace ui {
 
@@ -27,9 +29,16 @@
   // Gets the current X11WindowOzone recipient of mouse events.
   X11WindowOzone* event_grabber() const { return event_grabber_; }
 
+  // Gets the window corresponding to the AcceleratedWidget |widget|.
+  void AddWindow(X11WindowOzone* window);
+  void RemoveWindow(X11WindowOzone* window);
+  X11WindowOzone* GetWindow(gfx::AcceleratedWidget widget) const;
+
  private:
   X11WindowOzone* event_grabber_;
 
+  base::flat_map<gfx::AcceleratedWidget, X11WindowOzone*> windows_;
+
   DISALLOW_COPY_AND_ASSIGN(X11WindowManagerOzone);
 };
 
diff --git a/ui/ozone/platform/x11/x11_window_ozone.cc b/ui/ozone/platform/x11/x11_window_ozone.cc
index 86e2c54..9a80b98 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone.cc
@@ -49,6 +49,8 @@
   if (xwindow_ == x11::None)
     return;
 
+  RemoveFromWindowManager();
+
   // Stop processing events.
   XID xwindow = xwindow_;
   XDisplay* xdisplay = xdisplay_;
@@ -66,6 +68,7 @@
   DCHECK_NE(xwindow, x11::None);
 
   SetXWindow(xwindow);
+  window_manager_->AddWindow(this);
 
   DCHECK(X11EventSourceLibevent::GetInstance());
   X11EventSourceLibevent::GetInstance()->AddXEventDispatcher(this);
@@ -338,6 +341,13 @@
   XDefineCursor(xdisplay_, xwindow_, cursor_ozone->xcursor());
 }
 
+void X11WindowOzone::RemoveFromWindowManager() {
+  DCHECK(window_manager_);
+  if (xwindow_ != x11::None) {
+    window_manager_->RemoveWindow(this);
+  }
+}
+
 // CheckCanDispatchNextPlatformEvent is called by X11EventSourceLibevent to
 // determine whether X11WindowOzone instance (XEventDispatcher implementation)
 // is able to process next translated event sent by it. So, it's done through
diff --git a/ui/ozone/platform/x11/x11_window_ozone.h b/ui/ozone/platform/x11/x11_window_ozone.h
index 02112b7..c859842 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.h
+++ b/ui/ozone/platform/x11/x11_window_ozone.h
@@ -31,6 +31,8 @@
                  const gfx::Rect& bounds);
   ~X11WindowOzone() override;
 
+  gfx::AcceleratedWidget widget() const { return widget_; }
+
   // Called by |window_manager_| once capture is set to another X11WindowOzone.
   void OnLostCapture();
 
@@ -63,6 +65,8 @@
   bool DispatchXEvent(XEvent* event) override;
 
  private:
+  void RemoveFromWindowManager();
+
   // PlatformEventDispatcher:
   bool CanDispatchEvent(const PlatformEvent& event) override;
   uint32_t DispatchEvent(const PlatformEvent& event) override;
diff --git a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
index 2484f518..ac3b5ac 100644
--- a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
@@ -5,6 +5,7 @@
 #include "ui/ozone/platform/x11/x11_window_ozone.h"
 
 #include <memory>
+#include <utility>
 
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
@@ -21,7 +22,6 @@
 
 namespace {
 
-using ::testing::Eq;
 using ::testing::_;
 
 constexpr int kPointerDeviceId = 1;
@@ -72,6 +72,10 @@
     event_source_->ProcessXEvent(event);
   }
 
+  X11WindowManagerOzone* window_manager() const {
+    return window_manager_.get();
+  }
+
  private:
   std::unique_ptr<base::test::ScopedTaskEnvironment> task_env_;
   std::unique_ptr<X11WindowManagerOzone> window_manager_;
@@ -149,4 +153,28 @@
   EXPECT_EQ(gfx::Point(-277, 215), event->AsLocatedEvent()->location());
 }
 
+// This test case ensures window_manager properly provides X11WindowOzone
+// instances as they are created/destroyed.
+TEST_F(X11WindowOzoneTest, GetWindowFromAcceleratedWigets) {
+  MockPlatformWindowDelegate delegate;
+  gfx::Rect bounds(0, 0, 100, 100);
+  gfx::AcceleratedWidget widget_1;
+  auto window_1 = CreatePlatformWindow(&delegate, bounds, &widget_1);
+  EXPECT_EQ(window_1.get(), window_manager()->GetWindow(widget_1));
+
+  gfx::AcceleratedWidget widget_2;
+  auto window_2 = CreatePlatformWindow(&delegate, bounds, &widget_2);
+  EXPECT_EQ(window_2.get(), window_manager()->GetWindow(widget_2));
+  EXPECT_EQ(window_1.get(), window_manager()->GetWindow(widget_1));
+
+  window_1->Close();
+  window_1.reset();
+  EXPECT_EQ(nullptr, window_manager()->GetWindow(widget_1));
+  EXPECT_EQ(window_2.get(), window_manager()->GetWindow(widget_2));
+
+  window_2.reset();
+  EXPECT_EQ(nullptr, window_manager()->GetWindow(widget_1));
+  EXPECT_EQ(nullptr, window_manager()->GetWindow(widget_2));
+}
+
 }  // namespace ui
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 67d1357..fc22f54 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -40,6 +40,11 @@
 class SystemInputInjector;
 class PlatformClipboard;
 
+namespace internal {
+class InputMethodDelegate;
+}  // namespace internal
+class InputMethod;
+
 struct PlatformWindowInitProperties;
 
 // Base class for Ozone platform implementations.
@@ -155,6 +160,8 @@
   CreateNativeDisplayDelegate() = 0;
   virtual std::unique_ptr<PlatformScreen> CreateScreen();
   virtual PlatformClipboard* GetPlatformClipboard();
+  virtual std::unique_ptr<InputMethod> CreateInputMethod(
+      internal::InputMethodDelegate* delegate) = 0;
 
   // Returns true if the specified buffer format is supported.
   virtual bool IsNativePixmapConfigSupported(gfx::BufferFormat format,