diff --git a/.gn b/.gn
index ff4d8e14..62d221a 100644
--- a/.gn
+++ b/.gn
@@ -215,7 +215,6 @@
   "//chrome/browser/tab_contents/*",
   "//chrome/browser/task_manager/*",
   "//chrome/browser/themes/*",
-  "//chrome/browser/thumbnails/*",
   "//chrome/browser/tracing/*",
   "//chrome/browser/translate/*",
   "//chrome/browser/ui/*",
diff --git a/DEPS b/DEPS
index 9b44a4e1..32979fa 100644
--- a/DEPS
+++ b/DEPS
@@ -133,11 +133,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '36f660818365bef3b62122b4469f2f2658b6a4b0',
+  'skia_revision': '3b7170b34551d49cf123537ff089a9b55f1bd7b2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'e1451a8b9471ee544df39b0d1621ee1d64c4113e',
+  'v8_revision': 'a4404f08610f8dde2b745329ac5813c4a6a84c70',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -149,11 +149,11 @@
   # 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': '4ef71eb81f5d2f313ee83b78ff5e6fc7d7c5a291',
+  'swiftshader_revision': '9b62c5ea2af36ae332392a8a1d48c4b818c3f114',
   # 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': '812b09bf58227da6122cc50a43d41fbfb9953c1c',
+  'pdfium_revision': 'b271c06e57ba997a2f109e5311f84af8c804da9a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -196,7 +196,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': '2afe880da0ce34181cbfbc2d95550aa6e589537a',
+  'catapult_revision': '1a088f27008b608cfd9363cc70fbac3f44568f0e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -760,7 +760,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '382116b42cac12e85fc79174a865eb39d71610c4',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5d5aed4520ccd3a427528736661b2420ff8e9df9',
       'condition': 'checkout_linux',
   },
 
@@ -1127,7 +1127,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '0e83ee6b9e88ea3282134c05fdcd56aa4e85d153',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'f702532c71518410b9e9c738bd88516b7e6863c4',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1298,7 +1298,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'cc3503248f1dc7edd3ab505b5194c69718d0f711',
+    Var('webrtc_git') + '/src.git' + '@' + 'd841ea6b586a81065f78d3eae7ab82c505cda1d8',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1339,7 +1339,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@611b8351677e0d62e2c625bda639006192b3b4ab',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@05e8371e668ab2e8ed8dfc4377ef3dfb111a1e4b',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 8d51efe..6c84dd9 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -45,6 +45,9 @@
       'filepath': 'third_party/android_deps/' \
                   '|tools/android/roll/android_deps/'
     },
+    'android_features': {
+      'filepath': 'chrome/android/features/'
+    },
     'android_infobars': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/infobar/'
     },
@@ -182,6 +185,7 @@
     },
     'autofill_assistant': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/|'\
+                  'chrome/android/features/autofill_assistant/|'\
                   'chrome/browser/android/autofill_assistant/|'\
                   'components/autofill_assistant/',
     },
@@ -1129,6 +1133,7 @@
     },
     'media_router': {
       'filepath': 'chrome/android/(java|junit)/src/org/chromium/chrome/browser/media/router/' \
+                  '|chrome/android/features/media_router/' \
                   '|chrome/browser/media/router/' \
                   '|chrome/browser/resources/media_router/' \
                   '|chrome/browser/ui/media_router/' \
@@ -1810,6 +1815,7 @@
                                 'wnwen+watch@chromium.org'],
     'android_crazy_linker': ['johnmaguire+watch@google.com'],
     'android_deps': ['wnwen+watch@chromium.org'],
+    'android_features': ['wnwen+watch@chromium.org'],
     'android_infobars': ['dfalcantara+watch@chromium.org'],
     'android_infra': ['agrieve+watch@chromium.org',
                       'estevenson+watch@chromium.org',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index a2b1e0a..6379ad9 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2808,6 +2808,7 @@
       "debug/elf_reader_unittest.cc",
       "files/dir_reader_posix_unittest.cc",
       "files/file_descriptor_watcher_posix_unittest.cc",
+      "fuchsia/file_utils_unittest.cc",
       "fuchsia/filtered_service_directory_unittest.cc",
       "fuchsia/service_directory_test_base.cc",
       "fuchsia/service_directory_test_base.h",
diff --git a/base/fuchsia/file_utils.cc b/base/fuchsia/file_utils.cc
index bb012b8..d5286b6a 100644
--- a/base/fuchsia/file_utils.cc
+++ b/base/fuchsia/file_utils.cc
@@ -4,9 +4,14 @@
 
 #include "base/fuchsia/file_utils.h"
 
+#include <fcntl.h>
 #include <lib/fdio/fd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
-#include "base/files/file.h"
+#include <utility>
+
 #include "base/fuchsia/fuchsia_logging.h"
 
 namespace base {
@@ -16,26 +21,24 @@
 const char kServiceDirectoryPath[] = "/svc";
 const char kPackageRootDirectoryPath[] = "/pkg";
 
-zx::handle GetHandleFromFile(File file) {
-  zx::handle handle;
-  zx_status_t status =
-      fdio_fd_transfer(file.GetPlatformFile(), handle.reset_and_get_address());
-  if (status != ZX_ERR_UNAVAILABLE)
-    ignore_result(file.TakePlatformFile());
-  if (status == ZX_OK)
-    return handle;
-  ZX_DLOG(ERROR, status) << "fdio_fd_transfer";
-  return zx::handle();
-}
+fidl::InterfaceHandle<::fuchsia::io::Directory> OpenDirectory(
+    const base::FilePath& path) {
+  int fd = open(path.value().c_str(), O_DIRECTORY | O_RDONLY);
+  if (fd < 0) {
+    DPLOG(ERROR) << "Failed to open " << path;
+    return fidl::InterfaceHandle<::fuchsia::io::Directory>();
+  }
 
-base::File GetFileFromHandle(zx::handle handle) {
-  base::ScopedFD fd;
-  zx_status_t status =
-      fdio_fd_create(handle.release(), base::ScopedFD::Receiver(fd).get());
-  if (status == ZX_OK)
-    return base::File(fd.release());
-  ZX_LOG(WARNING, status) << "fdio_fd_create";
-  return base::File();
+  zx::channel channel;
+  zx_status_t status = fdio_fd_transfer(fd, channel.reset_and_get_address());
+  if (status != ZX_ERR_UNAVAILABLE)
+    PCHECK(close(fd));
+  if (status != ZX_OK) {
+    ZX_DLOG(ERROR, status) << "fdio_fd_transfer";
+    return fidl::InterfaceHandle<::fuchsia::io::Directory>();
+  }
+
+  return fidl::InterfaceHandle<::fuchsia::io::Directory>(std::move(channel));
 }
 
 }  // namespace fuchsia
diff --git a/base/fuchsia/file_utils.h b/base/fuchsia/file_utils.h
index 1b249929..b1df755 100644
--- a/base/fuchsia/file_utils.h
+++ b/base/fuchsia/file_utils.h
@@ -5,14 +5,12 @@
 #ifndef BASE_FUCHSIA_FILE_UTILS_H_
 #define BASE_FUCHSIA_FILE_UTILS_H_
 
-#include <lib/zx/handle.h>
+#include <fuchsia/io/cpp/fidl.h>
 
 #include "base/base_export.h"
+#include "base/files/file_path.h"
 
 namespace base {
-
-class File;
-
 namespace fuchsia {
 
 // Persisted data directory, i.e. /data . Returned as DIR_APP_DATA from
@@ -25,14 +23,10 @@
 // Package root directory, i.e. /pkg .
 BASE_EXPORT extern const char kPackageRootDirectoryPath[];
 
-// Gets a Zircon handle from a file or directory |path| in the process'
-// namespace.
-BASE_EXPORT zx::handle GetHandleFromFile(base::File file);
-
-// Makes a File object from a Zircon handle.
-// Returns an empty File if |handle| is invalid or not a valid PA_FDIO_REMOTE
-// descriptor.
-BASE_EXPORT base::File GetFileFromHandle(zx::handle handle);
+// Returns fuchsia.io.Directory for the specified |path| or null InterfaceHandle
+// if the path doesn't exist or it's not a directory.
+BASE_EXPORT fidl::InterfaceHandle<::fuchsia::io::Directory> OpenDirectory(
+    const base::FilePath& path);
 
 }  // namespace fuchsia
 }  // namespace base
diff --git a/base/fuchsia/file_utils_unittest.cc b/base/fuchsia/file_utils_unittest.cc
new file mode 100644
index 0000000..11bb1a2
--- /dev/null
+++ b/base/fuchsia/file_utils_unittest.cc
@@ -0,0 +1,44 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/fuchsia/file_utils.h"
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace fuchsia {
+
+class OpenDirectoryTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    EXPECT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(
+        base::FilePath(kPersistedDataDirectoryPath)));
+  }
+
+  ScopedTempDir temp_dir;
+};
+
+TEST_F(OpenDirectoryTest, Open) {
+  auto dir = OpenDirectory(temp_dir.GetPath());
+  ASSERT_TRUE(dir);
+}
+
+// OpenDirectory() should fail when opening a directory that doesn't exist.
+TEST_F(OpenDirectoryTest, OpenNonExistent) {
+  auto dir = OpenDirectory(temp_dir.GetPath().AppendASCII("non_existent"));
+  ASSERT_FALSE(dir);
+}
+
+// OpenDirectory() should open only directories.
+TEST_F(OpenDirectoryTest, OpenFile) {
+  auto file_path = temp_dir.GetPath().AppendASCII("test_file");
+  ASSERT_TRUE(WriteFile(file_path, "foo", 3));
+  auto dir = OpenDirectory(file_path);
+  ASSERT_FALSE(dir);
+}
+
+}  // namespace fuchsia
+}  // namespace base
\ No newline at end of file
diff --git a/base/fuchsia/service_directory_client.cc b/base/fuchsia/service_directory_client.cc
index 92167482..48379a7b 100644
--- a/base/fuchsia/service_directory_client.cc
+++ b/base/fuchsia/service_directory_client.cc
@@ -17,19 +17,11 @@
 
 namespace {
 
-fidl::InterfaceHandle<::fuchsia::io::Directory> ConnectToServiceRoot() {
-  fidl::InterfaceHandle<::fuchsia::io::Directory> directory;
-  zx_status_t result = fdio_service_connect(
-      kServiceDirectoryPath, directory.NewRequest().TakeChannel().release());
-  ZX_CHECK(result == ZX_OK, result) << "Failed to open /svc";
-  return directory;
-}
-
 // Singleton container for the process-global ServiceDirectoryClient instance.
 std::unique_ptr<ServiceDirectoryClient>* ProcessServiceDirectoryClient() {
   static base::NoDestructor<std::unique_ptr<ServiceDirectoryClient>>
-      service_directory_client_ptr(
-          std::make_unique<ServiceDirectoryClient>(ConnectToServiceRoot()));
+      service_directory_client_ptr(std::make_unique<ServiceDirectoryClient>(
+          OpenDirectory(base::FilePath(kServiceDirectoryPath))));
   return service_directory_client_ptr.get();
 }
 
diff --git a/base/process/launch_fuchsia.cc b/base/process/launch_fuchsia.cc
index d7c3696f..24008ad 100644
--- a/base/process/launch_fuchsia.cc
+++ b/base/process/launch_fuchsia.cc
@@ -181,14 +181,15 @@
     }
 
     for (const auto& path_to_clone : options.paths_to_clone) {
-      zx::handle handle = fuchsia::GetHandleFromFile(
-          base::File(base::FilePath(path_to_clone),
-                     base::File::FLAG_OPEN | base::File::FLAG_READ));
-      if (!handle) {
+      fidl::InterfaceHandle<::fuchsia::io::Directory> directory =
+          base::fuchsia::OpenDirectory(path_to_clone);
+      if (!directory) {
         LOG(WARNING) << "Could not open handle for path: " << path_to_clone;
         return base::Process();
       }
 
+      zx::handle handle = directory.TakeChannel();
+
       spawn_actions.push_back(FdioSpawnActionAddNamespaceEntry(
           path_to_clone.value().c_str(), handle.get()));
       transferred_handles.push_back(std::move(handle));
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index c694196..b08292b 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -264,13 +264,14 @@
 
   // Attach the tempdir to "data", but also try to duplicate the existing "data"
   // directory.
-  options.paths_to_clone.push_back(base::FilePath("/data"));
+  options.paths_to_clone.push_back(
+      base::FilePath(base::fuchsia::kPersistedDataDirectoryPath));
   options.paths_to_clone.push_back(base::FilePath("/tmp"));
   options.paths_to_transfer.push_back(
-      {FilePath("/data"),
-       fuchsia::GetHandleFromFile(
-           base::File(base::FilePath(tmpdir_with_staged.GetPath()),
-                      base::File::FLAG_OPEN | base::File::FLAG_READ))
+      {FilePath(base::fuchsia::kPersistedDataDirectoryPath),
+       base::fuchsia::OpenDirectory(
+           base::FilePath(tmpdir_with_staged.GetPath()))
+           .TakeChannel()
            .release()});
 
   // Verify from that "/data/staged" exists from the child process' perspective.
@@ -307,14 +308,14 @@
   staged_file.Close();
 
   // Mount the tempdir to "/foo".
-  zx::handle tmp_handle = fuchsia::GetHandleFromFile(
-      base::File(base::FilePath(new_tmpdir.GetPath()),
-                 base::File::FLAG_OPEN | base::File::FLAG_READ));
-  ASSERT_TRUE(tmp_handle.is_valid());
+  zx::channel tmp_channel =
+      base::fuchsia::OpenDirectory(new_tmpdir.GetPath()).TakeChannel();
+
+  ASSERT_TRUE(tmp_channel.is_valid());
   LaunchOptions options;
   options.paths_to_clone.push_back(base::FilePath("/tmp"));
   options.paths_to_transfer.push_back(
-      {base::FilePath("/foo"), tmp_handle.release()});
+      {base::FilePath("/foo"), tmp_channel.release()});
   options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
 
   // Verify from that "/foo/staged" exists from the child process' perspective.
diff --git a/base/profiler/native_stack_sampler_mac.cc b/base/profiler/native_stack_sampler_mac.cc
index 7522ce7..ad92f40 100644
--- a/base/profiler/native_stack_sampler_mac.cc
+++ b/base/profiler/native_stack_sampler_mac.cc
@@ -258,10 +258,10 @@
  private:
   // Walks the stack represented by |thread_state|, calling back to the
   // provided lambda for each frame.
-  template <typename StackFrameCallback, typename ContinueUnwindPredicate>
+  template <typename StackFrameCallback>
   void WalkStack(const x86_thread_state64_t& thread_state,
-                 const StackFrameCallback& callback,
-                 const ContinueUnwindPredicate& continue_unwind);
+                 uintptr_t stack_top,
+                 const StackFrameCallback& callback);
 
   // Weak reference: Mach port for thread being profiled.
   mach_port_t thread_port_;
@@ -360,42 +360,23 @@
     return;
   }
 
-  const auto continue_predicate = [this,
-                                   new_stack_top](unw_cursor_t* unwind_cursor) {
-    // Don't continue if we're in sigtramp. Unwinding this from another thread
-    // is very fragile. It's a complex DWARF unwind that needs to restore the
-    // entire thread context which was saved by the kernel when the interrupt
-    // occurred.
-    unw_word_t rip;
-    unw_get_reg(unwind_cursor, UNW_REG_IP, &rip);
-    if (rip >= sigtramp_start_ && rip < sigtramp_end_)
-      return false;
-
-    // Don't continue if rbp appears to be invalid (due to a previous bad
-    // unwind).
-    return HasValidRbp(unwind_cursor, new_stack_top);
-  };
-
   // Reserve enough memory for most stacks, to avoid repeated allocations.
   // Approximately 99.9% of recorded stacks are 128 frames or fewer.
   std::vector<Frame> frames;
   frames.reserve(128);
 
-  WalkStack(
-      thread_state,
-      [&frames](uintptr_t frame_ip, const ModuleCache::Module* module) {
-        frames.emplace_back(frame_ip, module);
-      },
-      continue_predicate);
+  WalkStack(thread_state, new_stack_top,
+            [&frames](uintptr_t frame_ip, const ModuleCache::Module* module) {
+              frames.emplace_back(frame_ip, module);
+            });
 
   profile_builder->OnSampleCompleted(frames);
 }
 
-template <typename StackFrameCallback, typename ContinueUnwindPredicate>
-void NativeStackSamplerMac::WalkStack(
-    const x86_thread_state64_t& thread_state,
-    const StackFrameCallback& callback,
-    const ContinueUnwindPredicate& continue_unwind) {
+template <typename StackFrameCallback>
+void NativeStackSamplerMac::WalkStack(const x86_thread_state64_t& thread_state,
+                                      uintptr_t stack_top,
+                                      const StackFrameCallback& callback) {
   // There isn't an official way to create a unw_context other than to create it
   // from the current state of the current thread's stack. Since we're walking a
   // different thread's stack we must forge a context. The unw_context is just a
@@ -433,7 +414,17 @@
 
     callback(static_cast<uintptr_t>(instruction_pointer), module);
 
-    if (!continue_unwind(&unwind_cursor))
+    // Don't continue if we're in sigtramp. Unwinding this from another thread
+    // is very fragile. It's a complex DWARF unwind that needs to restore the
+    // entire thread context which was saved by the kernel when the interrupt
+    // occurred.
+    if (instruction_pointer >= sigtramp_start_ &&
+        instruction_pointer < sigtramp_end_)
+      return;
+
+    // Don't continue if rbp appears to be invalid (due to a previous bad
+    // unwind).
+    if (!HasValidRbp(&unwind_cursor, stack_top))
       return;
 
     step_result = unw_step(&unwind_cursor);
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc
index cbb6dc7..27b872e7 100644
--- a/base/task/sequence_manager/sequence_manager_impl.cc
+++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -553,12 +553,16 @@
     main_thread_only().task_was_run_on_quiescence_monitored_queue = true;
 
 #if !defined(OS_NACL)
-  debug::SetCrashKeyString(
-      main_thread_only().file_name_crash_key,
-      executing_task->pending_task.posted_from.file_name());
-  debug::SetCrashKeyString(
-      main_thread_only().function_name_crash_key,
-      executing_task->pending_task.posted_from.function_name());
+  // SetCrashKeyString is a no-op even if the crash key is null, but we still
+  // have construct the StringPiece that is passed in.
+  if (main_thread_only().file_name_crash_key) {
+    debug::SetCrashKeyString(
+        main_thread_only().file_name_crash_key,
+        executing_task->pending_task.posted_from.file_name());
+    debug::SetCrashKeyString(
+        main_thread_only().function_name_crash_key,
+        executing_task->pending_task.posted_from.function_name());
+  }
 #endif  // OS_NACL
 
   bool record_task_timing = ShouldRecordTaskTiming(executing_task->task_queue);
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index a041c55..ccecde3 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -367,12 +367,8 @@
 
   // Bind the new test subdirectory to /data in the child process' namespace.
   new_options.paths_to_transfer.push_back(
-      {kDataPath, base::fuchsia::GetHandleFromFile(
-                      base::File(nested_data_path,
-                                 base::File::FLAG_OPEN | base::File::FLAG_READ |
-                                     base::File::FLAG_DELETE_ON_CLOSE))
-                      .release()});
-
+      {kDataPath,
+       base::fuchsia::OpenDirectory(nested_data_path).TakeChannel().release()});
 #endif  // defined(OS_FUCHSIA)
 
 #if defined(OS_LINUX)
@@ -452,9 +448,8 @@
     zx_status_t status = job_handle.kill();
     ZX_CHECK(status == ZX_OK, status);
 
-    // The child process' data dir should have been deleted automatically,
-    // thanks to the DELETE_ON_CLOSE flag.
-    DCHECK(!base::DirectoryExists(nested_data_path));
+    // Cleanup the data directory.
+    CHECK(DeleteFile(nested_data_path, true));
 #elif defined(OS_POSIX)
     if (exit_code != 0) {
       // On POSIX, in case the test does not exit cleanly, either due to a crash
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py
index a641daf8..4668e2e 100755
--- a/build/android/apk_operations.py
+++ b/build/android/apk_operations.py
@@ -152,7 +152,8 @@
 
       if not fake_modules:
         # Push empty temp_path to clear folder on device and update the cache.
-        device.PushChangedFiles([(temp_path, MODULES_SRC_DIRECTORY_PATH)])
+        device.PushChangedFiles([(temp_path, MODULES_SRC_DIRECTORY_PATH)],
+                                delete_device_stale=True)
         return
 
       # Device-spec JSON is needed, so create that first.
@@ -174,6 +175,7 @@
       bundletool.RunBundleTool(extract_apks_cmd_args)
 
       # Push fake modules, with renames.
+      fake_module_apks = set()
       for fake_module in fake_modules:
         found_master = False
 
@@ -184,8 +186,6 @@
           local_path = os.path.join(temp_path, filename)
 
           if not match:
-            # File doesn't match - remove from directory.
-            os.remove(local_path)
             continue
 
           module_suffix = match.group(1)
@@ -199,8 +199,15 @@
             remote = os.path.join(temp_path, '%s.apk' % fake_module)
 
           os.rename(local_path, remote)
+          fake_module_apks.add(os.path.basename(remote))
 
-      device.PushChangedFiles([(temp_path, MODULES_SRC_DIRECTORY_PATH)])
+      # Files that weren't renamed should not be pushed, remove from temp_path.
+      for filename in os.listdir(temp_path):
+        if filename not in fake_module_apks:
+          os.remove(os.path.join(temp_path, filename))
+
+      device.PushChangedFiles([(temp_path, MODULES_SRC_DIRECTORY_PATH)],
+                              delete_device_stale=True)
 
     finally:
       shutil.rmtree(temp_path, ignore_errors=True)
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 4d6ba29..6a6b8f8 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -272,8 +272,15 @@
   }
 }
 
-# Only //build/config/BUILDCONFIG.gn should reference this.
 group("common_deps") {
+  visibility = [
+    ":executable_deps",
+    ":loadable_module_deps",
+    ":shared_library_deps",
+  ]
+
+  # WARNING: This group is a dependency of **every executable and shared
+  # library**.  Please be careful adding new dependencies here.
   public_deps = []
 
   if (using_sanitizer) {
@@ -301,6 +308,7 @@
   }
 }
 
+# Only the executable template in BUILDCONFIG.gn should reference this.
 group("executable_deps") {
   public_deps = [
     ":common_deps",
@@ -310,12 +318,14 @@
   }
 }
 
+# Only the loadable_module template in BUILDCONFIG.gn should reference this.
 group("loadable_module_deps") {
   public_deps = [
     ":common_deps",
   ]
 }
 
+# Only the shared_library template in BUILDCONFIG.gn should reference this.
 group("shared_library_deps") {
   public_deps = [
     ":common_deps",
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn
index b6af43e..1654038 100644
--- a/buildtools/third_party/libc++/BUILD.gn
+++ b/buildtools/third_party/libc++/BUILD.gn
@@ -10,8 +10,8 @@
 config("config") {
   cflags = [ "-fstrict-aliasing" ]
   if (is_win) {
-    # libc++ wants to redefine the macros WIN32_LEAN_AND_MEAN and _CRT_RAND_S in its
-    # implementation.
+    # libc++ wants to redefine the macros WIN32_LEAN_AND_MEAN and _CRT_RAND_S in
+    # its implementation.
     cflags += [ "-Wno-macro-redefined" ]
   } else {
     cflags += [ "-fPIC" ]
@@ -24,6 +24,19 @@
   _libcxx_target_type = "source_set"
 }
 target(_libcxx_target_type, "libc++") {
+  # Most things that need to depend on libc++ should do so via the implicit
+  # 'common_deps' dependency below.  Some targets that package libc++.so may
+  # need to explicitly depend on libc++.
+  visibility = [
+    "//build/config:common_deps",
+    "//third_party/catapult/devil:devil",
+  ]
+  if (is_linux) {
+    # This target packages libc++.so, so must have an explicit dependency on
+    # libc++.
+    visibility +=
+        [ "//remoting/host/linux:remoting_me2me_host_copy_user_session" ]
+  }
   if (libcxx_is_shared) {
     no_default_deps = true
   }
diff --git a/buildtools/third_party/libc++abi/BUILD.gn b/buildtools/third_party/libc++abi/BUILD.gn
index 759327c..8949236 100644
--- a/buildtools/third_party/libc++abi/BUILD.gn
+++ b/buildtools/third_party/libc++abi/BUILD.gn
@@ -5,20 +5,19 @@
 import("//build/config/c++/c++.gni")
 
 source_set("libc++abi") {
-  visibility = [
-    "//buildtools/third_party/libc++",
-    "//build/config:executable_deps",
-    "//build/config:loadable_module_deps",
-    "//build/config:shared_library_deps",
-  ]
-  deps = []
+  if (export_libcxxabi_from_executables) {
+    visibility = [ "//build/config:executable_deps" ]
+  } else {
+    visibility = [ "//buildtools/third_party/libc++" ]
+  }
 
   # Fuchsia builds don't link against any libraries that provide stack
   # unwinding symbols, unlike Linux does with glibc.  Build and link against
   # libunwind manually to get this functionality.
-  # TODO(thomasanderson): Move this to exe_and_shlib_deps.
   if (is_fuchsia) {
-    deps += [ "//buildtools/third_party/libunwind" ]
+    deps = [
+      "//buildtools/third_party/libunwind",
+    ]
   }
 
   sources = [
diff --git a/buildtools/third_party/libunwind/BUILD.gn b/buildtools/third_party/libunwind/BUILD.gn
index 31bc075..3f671c8 100644
--- a/buildtools/third_party/libunwind/BUILD.gn
+++ b/buildtools/third_party/libunwind/BUILD.gn
@@ -15,11 +15,12 @@
 }
 
 source_set("libunwind") {
-  visibility = [
-    "//buildtools/third_party/libc++abi",
-    "//components/tracing",
-  ]
-
+  visibility = []
+  if (is_fuchsia) {
+    visibility += [ "//buildtools/third_party/libc++abi" ]
+  } else if (is_android) {
+    visibility += [ "//components/tracing" ]
+  }
   if (!is_component_build) {
     defines = [ "_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS" ]
   }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3fa111c..0cc38505 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2392,6 +2392,7 @@
     "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java",
     "java/src/org/chromium/chrome/browser/suggestions/SuggestionsEventReporterBridge.java",
     "java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java",
+    "java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java",
     "java/src/org/chromium/chrome/browser/tab/Tab.java",
     "java/src/org/chromium/chrome/browser/tab/TabFavicon.java",
     "java/src/org/chromium/chrome/browser/tab/TabState.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
index 45fe213..7c0a453 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
@@ -92,7 +92,6 @@
 
         // setup toolbar property model
         setupToolbarClickHandlers();
-        updateBottomSheetTitleAndMargin();
     }
 
     /**
@@ -141,6 +140,7 @@
 
     private void updateBottomSheetTitleAndMargin() {
         Tab currentTab = mTabModelSelector.getCurrentTab();
+        if (currentTab == null) return;
         int tabsCount = mTabModelSelector.getTabModelFilterProvider()
                                 .getCurrentTabModelFilter()
                                 .getRelatedTabList(currentTab.getId())
@@ -167,9 +167,16 @@
     private OnClickListener getAddButtonClickListener() {
         return view -> {
             Tab currentTab = mTabModelSelector.getCurrentTab();
+            List<Tab> relatedTabs = mTabModelSelector.getTabModelFilterProvider()
+                                            .getCurrentTabModelFilter()
+                                            .getRelatedTabList(currentTab.getId());
+
+            assert relatedTabs.size() > 0;
+
+            Tab parentTabToAttach = relatedTabs.get(relatedTabs.size() - 1);
             mTabCreatorManager.getTabCreator(currentTab.isIncognito())
-                    .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL), TabLaunchType.FROM_LINK,
-                            currentTab);
+                    .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL),
+                            TabLaunchType.FROM_CHROME_UI, parentTabToAttach);
         };
     }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 9613412..eaeda45 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -83,6 +83,12 @@
                 if (type == TabLaunchType.FROM_CHROME_UI) return;
                 resetTabStripWithRelatedTabsForId(tab.getId());
             }
+
+            @Override
+            public void restoreCompleted() {
+                Tab currentTab = mTabModelSelector.getCurrentTab();
+                mResetHandler.resetStripWithListOfTabs(getRelatedTabsForId(currentTab.getId()));
+            }
         };
         mOverviewModeObserver = new EmptyOverviewModeObserver() {
             @Override
@@ -116,9 +122,16 @@
         });
         mToolbarPropertyModel.set(TabStripToolbarViewProperties.ADD_CLICK_LISTENER, view -> {
             Tab currentTab = mTabModelSelector.getCurrentTab();
+            List<Tab> relatedTabs = mTabModelSelector.getTabModelFilterProvider()
+                                            .getCurrentTabModelFilter()
+                                            .getRelatedTabList(currentTab.getId());
+
+            assert relatedTabs.size() > 0;
+
+            Tab parentTabToAttach = relatedTabs.get(relatedTabs.size() - 1);
             mTabCreatorManager.getTabCreator(currentTab.isIncognito())
-                    .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL), TabLaunchType.FROM_LINK,
-                            currentTab);
+                    .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL),
+                            TabLaunchType.FROM_CHROME_UI, parentTabToAttach);
         });
     }
 
diff --git a/chrome/android/java/res/xml/developer_preferences.xml b/chrome/android/java/res/xml/developer_preferences.xml
index 22e77f3..3e24e11 100644
--- a/chrome/android/java/res/xml/developer_preferences.xml
+++ b/chrome/android/java/res/xml/developer_preferences.xml
@@ -3,9 +3,15 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:orderingFromXml="true">
     <Preference
         android:fragment="org.chromium.chrome.browser.preferences.developer.TracingPreferences"
         android:key="tracing"
         android:title="Tracing"/>
+    <org.chromium.chrome.browser.preferences.TextMessagePreference
+        android:key="beta_stable_hint"
+        android:title="Enable Developer options on Beta/Stable channels by tapping the Chrome version in &quot;Settings > About Chrome&quot; multiple times."
+        android:enabled="false"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
 </PreferenceScreen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
index b25c175..aa04dfe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsService.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.browseractions;
 
 import android.app.Activity;
-import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
@@ -25,10 +24,13 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.notifications.ChromeNotification;
 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
 import org.chromium.chrome.browser.notifications.NotificationConstants;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
+import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
@@ -229,22 +231,28 @@
     }
 
     private void sendBrowserActionsNotification(boolean isUpdate, int tabId) {
-        Notification notification = createNotificationBuilder(isUpdate, tabId).build();
+        ChromeNotification notification =
+                createNotificationBuilder(isUpdate, tabId).buildChromeNotification();
 
-        AppHooks.get().startForeground(this, NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS,
-                notification, 0 /* foregroundServiceType */);
+        AppHooks.get().startForeground(this, notification.getMetadata().id,
+                notification.getNotification(), 0 /* foregroundServiceType */);
 
         if (!isUpdate) {
             NotificationUmaTracker.getInstance().onNotificationShown(
-                    NotificationUmaTracker.SystemNotificationType.BROWSER_ACTIONS, notification);
+                    NotificationUmaTracker.SystemNotificationType.BROWSER_ACTIONS,
+                    notification.getNotification());
         }
     }
 
     private ChromeNotificationBuilder createNotificationBuilder(boolean isUpdate, int tabId) {
+        NotificationMetadata metadata = new NotificationMetadata(
+                NotificationUmaTracker.SystemNotificationType.BROWSER_ACTIONS,
+                null /* notificationTag */, NotificationConstants.NOTIFICATION_ID_BROWSER_ACTIONS);
         ChromeNotificationBuilder builder =
                 NotificationBuilderFactory
-                        .createChromeNotificationBuilder(
-                                true /* preferCompat */, ChannelDefinitions.ChannelId.BROWSER)
+                        .createChromeNotificationBuilder(true /* preferCompat */,
+                                ChannelDefinitions.ChannelId.BROWSER,
+                                null /* remoteAppPackageName */, metadata)
                         .setSmallIcon(R.drawable.infobar_chrome)
                         .setLocalOnly(true)
                         .setAutoCancel(true)
@@ -252,7 +260,7 @@
         sTitleResId = getNotificationTitleId(isUpdate);
         builder.setContentTitle(this.getString(sTitleResId));
         sNotificationIntent = buildNotificationIntent(isUpdate, tabId);
-        PendingIntent notifyPendingIntent = PendingIntent.getActivity(
+        PendingIntentProvider notifyPendingIntent = PendingIntentProvider.getActivity(
                 this, 0, sNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
         builder.setContentIntent(notifyPendingIntent);
         return builder;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
index 9ad0175c9..678ef0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.fullscreen.ComposedBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate;
-import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabContextMenuItemDelegate;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
@@ -207,7 +206,6 @@
     private final MultiWindowUtils mMultiWindowUtils;
 
     private ExternalNavigationDelegateImpl mNavigationDelegate;
-    private ExternalNavigationHandler mNavigationHandler;
 
     /**
      * @param shouldHideBrowserControls Whether or not the browser controls may auto-hide.
@@ -270,15 +268,14 @@
     }
 
     @Override
-    public InterceptNavigationDelegateImpl createInterceptNavigationDelegate(Tab tab) {
+    public ExternalNavigationHandler createExternalNavigationHandler(Tab tab) {
         if (mIsOpenedByChrome) {
             mNavigationDelegate = new ExternalNavigationDelegateImpl(tab);
         } else {
             mNavigationDelegate = new CustomTabNavigationDelegate(tab, tab.getAppAssociatedWith(),
                     mExternalAuthUtils);
         }
-        mNavigationHandler = new ExternalNavigationHandler(mNavigationDelegate);
-        return new InterceptNavigationDelegateImpl(mNavigationHandler, tab);
+        return new ExternalNavigationHandler(mNavigationDelegate);
     }
 
     @Override
@@ -293,14 +290,6 @@
     }
 
     /**
-     * @return The {@link ExternalNavigationHandler} in this tab. For test purpose only.
-     */
-    @VisibleForTesting
-    ExternalNavigationHandler getExternalNavigationHandler() {
-        return mNavigationHandler;
-    }
-
-    /**
      * @return The {@link CustomTabNavigationDelegate} in this tab. For test purpose only.
      */
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
index 491188f..cdb9f4495 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
@@ -78,7 +78,9 @@
     @IntDef({ActionType.UNKNOWN, ActionType.DOWNLOAD_PAUSE, ActionType.DOWNLOAD_RESUME,
             ActionType.DOWNLOAD_CANCEL, ActionType.DOWNLOAD_PAGE_PAUSE,
             ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL,
-            ActionType.CONTENT_SUGGESTION_SETTINGS})
+            ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE,
+            ActionType.WEB_APP_ACTION_OPEN_IN_CHROME,
+            ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActionType {
         int UNKNOWN = -1;
@@ -96,8 +98,14 @@
         int DOWNLOAD_PAGE_CANCEL = 5;
         // Setting button on content suggestion notification.
         int CONTENT_SUGGESTION_SETTINGS = 6;
+        // Share button on web app action notification.
+        int WEB_APP_ACTION_SHARE = 7;
+        // Open in Chrome button on web app action notification.
+        int WEB_APP_ACTION_OPEN_IN_CHROME = 8;
+        // Setting button in offline content suggestion notification.
+        int OFFLINE_CONTENT_SUGGESTION_SETTINGS = 9;
 
-        int NUM_ENTRIES = 7;
+        int NUM_ENTRIES = 10;
     }
 
     private static final String LAST_SHOWN_NOTIFICATION_TYPE_KEY =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
index 0e396c8..903e1c9f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
@@ -25,9 +25,14 @@
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
+import org.chromium.chrome.browser.notifications.ChromeNotification;
 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxy;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
+import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
@@ -295,7 +300,7 @@
 
         clickIntent.setPackage(context.getPackageName());
 
-        PendingIntent pendingClickIntent = PendingIntent.getBroadcast(
+        PendingIntentProvider pendingClickIntent = PendingIntentProvider.getBroadcast(
                 context, (int) offlineId /* requestCode */, clickIntent, 0 /* flags */);
 
         // Intent for swiping away.
@@ -305,10 +310,19 @@
         deleteIntent.setPackage(context.getPackageName());
 
         // Create the notification.
+        // Use the offline ID for a unique notification ID. Offline ID is a random
+        // 64-bit integer. Truncating to 32 bits isn't ideal, but chances of collision
+        // is still very low, and users should have few of these notifications
+        // anyway.
+        int notificationId = (int) offlineId;
+        NotificationMetadata metadata = new NotificationMetadata(
+                NotificationUmaTracker.SystemNotificationType.OFFLINE_PAGES,
+                COMPLETE_NOTIFICATION_TAG, notificationId);
         ChromeNotificationBuilder builder =
                 NotificationBuilderFactory
-                        .createChromeNotificationBuilder(
-                                true /* preferCompat */, ChannelDefinitions.ChannelId.DOWNLOADS)
+                        .createChromeNotificationBuilder(true /* preferCompat */,
+                                ChannelDefinitions.ChannelId.DOWNLOADS,
+                                null /* remoteAppPackageName */, metadata)
                         .setAutoCancel(true)
                         .setContentIntent(pendingClickIntent)
                         .setContentTitle(pageTitle)
@@ -317,20 +331,15 @@
                         .setGroup(COMPLETE_NOTIFICATION_TAG)
                         .setPriorityBeforeO(NotificationCompat.PRIORITY_LOW)
                         .setSmallIcon(R.drawable.ic_chrome)
-                        .setDeleteIntent(PendingIntent.getBroadcast(
+                        .setDeleteIntent(PendingIntentProvider.getBroadcast(
                                 context, 0 /* requestCode */, deleteIntent, 0 /* flags */));
 
-        Notification notification = builder.build();
-        // Use the offline ID for a unique notification ID. Offline ID is a random
-        // 64-bit integer. Truncating to 32 bits isn't ideal, but chances of collision
-        // is still very low, and users should have few of these notifications
-        // anyway.
-        int notificationId = (int) offlineId;
-        NotificationManager manager =
-                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        manager.notify(COMPLETE_NOTIFICATION_TAG, notificationId, notification);
+        ChromeNotification notification = builder.buildChromeNotification();
+        NotificationManagerProxy manager = new NotificationManagerProxyImpl(context);
+        manager.notify(notification);
         NotificationUmaTracker.getInstance().onNotificationShown(
-                NotificationUmaTracker.SystemNotificationType.OFFLINE_PAGES, notification);
+                NotificationUmaTracker.SystemNotificationType.OFFLINE_PAGES,
+                notification.getNotification());
         reportCompleteNotificationAction(NotificationAction.SHOWN);
         if (mTestHooks != null) {
             mTestHooks.completeNotificationShown(clickIntent, deleteIntent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
index 94cdf23..e599321 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
@@ -4,9 +4,6 @@
 
 package org.chromium.chrome.browser.offlinepages.prefetch;
 
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -19,9 +16,14 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.DownloadUtils;
+import org.chromium.chrome.browser.notifications.ChromeNotification;
 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxy;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
+import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.preferences.NotificationsPreferences;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
@@ -103,18 +105,23 @@
 
         // TODO(dewittj): Use unique notification IDs, allowing multiple to appear in the
         // notification center.
+        // TODO(xingliu): Unify the notification logic in here and AutoFetchNotifier.
         int notificationId = 1;
-        PendingIntent clickIntent = getPendingBroadcastFor(context, ClickReceiver.class);
+        PendingIntentProvider clickIntent = getPendingBroadcastFor(context, ClickReceiver.class);
         String title =
                 String.format(context.getString(R.string.offline_pages_prefetch_notification_title),
                         context.getString(R.string.app_name));
         String text = String.format(
                 context.getString(R.string.offline_pages_prefetch_notification_text), origin);
 
+        NotificationMetadata metadata = new NotificationMetadata(
+                NotificationUmaTracker.SystemNotificationType.OFFLINE_CONTENT_SUGGESTION,
+                NOTIFICATION_TAG, notificationId);
         ChromeNotificationBuilder builder =
                 NotificationBuilderFactory
                         .createChromeNotificationBuilder(true /* preferCompat */,
-                                ChannelDefinitions.ChannelId.CONTENT_SUGGESTIONS)
+                                ChannelDefinitions.ChannelId.CONTENT_SUGGESTIONS,
+                                null /* remoteAppPackageName */, metadata)
                         .setAutoCancel(true)
                         .setContentIntent(clickIntent)
                         .setContentTitle(title)
@@ -123,16 +130,17 @@
                         .setPriorityBeforeO(NotificationCompat.PRIORITY_LOW)
                         .setSmallIcon(R.drawable.ic_chrome);
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
-            PendingIntent settingsIntent = getPendingBroadcastFor(context, SettingsReceiver.class);
+            PendingIntentProvider settingsIntent =
+                    getPendingBroadcastFor(context, SettingsReceiver.class);
             builder.addAction(R.drawable.settings_cog, context.getString(R.string.preferences),
-                    settingsIntent);
+                    settingsIntent,
+                    NotificationUmaTracker.ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS);
         }
 
-        Notification notification = builder.build();
+        ChromeNotification notification = builder.buildChromeNotification();
 
-        NotificationManager manager =
-                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        manager.notify(NOTIFICATION_TAG, notificationId, notification);
+        NotificationManagerProxy manager = new NotificationManagerProxyImpl(context);
+        manager.notify(notification);
 
         // Increment ignored notification counter.  This will be reset on click.
         PrefetchPrefs.setIgnoredNotificationCounter(
@@ -142,11 +150,11 @@
         recordNotificationAction(NOTIFICATION_ACTION_SHOWN);
         NotificationUmaTracker.getInstance().onNotificationShown(
                 NotificationUmaTracker.SystemNotificationType.OFFLINE_CONTENT_SUGGESTION,
-                notification);
+                notification.getNotification());
     }
 
-    private static PendingIntent getPendingBroadcastFor(Context context, Class clazz) {
-        return PendingIntent.getBroadcast(
+    private static PendingIntentProvider getPendingBroadcastFor(Context context, Class clazz) {
+        return PendingIntentProvider.getBroadcast(
                 context, 0 /* requestCode */, new Intent(context, clazz), 0 /* flags */);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/developer/DeveloperPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/developer/DeveloperPreferences.java
index b215ddb3..de4ccc4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/developer/DeveloperPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/developer/DeveloperPreferences.java
@@ -9,6 +9,7 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.components.version_info.Channel;
 import org.chromium.components.version_info.VersionConstants;
@@ -17,6 +18,7 @@
  * Settings fragment containing preferences aimed at Chrome and web developers.
  */
 public class DeveloperPreferences extends PreferenceFragment {
+    private static final String UI_PREF_BETA_STABLE_HINT = "beta_stable_hint";
     private static final String PREF_DEVELOPER_ENABLED = "developer";
 
     // Non-translated strings:
@@ -41,5 +43,9 @@
         super.onCreate(savedInstanceState);
         getActivity().setTitle(MSG_DEVELOPER_OPTIONS_TITLE);
         PreferenceUtils.addPreferencesFromResource(this, R.xml.developer_preferences);
+
+        if (ChromeVersionInfo.isBetaBuild() || ChromeVersionInfo.isStableBuild()) {
+            getPreferenceScreen().removePreference(findPreference(UI_PREF_BETA_STABLE_HINT));
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
index 404da581a..518e0de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
@@ -4,13 +4,13 @@
 
 package org.chromium.chrome.browser.tab;
 
+import org.chromium.base.UserData;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationParams;
@@ -18,6 +18,7 @@
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.components.navigation_interception.NavigationParams;
 import org.chromium.content_public.browser.NavigationController;
+import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.ConsoleMessageLevel;
@@ -30,12 +31,17 @@
  * hence can cause UAF error. It should be done in an asynchronous fashion to avoid it.
  * See https://crbug.com/732260.
  */
-public class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
+public class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate, UserData {
+    private static final Class<InterceptNavigationDelegateImpl> USER_DATA_KEY =
+            InterceptNavigationDelegateImpl.class;
+
     private final Tab mTab;
-    private final ExternalNavigationHandler mExternalNavHandler;
     private final AuthenticatorNavigationInterceptor mAuthenticatorHelper;
     private @OverrideUrlLoadingResult int mLastOverrideUrlLoadingResult =
             OverrideUrlLoadingResult.NO_OVERRIDE;
+    private final TabObserver mDelegateObserver;
+    private WebContents mWebContents;
+    private ExternalNavigationHandler mExternalNavHandler;
 
     /**
      * Whether forward history should be cleared after navigation is committed.
@@ -43,29 +49,72 @@
     private boolean mClearAllForwardHistoryRequired;
     private boolean mShouldClearRedirectHistoryForTabClobbering;
 
+    public static void createForTab(Tab tab) {
+        assert get(tab) == null;
+        tab.getUserDataHost().setUserData(USER_DATA_KEY, new InterceptNavigationDelegateImpl(tab));
+    }
+
+    public static InterceptNavigationDelegateImpl get(Tab tab) {
+        return tab.getUserDataHost().getUserData(USER_DATA_KEY);
+    }
+
     /**
      * Default constructor of {@link InterceptNavigationDelegateImpl}.
      */
-    public InterceptNavigationDelegateImpl(Tab tab) {
-        this(new ExternalNavigationHandler(tab), tab);
-    }
-
-    /**
-     * Constructs a new instance of {@link InterceptNavigationDelegateImpl} with the given
-     * {@link ExternalNavigationDelegate}.
-     */
-    public InterceptNavigationDelegateImpl(ExternalNavigationDelegateImpl delegate, Tab tab) {
-        this(new ExternalNavigationHandler(delegate), tab);
-    }
-
-    /**
-     * Constructs a new instance of {@link InterceptNavigationDelegateImpl} with the given
-     * {@link ExternalNavigationHandler}.
-     */
-    public InterceptNavigationDelegateImpl(ExternalNavigationHandler externalNavHandler, Tab tab) {
+    @VisibleForTesting
+    InterceptNavigationDelegateImpl(Tab tab) {
         mTab = tab;
-        mExternalNavHandler = externalNavHandler;
         mAuthenticatorHelper = AppHooks.get().createAuthenticatorNavigationInterceptor(mTab);
+        mDelegateObserver = new EmptyTabObserver() {
+            @Override
+            public void onContentChanged(Tab tab) {
+                associateWithWebContents(tab.getWebContents());
+            }
+
+            @Override
+            public void onActivityAttachmentChanged(Tab tab, boolean attached) {
+                if (attached) {
+                    setExternalNavigationHandler(
+                            tab.getDelegateFactory().createExternalNavigationHandler(tab));
+                }
+            }
+
+            @Override
+            public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) {
+                if (!navigation.hasCommitted() || !navigation.isInMainFrame()) return;
+                maybeUpdateNavigationHistory();
+            }
+
+            @Override
+            public void onDestroyed(Tab tab) {
+                associateWithWebContents(null);
+            }
+        };
+        mTab.addObserver(mDelegateObserver);
+        associateWithWebContents(mTab.getWebContents());
+    }
+
+    @Override
+    public void destroy() {
+        mTab.removeObserver(mDelegateObserver);
+    }
+
+    @VisibleForTesting
+    void setExternalNavigationHandler(ExternalNavigationHandler handler) {
+        mExternalNavHandler = handler;
+    }
+
+    private void associateWithWebContents(WebContents webContents) {
+        if (mWebContents == webContents) return;
+        mWebContents = webContents;
+        if (mWebContents == null) return;
+
+        // Lazily initialize the external navigation handler.
+        if (mExternalNavHandler == null) {
+            setExternalNavigationHandler(
+                    mTab.getDelegateFactory().createExternalNavigationHandler(mTab));
+        }
+        nativeAssociateWithWebContents(this, mWebContents);
     }
 
     public boolean shouldIgnoreNewTab(String url, boolean incognito) {
@@ -288,4 +337,14 @@
         mTab.getWebContents().addMessageToDevToolsConsole(
                 ConsoleMessageLevel.WARNING, mTab.getApplicationContext().getString(resId, url));
     }
+
+    @VisibleForTesting
+    static void initDelegateForTesting(Tab tab, InterceptNavigationDelegateImpl delegate) {
+        delegate.associateWithWebContents(tab.getWebContents());
+        tab.getUserDataHost().setUserData(USER_DATA_KEY, delegate);
+    }
+
+    private static native void nativeAssociateWithWebContents(
+            InterceptNavigationDelegateImpl nativeInterceptNavigationDelegateImpl,
+            WebContents webContents);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 1695c2d9..41d7b40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -75,7 +75,6 @@
 import org.chromium.components.content_capture.ContentCaptureReceiverManager;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.embedder_support.view.ContentView;
-import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.content_public.browser.ChildProcessImportance;
 import org.chromium.content_public.browser.GestureListenerManager;
@@ -259,13 +258,6 @@
     private String mTitle;
 
     /**
-     * The mInterceptNavigationDelegate will be consulted for top-level frame navigations. This
-     * allows presenting the intent picker to the user so that a native Android application can be
-     * used if available.
-     */
-    private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
-
-    /**
      * Whether didCommitProvisionalLoadForFrame() hasn't yet been called for the current native page
      * (page A). To decrease latency, we show native pages in both loadUrl() and
      * didCommitProvisionalLoadForFrame(). However, we mustn't show a new native page (page B) in
@@ -370,6 +362,7 @@
         }
 
         TabFullscreenHandler.createForTab(this);
+        InterceptNavigationDelegateImpl.createForTab(this);
 
         if (incognito) {
             CipherFactory.getInstance().triggerKeyGeneration();
@@ -1127,13 +1120,9 @@
             nativeUpdateDelegates(mNativeTabAndroid, mWebContentsDelegate,
                     new TabContextMenuPopulator(
                             mDelegateFactory.createContextMenuPopulator(this), this));
-            setInterceptNavigationDelegate(
-                    mDelegateFactory.createInterceptNavigationDelegate(this));
         }
 
-        for (TabObserver observer : mObservers) {
-            observer.onActivityAttachmentChanged(this, true);
-        }
+        for (TabObserver observer : mObservers) observer.onActivityAttachmentChanged(this, true);
     }
 
     /**
@@ -1359,8 +1348,6 @@
                 }
             });
 
-            setInterceptNavigationDelegate(mDelegateFactory.createInterceptNavigationDelegate(
-                    this));
             if (ContentCaptureFeatures.isEnabled()) {
                 // The created object is held by native side.
                 ContentCaptureReceiverManager.create(getWebContents());
@@ -1410,10 +1397,6 @@
         if (!maybeShowNativePage(url, isReload)) {
             showRenderedPage();
         }
-
-        if (getInterceptNavigationDelegate() != null) {
-            getInterceptNavigationDelegate().maybeUpdateNavigationHistory();
-        }
     }
 
     /**
@@ -2181,23 +2164,6 @@
         if (view != null) view.requestFocus();
     }
 
-    /**
-     * See {@link #mInterceptNavigationDelegate}.
-     */
-    @VisibleForTesting
-    public InterceptNavigationDelegateImpl getInterceptNavigationDelegate() {
-        return mInterceptNavigationDelegate;
-    }
-
-    /**
-     * See {@link #mInterceptNavigationDelegate}.
-     */
-    @VisibleForTesting
-    void setInterceptNavigationDelegate(InterceptNavigationDelegateImpl delegate) {
-        mInterceptNavigationDelegate = delegate;
-        nativeSetInterceptNavigationDelegate(mNativeTabAndroid, delegate);
-    }
-
     @VisibleForTesting
     public boolean hasPrerenderedUrl(String url) {
         return nativeHasPrerenderedUrl(mNativeTabAndroid, url);
@@ -2313,8 +2279,6 @@
             long nativeTabAndroid, int constraints, int current, boolean animate);
     private native void nativeLoadOriginalImage(long nativeTabAndroid);
     private native long nativeGetBookmarkId(long nativeTabAndroid, boolean onlyEditable);
-    private native void nativeSetInterceptNavigationDelegate(long nativeTabAndroid,
-            InterceptNavigationDelegate delegate);
     private native void nativeAttachToTabContentManager(long nativeTabAndroid,
             TabContentManager tabContentManager);
     private native void nativeClearThumbnailPlaceholder(long nativeTabAndroid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
index 53b10e6f..f6d576284 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
@@ -6,6 +6,7 @@
 
 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
 import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator;
+import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler;
 import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 
@@ -23,12 +24,14 @@
     }
 
     /**
-     * Creates the {@link InterceptNavigationDelegate} the tab will be initialized with.
+     * Creates the {@link ExternalNavigationHandler} the tab will use for its
+     * {@link InterceptNavigationDelegate}.
      * @param tab The associated {@link Tab}.
-     * @return The {@link InterceptNavigationDelegate} to be used for this tab.
+     * @return The {@link ExternalNavigationHandler} to be used for this tab.
      */
-    public InterceptNavigationDelegateImpl createInterceptNavigationDelegate(Tab tab) {
-        return new InterceptNavigationDelegateImpl(tab);
+
+    public ExternalNavigationHandler createExternalNavigationHandler(Tab tab) {
+        return new ExternalNavigationHandler(tab);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
index 25b4b8f..d04ff0704 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -771,7 +771,7 @@
 
         // If shouldIgnoreNewTab returns true, the intent is handled by another
         // activity. As a result, don't launch a new tab to open the URL.
-        InterceptNavigationDelegateImpl delegate = parent.getInterceptNavigationDelegate();
+        InterceptNavigationDelegateImpl delegate = InterceptNavigationDelegateImpl.get(parent);
         if (delegate != null && delegate.shouldIgnoreNewTab(url, incognito)) return;
 
         LoadUrlParams loadUrlParams = new LoadUrlParams(url);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderController.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderController.java
index 1aaf279..8dfec2e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderController.java
@@ -63,8 +63,15 @@
             int currentIndex = TabModelUtils.getTabIndexById(currentModel, currentId);
 
             if (willOpenInForeground(type, newTab.isIncognito())) {
-                // If the tab was opened in the foreground, insert it adjacent to
-                // the tab that opened that link.
+                // If the tab was opened in the foreground, insert it adjacent to its parent tab if
+                // that exists and that tab is not the current selected tab, else insert the tab
+                // adjacent to the current tab that opened that link.
+                Tab parentTab = TabModelUtils.getTabById(currentModel, newTab.getParentId());
+                if (parentTab != null && currentTab != parentTab) {
+                    int parentTabIndex =
+                            TabModelUtils.getTabIndexById(currentModel, parentTab.getId());
+                    return parentTabIndex + 1;
+                }
                 return currentIndex + 1;
             } else {
                 // If the tab was opened in the background, position at the end of
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
index 0ebcbc48..1c79da4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
@@ -33,17 +33,21 @@
      * group.
      */
     private class TabGroup {
+        private final static int INVALID_GROUP_ID = -1;
         private final Set<Integer> mTabIds;
         private int mLastShownTabId;
+        private int mGroupId;
 
-        TabGroup() {
+        TabGroup(int groupId) {
             mTabIds = new LinkedHashSet<>();
             mLastShownTabId = Tab.INVALID_TAB_ID;
+            mGroupId = groupId;
         }
 
         void addTab(int tabId) {
             mTabIds.add(tabId);
             if (mLastShownTabId == Tab.INVALID_TAB_ID) setLastShownTabId(tabId);
+            if (size() > 1) reorderGroup(mGroupId);
         }
 
         void removeTab(int tabId) {
@@ -56,7 +60,8 @@
         }
 
         void moveToEndInGroup(int tabId) {
-            if (mTabIds.contains(tabId)) mTabIds.remove(tabId);
+            if (!mTabIds.contains(tabId)) return;
+            mTabIds.remove(tabId);
             mTabIds.add(tabId);
         }
 
@@ -129,7 +134,7 @@
         if (mGroupIdToGroupMap.containsKey(groupId)) {
             mGroupIdToGroupMap.get(groupId).addTab(tab.getId());
         } else {
-            TabGroup tabGroup = new TabGroup();
+            TabGroup tabGroup = new TabGroup(tab.getRootId());
             tabGroup.addTab(tab.getId());
             mGroupIdToGroupMap.put(groupId, tabGroup);
             mGroupIdToGroupIndexMap.put(groupId, mGroupIdToGroupIndexMap.size());
@@ -173,22 +178,31 @@
 
     @Override
     protected void reorder() {
-        mGroupIdToGroupIndexMap.clear();
+        reorderGroup(TabGroup.INVALID_GROUP_ID);
+
+        TabModel tabModel = getTabModel();
+        selectTab(tabModel.getTabAt(tabModel.index()));
+
+        assert mGroupIdToGroupIndexMap.size() == mGroupIdToGroupMap.size();
+    }
+
+    private void reorderGroup(int groupId) {
+        boolean reorderAllGroups = groupId == TabGroup.INVALID_GROUP_ID;
+        if (reorderAllGroups) {
+            mGroupIdToGroupIndexMap.clear();
+        }
 
         TabModel tabModel = getTabModel();
         for (int i = 0; i < tabModel.getCount(); i++) {
             Tab tab = tabModel.getTabAt(i);
-            int groupId = tab.getRootId();
-            mGroupIdToGroupMap.get(groupId).moveToEndInGroup(tab.getId());
-
-            if (!mGroupIdToGroupIndexMap.containsKey(groupId)) {
-                mGroupIdToGroupIndexMap.put(groupId, mGroupIdToGroupIndexMap.size());
+            if (reorderAllGroups) {
+                groupId = tab.getRootId();
+                if (!mGroupIdToGroupIndexMap.containsKey(groupId)) {
+                    mGroupIdToGroupIndexMap.put(groupId, mGroupIdToGroupIndexMap.size());
+                }
             }
+            mGroupIdToGroupMap.get(groupId).moveToEndInGroup(tab.getId());
         }
-
-        selectTab(tabModel.getTabAt(tabModel.index()));
-
-        assert mGroupIdToGroupIndexMap.size() == mGroupIdToGroupMap.size();
     }
 
     // TabList implementation.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
index 08a8d695..2203864 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationManager.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.webapps;
 
-import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -17,9 +16,14 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.notifications.ChromeNotification;
 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
 import org.chromium.chrome.browser.notifications.NotificationConstants;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxy;
+import org.chromium.chrome.browser.notifications.NotificationManagerProxyImpl;
+import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
+import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.IntentUtils;
@@ -55,28 +59,34 @@
         }
 
         Context appContext = ContextUtils.getApplicationContext();
-        Notification notification = createNotification(appContext, tab, webappInfo);
-        NotificationManager nm =
-                (NotificationManager) appContext.getSystemService(Context.NOTIFICATION_SERVICE);
-        nm.notify(NotificationConstants.NOTIFICATION_ID_WEBAPP_ACTIONS, notification);
+        ChromeNotification notification = createNotification(appContext, tab, webappInfo);
+        NotificationManagerProxy nm = new NotificationManagerProxyImpl(appContext);
+        nm.notify(notification);
 
         NotificationUmaTracker.getInstance().onNotificationShown(
-                NotificationUmaTracker.SystemNotificationType.WEBAPP_ACTIONS, notification);
+                NotificationUmaTracker.SystemNotificationType.WEBAPP_ACTIONS,
+                notification.getNotification());
     }
 
-    private static Notification createNotification(
+    private static ChromeNotification createNotification(
             Context appContext, Tab tab, WebappInfo webappInfo) {
         // The pending intents target an activity (instead of a service or a broadcast receiver) so
         // that the notification tray closes when a user taps the one of the notification action
         // links.
-        PendingIntent focusIntent = createPendingIntentWithAction(appContext, tab, ACTION_FOCUS);
-        PendingIntent openInChromeIntent =
+        PendingIntentProvider focusIntent =
+                createPendingIntentWithAction(appContext, tab, ACTION_FOCUS);
+        PendingIntentProvider openInChromeIntent =
                 createPendingIntentWithAction(appContext, tab, ACTION_OPEN_IN_CHROME);
-        PendingIntent shareIntent = createPendingIntentWithAction(appContext, tab, ACTION_SHARE);
+        PendingIntentProvider shareIntent =
+                createPendingIntentWithAction(appContext, tab, ACTION_SHARE);
 
+        NotificationMetadata metadata = new NotificationMetadata(
+                NotificationUmaTracker.SystemNotificationType.WEBAPP_ACTIONS,
+                null /* notificationTag */, NotificationConstants.NOTIFICATION_ID_WEBAPP_ACTIONS);
         return NotificationBuilderFactory
-                .createChromeNotificationBuilder(
-                        true /* prefer compat */, ChannelDefinitions.ChannelId.WEBAPP_ACTIONS)
+                .createChromeNotificationBuilder(true /* prefer compat */,
+                        ChannelDefinitions.ChannelId.WEBAPP_ACTIONS,
+                        null /* remoteAppPackageName */, metadata)
                 .setSmallIcon(R.drawable.ic_chrome)
                 .setContentTitle(webappInfo.shortName())
                 .setContentText(appContext.getString(R.string.webapp_tap_to_copy_url))
@@ -86,21 +96,23 @@
                 .setPriorityBeforeO(NotificationCompat.PRIORITY_MIN)
                 .setContentIntent(focusIntent)
                 .addAction(R.drawable.ic_share_white_24dp,
-                        appContext.getResources().getString(R.string.share), shareIntent)
+                        appContext.getResources().getString(R.string.share), shareIntent,
+                        NotificationUmaTracker.ActionType.WEB_APP_ACTION_SHARE)
                 .addAction(R.drawable.ic_exit_to_app_white_24dp,
                         appContext.getResources().getString(R.string.menu_open_in_chrome),
-                        openInChromeIntent)
-                .build();
+                        openInChromeIntent,
+                        NotificationUmaTracker.ActionType.WEB_APP_ACTION_OPEN_IN_CHROME)
+                .buildChromeNotification();
     }
 
     /** Creates an intent which targets {@link WebappLauncherActivity} with the passed-in action. */
-    private static PendingIntent createPendingIntentWithAction(
+    private static PendingIntentProvider createPendingIntentWithAction(
             Context context, Tab tab, String action) {
         Intent intent = new Intent(action);
         intent.setClass(context, WebappLauncherActivity.class);
         intent.putExtra(IntentHandler.EXTRA_TAB_ID, tab.getId());
         IntentHandler.addTrustedIntentExtras(intent);
-        return PendingIntent.getActivity(context, 0, intent,
+        return PendingIntentProvider.getActivity(context, 0, intent,
                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
index 2169817f5..868ed91 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
@@ -76,7 +76,7 @@
         Assert.assertTrue(delegateFactory instanceof CustomTabDelegateFactory);
         CustomTabDelegateFactory customTabDelegateFactory =
                 ((CustomTabDelegateFactory) delegateFactory);
-        mUrlHandler = customTabDelegateFactory.getExternalNavigationHandler();
+        mUrlHandler = customTabDelegateFactory.createExternalNavigationHandler(tab);
         Assert.assertTrue(customTabDelegateFactory.getExternalNavigationDelegate()
                                   instanceof CustomTabNavigationDelegate);
         mNavigationDelegate = (CustomTabNavigationDelegate)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
index 814c0ecf..d7f1615 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
@@ -144,8 +144,10 @@
             @Override
             public boolean isSatisfied() {
                 Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
-                if (tab == null || tab.getInterceptNavigationDelegate() == null) return false;
-                navigationDelegate.set(tab.getInterceptNavigationDelegate());
+                if (tab == null) return false;
+                InterceptNavigationDelegateImpl delegate = InterceptNavigationDelegateImpl.get(tab);
+                if (delegate == null) return false;
+                navigationDelegate.set(delegate);
                 return true;
             }
         });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
index 96ce5d2..2b355b9e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -25,6 +25,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.RetryOnFailure;
@@ -33,6 +34,7 @@
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
+import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.test.ChromeActivityTestRule;
@@ -147,7 +149,10 @@
 
         final Tab tab = mActivityTestRule.getActivity().getActivityTab();
         final Tab[] latestTabHolder = new Tab[1];
+        final InterceptNavigationDelegateImpl[] latestDelegateHolder =
+                new InterceptNavigationDelegateImpl[1];
         latestTabHolder[0] = tab;
+        latestDelegateHolder[0] = getInterceptNavigationDelegate(tab);
         tab.addObserver(new TestTabObserver(finishCallback, failCallback));
         if (expectedNewTabCount > 0) {
             mActivityTestRule.getActivity().getTabModelSelector().addObserver(
@@ -157,6 +162,7 @@
                             newTabCallback.notifyCalled();
                             newTab.addObserver(new TestTabObserver(finishCallback, failCallback));
                             latestTabHolder[0] = newTab;
+                            latestDelegateHolder[0] = getInterceptNavigationDelegate(newTab);
                         }
                     });
         }
@@ -220,10 +226,10 @@
                         // in the tab. Rather, we check the final URL to distinguish between
                         // fallback and normal navigation. See crbug.com/487364 for more.
                         Tab tab = latestTabHolder[0];
+                        InterceptNavigationDelegateImpl delegate = latestDelegateHolder[0];
                         if (shouldLaunchExternalIntent
                                 != (OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT
-                                        == tab.getInterceptNavigationDelegate()
-                                                .getLastOverrideUrlLoadingResultForTests())) {
+                                        == delegate.getLastOverrideUrlLoadingResultForTests())) {
                             return false;
                         }
                         updateFailureReason("Expected: " + expectedFinalUrl + " actual: "
@@ -245,6 +251,11 @@
         Assert.assertTrue(failCallback.getCallCount() >= 1);
     }
 
+    private static InterceptNavigationDelegateImpl getInterceptNavigationDelegate(Tab tab) {
+        return ThreadUtils.runOnUiThreadBlockingNoException(
+                () -> InterceptNavigationDelegateImpl.get(tab));
+    }
+
     @Test
     @SmallTest
     @RetryOnFailure
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
index 5e99499..a52feb2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
@@ -69,21 +69,8 @@
     private ChromeActivity mActivity;
     private List<NavigationParams> mNavParamHistory = new ArrayList<>();
     private List<ExternalNavigationParams> mExternalNavParamHistory = new ArrayList<>();
-    private TestInterceptNavigationDelegate mInterceptNavigationDelegate;
     private EmbeddedTestServer mTestServer;
 
-    class TestInterceptNavigationDelegate extends InterceptNavigationDelegateImpl {
-        TestInterceptNavigationDelegate() {
-            super(new TestExternalNavigationHandler(), mActivity.getActivityTab());
-        }
-
-        @Override
-        public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
-            mNavParamHistory.add(navigationParams);
-            return super.shouldIgnoreNavigation(navigationParams);
-        }
-    }
-
     class TestExternalNavigationHandler extends ExternalNavigationHandler {
         public TestExternalNavigationHandler() {
             super(mActivity.getActivityTab());
@@ -111,13 +98,17 @@
     public void setUp() throws Exception {
         mActivityTestRule.startMainActivityOnBlankPage();
         mActivity = mActivityTestRule.getActivity();
-        mInterceptNavigationDelegate = new TestInterceptNavigationDelegate();
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                Tab tab = mActivity.getActivityTab();
-                tab.setInterceptNavigationDelegate(mInterceptNavigationDelegate);
-            }
+        final Tab tab = mActivity.getActivityTab();
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            InterceptNavigationDelegateImpl delegate = new InterceptNavigationDelegateImpl(tab) {
+                @Override
+                public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
+                    mNavParamHistory.add(navigationParams);
+                    return super.shouldIgnoreNavigation(navigationParams);
+                }
+            };
+            delegate.setExternalNavigationHandler(new TestExternalNavigationHandler());
+            InterceptNavigationDelegateImpl.initDelegateForTesting(tab, delegate);
         });
         mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
index a583142..4182eb2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -296,8 +296,10 @@
     public void testRegularLinkToExternalApp() throws Exception {
         runWebappActivityAndWaitForIdle(mActivityTestRule.createIntent());
 
-        InterceptNavigationDelegateImpl navigationDelegate =
-                mActivityTestRule.getActivity().getActivityTab().getInterceptNavigationDelegate();
+        InterceptNavigationDelegateImpl navigationDelegate = ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> InterceptNavigationDelegateImpl.get(
+                                mActivityTestRule.getActivity().getActivityTab()));
 
         addAnchorAndClick(YOUTUBE_URL, "_self");
 
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index abffa3c..08def2747 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-74.0.3729.10_rc-r1-merged.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-74.0.3729.12_rc-r1-merged.afdo.bz2
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 915a5eb..5b9c13bd 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1685,12 +1685,6 @@
     "task_manager/web_contents_tags.h",
     "themes/theme_service_win.cc",
     "themes/theme_service_win.h",
-    "thumbnails/thumbnail_tab_helper.cc",
-    "thumbnails/thumbnail_tab_helper.h",
-    "thumbnails/thumbnail_utils.cc",
-    "thumbnails/thumbnail_utils.h",
-    "thumbnails/thumbnailing_context.cc",
-    "thumbnails/thumbnailing_context.h",
     "tracing/background_tracing_field_trial.cc",
     "tracing/background_tracing_field_trial.h",
     "tracing/chrome_tracing_delegate.cc",
@@ -2391,6 +2385,7 @@
       "android/instantapps/instant_apps_settings.h",
       "android/intent_helper.cc",
       "android/intent_helper.h",
+      "android/intercept_navigation_delegate_impl.cc",
       "android/large_icon_bridge.cc",
       "android/large_icon_bridge.h",
       "android/locale/locale_manager.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1d70726b..361e146 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3385,6 +3385,13 @@
      flag_descriptions::kAutofillEnableCompanyNameName,
      flag_descriptions::kAutofillEnableCompanyNameDescription, kOsAll,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCompanyName)},
+
+    {"autofill-enable-toolbar-status-chip",
+     flag_descriptions::kAutofillEnableToolbarStatusChipName,
+     flag_descriptions::kAutofillEnableToolbarStatusChipDescription,
+     kOsMac | kOsWin | kOsLinux,
+     FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableToolbarStatusChip)},
+
     {"autofill-enforce-min-required-fields-for-heuristics",
      flag_descriptions::kAutofillEnforceMinRequiredFieldsForHeuristicsName,
      flag_descriptions::
diff --git a/chrome/browser/android/background_sync_launcher_android.cc b/chrome/browser/android/background_sync_launcher_android.cc
index effc509..8eaedf25 100644
--- a/chrome/browser/android/background_sync_launcher_android.cc
+++ b/chrome/browser/android/background_sync_launcher_android.cc
@@ -8,7 +8,6 @@
 
 #include "base/android/callback_android.h"
 #include "base/barrier_closure.h"
-#include "base/bind.h"
 #include "base/feature_list.h"
 #include "chrome/browser/android/chrome_feature_list.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -53,10 +52,12 @@
 }
 
 // static
-void BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped() {
+void BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped(
+    bool launch_when_next_online,
+    int64_t min_delay_ms) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  Get()->LaunchBrowserIfStoppedImpl();
+  Get()->LaunchBrowserIfStoppedImpl(launch_when_next_online, min_delay_ms);
 }
 
 // static
@@ -75,38 +76,24 @@
       base::android::AttachCurrentThread());
 }
 
-void BackgroundSyncLauncherAndroid::LaunchBrowserIfStoppedImpl() {
+void BackgroundSyncLauncherAndroid::LaunchBrowserIfStoppedImpl(
+    bool launch_when_next_online,
+    int64_t min_delay_ms) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  auto* profile = ProfileManager::GetLastUsedProfile();
-  DCHECK(profile);
-
-  auto* storage_partition =
-      content::BrowserContext::GetDefaultStoragePartition(profile);
-  storage_partition->GetBackgroundSyncContext()
-      ->GetSoonestWakeupDeltaAcrossPartitions(
-          profile,
-          base::BindOnce(
-              &BackgroundSyncLauncherAndroid::LaunchBrowserWithWakeupDelta,
-              base::Unretained(this)));
-}
-
-void BackgroundSyncLauncherAndroid::LaunchBrowserWithWakeupDelta(
-    base::TimeDelta soonest_wakeup_delta) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  int64_t min_delay_ms = soonest_wakeup_delta.InMilliseconds();
 
   if (!base::FeatureList::IsEnabled(
           chrome::android::kBackgroundTaskSchedulerForBackgroundSync)) {
     Java_BackgroundSyncLauncher_launchBrowserIfStopped(
-        env, java_gcm_network_manager_launcher_, soonest_wakeup_delta.is_max(),
+        env, java_gcm_network_manager_launcher_, launch_when_next_online,
         min_delay_ms);
     return;
   }
 
   Java_BackgroundSyncBackgroundTaskScheduler_launchBrowserIfStopped(
       env, java_background_sync_background_task_scheduler_launcher_,
-      soonest_wakeup_delta.is_max(), min_delay_ms);
+      launch_when_next_online, min_delay_ms);
 }
 
 void BackgroundSyncLauncherAndroid::FireBackgroundSyncEvents(
@@ -116,12 +103,51 @@
   auto* profile = ProfileManager::GetLastUsedProfile();
   DCHECK(profile);
 
-  auto* storage_partition =
-      content::BrowserContext::GetDefaultStoragePartition(profile);
-  storage_partition->GetBackgroundSyncContext()
-      ->FireBackgroundSyncEventsAcrossPartitions(profile, j_runnable);
+  int num_partitions = 0;
+  content::BrowserContext::ForEachStoragePartition(
+      profile, base::BindRepeating(
+                   [](int* num_partitions,
+                      content::StoragePartition* storage_partition) {
+                     (*num_partitions)++;
+                   },
+                   &num_partitions));
+
+  // This class is a singleton, which is only destructed on program exit.
+  // Therefore, use of base::Unretained(this) is safe.
+  base::RepeatingClosure done_closure = base::BarrierClosure(
+      num_partitions,
+      base::BindOnce(base::android::RunRunnableAndroid,
+                     base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
+
+  content::BrowserContext::ForEachStoragePartition(
+      profile,
+      base::BindRepeating(&BackgroundSyncLauncherAndroid::
+                              FireBackgroundSyncEventsForStoragePartition,
+                          base::Unretained(this), done_closure));
 }
 
+void BackgroundSyncLauncherAndroid::FireBackgroundSyncEventsForStoragePartition(
+    base::OnceClosure done_closure,
+    content::StoragePartition* storage_partition) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  content::BackgroundSyncContext* sync_context =
+      storage_partition->GetBackgroundSyncContext();
+  if (!sync_context) {
+    std::move(done_closure).Run();
+    return;
+  }
+
+  sync_context->FireBackgroundSyncEventsForStoragePartition(
+      storage_partition, std::move(done_closure));
+}
+
+void BackgroundSyncLauncherAndroid::OnFiredBackgroundSyncEvents(
+    base::android::ScopedJavaGlobalRef<jobject> j_runnable) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  base::android::RunRunnableAndroid(j_runnable);
+}
 
 BackgroundSyncLauncherAndroid::BackgroundSyncLauncherAndroid() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/android/background_sync_launcher_android.h b/chrome/browser/android/background_sync_launcher_android.h
index 25cfec2..1afb9bae 100644
--- a/chrome/browser/android/background_sync_launcher_android.h
+++ b/chrome/browser/android/background_sync_launcher_android.h
@@ -13,7 +13,10 @@
 #include "base/callback_forward.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
-#include "base/time/time.h"
+
+namespace content {
+class StoragePartition;
+}  // namespace content
 
 // The BackgroundSyncLauncherAndroid singleton owns the Java
 // BackgroundSyncLauncher object and is used to register interest in starting
@@ -23,12 +26,8 @@
  public:
   static BackgroundSyncLauncherAndroid* Get();
 
-  // Calculates the soonest wakeup time across all the storage
-  // partitions for the non-incognito profile and ensures that the browser
-  // is running when the device next goes online after that time has passed.
-  // If this time is set to base::TimeDelta::Max() across all storage
-  // partitions, the wake-up task is cancelled.
-  static void LaunchBrowserIfStopped();
+  static void LaunchBrowserIfStopped(bool launch_when_next_online,
+                                     int64_t min_delay_ms);
 
   static bool ShouldDisableBackgroundSync();
 
@@ -48,8 +47,13 @@
   BackgroundSyncLauncherAndroid();
   ~BackgroundSyncLauncherAndroid();
 
-  void LaunchBrowserIfStoppedImpl();
-  void LaunchBrowserWithWakeupDelta(base::TimeDelta soonest_wakeup_delta);
+  void LaunchBrowserIfStoppedImpl(bool launch_when_next_online,
+                                  int64_t min_delay_ms);
+  void FireBackgroundSyncEventsForStoragePartition(
+      base::OnceClosure done_closure,
+      content::StoragePartition* storage_partition);
+  void OnFiredBackgroundSyncEvents(
+      base::android::ScopedJavaGlobalRef<jobject> j_runnable);
 
   base::android::ScopedJavaGlobalRef<jobject>
       java_gcm_network_manager_launcher_;
diff --git a/chrome/browser/android/intercept_navigation_delegate_impl.cc b/chrome/browser/android/intercept_navigation_delegate_impl.cc
new file mode 100644
index 0000000..76722b7f
--- /dev/null
+++ b/chrome/browser/android/intercept_navigation_delegate_impl.cc
@@ -0,0 +1,44 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/navigation_interception/intercept_navigation_delegate.h"
+#include "components/navigation_interception/navigation_params.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/InterceptNavigationDelegateImpl_jni.h"
+#include "net/base/escape.h"
+
+namespace {
+
+using navigation_interception::InterceptNavigationDelegate;
+using navigation_interception::NavigationParams;
+
+class ChromeInterceptNavigationDelegate : public InterceptNavigationDelegate {
+ public:
+  ChromeInterceptNavigationDelegate(JNIEnv* env, jobject jdelegate)
+      : InterceptNavigationDelegate(env, jdelegate) {}
+
+  bool ShouldIgnoreNavigation(
+      const NavigationParams& navigation_params) override {
+    NavigationParams chrome_navigation_params(navigation_params);
+    chrome_navigation_params.url() =
+        GURL(net::EscapeExternalHandlerValue(navigation_params.url().spec()));
+    return InterceptNavigationDelegate::ShouldIgnoreNavigation(
+        chrome_navigation_params);
+  }
+};
+
+}  // namespace
+
+static void JNI_InterceptNavigationDelegateImpl_AssociateWithWebContents(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jdelegate,
+    const base::android::JavaParamRef<jobject>& jweb_contents) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  content::WebContents* web_contents =
+      content::WebContents::FromJavaWebContents(jweb_contents);
+  InterceptNavigationDelegate::Associate(
+      web_contents,
+      std::make_unique<ChromeInterceptNavigationDelegate>(env, jdelegate));
+}
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index 4bb77b1a..7d29af0 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -48,8 +48,6 @@
 #include "components/bookmarks/browser/bookmark_utils.h"
 #include "components/bookmarks/managed/managed_bookmark_service.h"
 #include "components/dom_distiller/core/url_utils.h"
-#include "components/navigation_interception/intercept_navigation_delegate.h"
-#include "components/navigation_interception/navigation_params.h"
 #include "components/sessions/content/content_live_tab.h"
 #include "components/sessions/core/tab_restore_service.h"
 #include "components/url_formatter/url_fixer.h"
@@ -66,7 +64,6 @@
 #include "content/public/browser/web_contents_user_data.h"
 #include "content/public/common/resource_request_body_android.h"
 #include "jni/Tab_jni.h"
-#include "net/base/escape.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "ui/android/view_android.h"
@@ -78,12 +75,9 @@
 using base::android::JavaParamRef;
 using base::android::JavaRef;
 using chrome::android::BackgroundTabManager;
-using content::BrowserThread;
 using content::GlobalRequestID;
 using content::NavigationController;
 using content::WebContents;
-using navigation_interception::InterceptNavigationDelegate;
-using navigation_interception::NavigationParams;
 
 namespace {
 
@@ -622,35 +616,6 @@
   }
 }
 
-namespace {
-
-class ChromeInterceptNavigationDelegate : public InterceptNavigationDelegate {
- public:
-  ChromeInterceptNavigationDelegate(JNIEnv* env, jobject jdelegate)
-      : InterceptNavigationDelegate(env, jdelegate) {}
-
-  bool ShouldIgnoreNavigation(
-      const NavigationParams& navigation_params) override {
-    NavigationParams chrome_navigation_params(navigation_params);
-    chrome_navigation_params.url() =
-        GURL(net::EscapeExternalHandlerValue(navigation_params.url().spec()));
-    return InterceptNavigationDelegate::ShouldIgnoreNavigation(
-        chrome_navigation_params);
-  }
-};
-
-}  // namespace
-
-void TabAndroid::SetInterceptNavigationDelegate(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jobject>& delegate) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  InterceptNavigationDelegate::Associate(
-      web_contents(),
-      std::make_unique<ChromeInterceptNavigationDelegate>(env, delegate));
-}
-
 void TabAndroid::SetWebappManifestScope(JNIEnv* env,
                                         const JavaParamRef<jobject>& obj,
                                         const JavaParamRef<jstring>& scope) {
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.cc b/chrome/browser/background_sync/background_sync_controller_impl.cc
index f73f95e2..40c86396 100644
--- a/chrome/browser/background_sync/background_sync_controller_impl.cc
+++ b/chrome/browser/background_sync/background_sync_controller_impl.cc
@@ -114,13 +114,17 @@
                                           origin.GetURL());
 }
 
-void BackgroundSyncControllerImpl::RunInBackground() {
+void BackgroundSyncControllerImpl::RunInBackground(bool enabled,
+                                                   int64_t min_ms) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (profile_->IsOffTheRecord())
     return;
 #if defined(OS_ANDROID)
-  BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped();
+  BackgroundSyncLauncherAndroid::LaunchBrowserIfStopped(enabled, min_ms);
+#else
+// TODO(jkarlin): Use BackgroundModeManager to enter background mode. See
+// https://crbug.com/484201.
 #endif
 }
 
diff --git a/chrome/browser/background_sync/background_sync_controller_impl.h b/chrome/browser/background_sync/background_sync_controller_impl.h
index e5739a39..6446b77 100644
--- a/chrome/browser/background_sync/background_sync_controller_impl.h
+++ b/chrome/browser/background_sync/background_sync_controller_impl.h
@@ -45,7 +45,7 @@
   void GetParameterOverrides(
       content::BackgroundSyncParameters* parameters) const override;
   void NotifyBackgroundSyncRegistered(const url::Origin& origin) override;
-  void RunInBackground() override;
+  void RunInBackground(bool enabled, int64_t min_ms) override;
 
  protected:
   // Virtual for testing.
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index fbc75a1..75633bcd 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -852,11 +852,16 @@
           delete_begin_, delete_end_);
 
       // Clear out the Autofill LegacyStrikeDatabase in its entirety.
+      // Both StrikeDatabase and LegacyStrikeDatabase use data from the same
+      // ProtoDatabase, so only one of them needs to call ClearAllStrikes(~).
       // TODO(crbug.com/884817): Respect |delete_begin_| and |delete_end_| and
       // only clear out entries whose last strikes were created in that
       // timeframe.
       if (base::FeatureList::IsEnabled(
-              autofill::features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+              autofill::features::kAutofillSaveCreditCardUsesStrikeSystemV2) ||
+          base::FeatureList::IsEnabled(
+              autofill::features::
+                  kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
         autofill::StrikeDatabase* strike_database =
             autofill::StrikeDatabaseFactory::GetForProfile(profile_);
         if (strike_database)
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import.cc b/chrome/browser/chromeos/crostini/crostini_export_import.cc
index da2b88f..0dc16c1 100644
--- a/chrome/browser/chromeos/crostini/crostini_export_import.cc
+++ b/chrome/browser/chromeos/crostini/crostini_export_import.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/crostini/crostini_export_import.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
@@ -133,8 +135,30 @@
                                         void* params) {
   ExportImportType type =
       static_cast<ExportImportType>(reinterpret_cast<uintptr_t>(params));
-  ContainerId container_id(kCrostiniDefaultVmName,
-                           kCrostiniDefaultContainerName);
+  Start(type,
+        ContainerId(kCrostiniDefaultVmName, kCrostiniDefaultContainerName),
+        path, base::DoNothing());
+}
+
+void CrostiniExportImport::ExportContainer(
+    ContainerId container_id,
+    base::FilePath path,
+    CrostiniManager::CrostiniResultCallback callback) {
+  Start(ExportImportType::EXPORT, container_id, path, std::move(callback));
+}
+
+void CrostiniExportImport::ImportContainer(
+    ContainerId container_id,
+    base::FilePath path,
+    CrostiniManager::CrostiniResultCallback callback) {
+  Start(ExportImportType::IMPORT, container_id, path, std::move(callback));
+}
+
+void CrostiniExportImport::Start(
+    ExportImportType type,
+    const ContainerId& container_id,
+    base::FilePath path,
+    CrostiniManager::CrostiniResultCallback callback) {
   notifications_[container_id] =
       std::make_unique<CrostiniExportImportNotification>(
           profile_, this, type, GetUniqueNotificationId(), path);
@@ -145,13 +169,14 @@
           kCrostiniDefaultVmName, path.DirName(), false,
           base::BindOnce(&CrostiniExportImport::ExportAfterSharing,
                          weak_ptr_factory_.GetWeakPtr(), container_id,
-                         path.BaseName()));
+                         path.BaseName(), std::move(callback)));
       break;
     case ExportImportType::IMPORT:
       CrostiniSharePath::GetForProfile(profile_)->SharePath(
           kCrostiniDefaultVmName, path, false,
           base::BindOnce(&CrostiniExportImport::ImportAfterSharing,
-                         weak_ptr_factory_.GetWeakPtr(), container_id));
+                         weak_ptr_factory_.GetWeakPtr(), container_id,
+                         std::move(callback)));
       break;
   }
 }
@@ -159,6 +184,7 @@
 void CrostiniExportImport::ExportAfterSharing(
     const ContainerId& container_id,
     const base::FilePath& filename,
+    CrostiniManager::CrostiniResultCallback callback,
     const base::FilePath& container_path,
     bool result,
     const std::string failure_reason) {
@@ -177,12 +203,14 @@
       container_path.Append(filename),
       base::BindOnce(&CrostiniExportImport::OnExportComplete,
                      weak_ptr_factory_.GetWeakPtr(), base::Time::Now(),
-                     container_id));
+                     container_id, std::move(callback)));
 }
 
-void CrostiniExportImport::OnExportComplete(const base::Time& start,
-                                            const ContainerId& container_id,
-                                            CrostiniResult result) {
+void CrostiniExportImport::OnExportComplete(
+    const base::Time& start,
+    const ContainerId& container_id,
+    CrostiniManager::CrostiniResultCallback callback,
+    CrostiniResult result) {
   auto it = notifications_.find(container_id);
   DCHECK(it != notifications_.end())
       << ContainerIdToString(container_id) << " has no notification to update";
@@ -190,18 +218,28 @@
   CrostiniExportImportNotification::Status status =
       CrostiniExportImportNotification::Status::DONE;
   ExportContainerResult enum_hist_result = ExportContainerResult::kSuccess;
-  if (result != crostini::CrostiniResult::SUCCESS) {
-    LOG(ERROR) << "Error exporting " << int(result);
-    status = CrostiniExportImportNotification::Status::FAILED;
-    enum_hist_result = ExportContainerResult::kFailed;
-    UMA_HISTOGRAM_LONG_TIMES("Crostini.BackupTimeFailed",
+  if (result == crostini::CrostiniResult::SUCCESS) {
+    UMA_HISTOGRAM_LONG_TIMES("Crostini.BackupTimeSuccess",
                              base::Time::Now() - start);
   } else {
-    UMA_HISTOGRAM_LONG_TIMES("Crostini.BackupTimeSuccess",
+    LOG(ERROR) << "Error exporting " << int(result);
+    status = CrostiniExportImportNotification::Status::FAILED;
+    switch (result) {
+      case crostini::CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED:
+        enum_hist_result = ExportContainerResult::kFailedVmStopped;
+        break;
+      case crostini::CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED:
+        enum_hist_result = ExportContainerResult::kFailedVmStarted;
+        break;
+      default:
+        enum_hist_result = ExportContainerResult::kFailed;
+    }
+    UMA_HISTOGRAM_LONG_TIMES("Crostini.BackupTimeFailed",
                              base::Time::Now() - start);
   }
   it->second->UpdateStatus(status, 0);
   UMA_HISTOGRAM_ENUMERATION("Crostini.Backup", enum_hist_result);
+  std::move(callback).Run(result);
 }
 
 void CrostiniExportImport::OnExportContainerProgress(
@@ -235,6 +273,7 @@
 
 void CrostiniExportImport::ImportAfterSharing(
     const ContainerId& container_id,
+    CrostiniManager::CrostiniResultCallback callback,
     const base::FilePath& container_path,
     bool result,
     const std::string failure_reason) {
@@ -252,30 +291,45 @@
       kCrostiniDefaultVmName, kCrostiniDefaultContainerName, container_path,
       base::BindOnce(&CrostiniExportImport::OnImportComplete,
                      weak_ptr_factory_.GetWeakPtr(), base::Time::Now(),
-                     container_id));
+                     container_id, std::move(callback)));
 }
 
-void CrostiniExportImport::OnImportComplete(const base::Time& start,
-                                            const ContainerId& container_id,
-                                            CrostiniResult result) {
+void CrostiniExportImport::OnImportComplete(
+    const base::Time& start,
+    const ContainerId& container_id,
+    CrostiniManager::CrostiniResultCallback callback,
+    CrostiniResult result) {
   auto it = notifications_.find(container_id);
   DCHECK(it != notifications_.end())
       << ContainerIdToString(container_id) << " has no notification to update";
   CrostiniExportImportNotification::Status status =
       CrostiniExportImportNotification::Status::DONE;
   ImportContainerResult enum_hist_result = ImportContainerResult::kSuccess;
-  if (result != crostini::CrostiniResult::SUCCESS) {
-    LOG(ERROR) << "Error importing " << int(result);
-    status = CrostiniExportImportNotification::Status::FAILED;
-    enum_hist_result = ImportContainerResult::kFailed;
-    UMA_HISTOGRAM_LONG_TIMES("Crostini.RestoreTimeFailed",
+  if (result == crostini::CrostiniResult::SUCCESS) {
+    UMA_HISTOGRAM_LONG_TIMES("Crostini.RestoreTimeSuccess",
                              base::Time::Now() - start);
   } else {
-    UMA_HISTOGRAM_LONG_TIMES("Crostini.RestoreTimeSuccess",
+    LOG(ERROR) << "Error importing " << int(result);
+    status = CrostiniExportImportNotification::Status::FAILED;
+    switch (result) {
+      case crostini::CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED:
+        enum_hist_result = ImportContainerResult::kFailedVmStopped;
+        break;
+      case crostini::CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED:
+        enum_hist_result = ImportContainerResult::kFailedVmStarted;
+        break;
+      default:
+        enum_hist_result = ImportContainerResult::kFailed;
+    }
+    UMA_HISTOGRAM_LONG_TIMES("Crostini.RestoreTimeFailed",
                              base::Time::Now() - start);
   }
   it->second->UpdateStatus(status, 0);
   UMA_HISTOGRAM_ENUMERATION("Crostini.Restore", enum_hist_result);
+
+  // Restart from CrostiniManager.
+  CrostiniManager::GetForProfile(profile_)->RestartCrostini(
+      container_id.first, container_id.second, std::move(callback));
 }
 
 void CrostiniExportImport::OnImportContainerProgress(
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import.h b/chrome/browser/chromeos/crostini/crostini_export_import.h
index a6e78df..a3685856 100644
--- a/chrome/browser/chromeos/crostini/crostini_export_import.h
+++ b/chrome/browser/chromeos/crostini/crostini_export_import.h
@@ -33,13 +33,17 @@
 enum class ExportContainerResult {
   kSuccess = 0,
   kFailed = 1,
-  kMaxValue = kFailed,
+  kFailedVmStopped = 2,
+  kFailedVmStarted = 3,
+  kMaxValue = kFailedVmStarted,
 };
 
 enum class ImportContainerResult {
   kSuccess = 0,
   kFailed = 1,
-  kMaxValue = kFailed,
+  kFailedVmStopped = 2,
+  kFailedVmStarted = 3,
+  kMaxValue = kFailedVmStarted,
 };
 
 // CrostiniExportImport is a keyed profile service to manage exporting and
@@ -61,11 +65,20 @@
   // KeyedService:
   void Shutdown() override;
 
-  // Export the crostini container.
+  // Export the crostini container showing FileDialog.
   void ExportContainer(content::WebContents* web_contents);
-  // Import the crostini container.
+  // Import the crostini container showing FileDialog.
   void ImportContainer(content::WebContents* web_contents);
 
+  // Export |container| to |path| and invoke |callback| when complete.
+  void ExportContainer(ContainerId container_id,
+                       base::FilePath path,
+                       CrostiniManager::CrostiniResultCallback callback);
+  // Import |container| to |path| and invoke |callback| when complete.
+  void ImportContainer(ContainerId container_id,
+                       base::FilePath path,
+                       CrostiniManager::CrostiniResultCallback callback);
+
   // Called by the notification when it is closed so it can be destroyed.
   void NotificationCompleted(CrostiniExportImportNotification* notification);
 
@@ -83,6 +96,11 @@
                     int index,
                     void* params) override;
 
+  void Start(ExportImportType type,
+             const ContainerId& container_id,
+             base::FilePath path,
+             CrostiniManager::CrostiniResultCallback callback);
+
   // crostini::ExportContainerProgressObserver implementation.
   void OnExportContainerProgress(const std::string& vm_name,
                                  const std::string& container_name,
@@ -99,19 +117,23 @@
 
   void ExportAfterSharing(const ContainerId& container_id,
                           const base::FilePath& filename,
+                          CrostiniManager::CrostiniResultCallback callback,
                           const base::FilePath& container_path,
                           bool result,
                           const std::string failure_reason);
   void OnExportComplete(const base::Time& start,
                         const ContainerId& container_id,
+                        CrostiniManager::CrostiniResultCallback callback,
                         CrostiniResult result);
 
   void ImportAfterSharing(const ContainerId& container_id,
+                          CrostiniManager::CrostiniResultCallback callback,
                           const base::FilePath& container_path,
                           bool result,
                           const std::string failure_reason);
   void OnImportComplete(const base::Time& start,
                         const ContainerId& container_id,
+                        CrostiniManager::CrostiniResultCallback callback,
                         CrostiniResult result);
 
   void OpenFileDialog(ExportImportType type,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index cf37eab..6f06558b 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -1121,7 +1121,7 @@
       export_lxd_container_callbacks_.end()) {
     LOG(ERROR) << "Export currently in progress for " << vm_name << ", "
                << container_name;
-    std::move(callback).Run(CrostiniResult::CONTAINER_EXPORT_FAILED);
+    std::move(callback).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     return;
   }
   export_lxd_container_callbacks_.emplace(key, std::move(callback));
@@ -1162,7 +1162,7 @@
       import_lxd_container_callbacks_.end()) {
     LOG(ERROR) << "Import currently in progress for " << vm_name << ", "
                << container_name;
-    std::move(callback).Run(CrostiniResult::CONTAINER_IMPORT_FAILED);
+    std::move(callback).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     return;
   }
   import_lxd_container_callbacks_.emplace(key, std::move(callback));
@@ -1905,16 +1905,20 @@
   }
   vm_tools::concierge::StartVmResponse response = reply.value();
 
+  // Any pending backup or restore callbacks can be marked as failed.
+  InvokeAndErasePendingCallbacks(
+      &export_lxd_container_callbacks_, vm_name,
+      CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED);
+  InvokeAndErasePendingCallbacks(
+      &import_lxd_container_callbacks_, vm_name,
+      CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED);
+
   if (response.status() == vm_tools::concierge::VM_STATUS_FAILURE ||
       response.status() == vm_tools::concierge::VM_STATUS_UNKNOWN) {
     LOG(ERROR) << "Failed to start VM: " << response.failure_reason();
     // If we thought vms and containers were running before, they aren't now.
     running_vms_.erase(vm_name);
     running_containers_.erase(vm_name);
-    InvokeAndErasePendingCallbacks(&export_lxd_container_callbacks_, vm_name,
-                                   CrostiniResult::CONTAINER_EXPORT_FAILED);
-    InvokeAndErasePendingCallbacks(&import_lxd_container_callbacks_, vm_name,
-                                   CrostiniResult::CONTAINER_IMPORT_FAILED);
     std::move(callback).Run(CrostiniResult::VM_START_FAILED);
     return;
   }
@@ -1989,10 +1993,12 @@
   // Remove from running_vms_, and other vm-keyed state.
   running_vms_.erase(vm_name);
   running_containers_.erase(vm_name);
-  InvokeAndErasePendingCallbacks(&export_lxd_container_callbacks_, vm_name,
-                                 CrostiniResult::CONTAINER_EXPORT_FAILED);
-  InvokeAndErasePendingCallbacks(&import_lxd_container_callbacks_, vm_name,
-                                 CrostiniResult::CONTAINER_IMPORT_FAILED);
+  InvokeAndErasePendingCallbacks(
+      &export_lxd_container_callbacks_, vm_name,
+      CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED);
+  InvokeAndErasePendingCallbacks(
+      &import_lxd_container_callbacks_, vm_name,
+      CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED);
   std::move(callback).Run(CrostiniResult::SUCCESS);
 }
 
@@ -2585,7 +2591,7 @@
 
   if (!reply.has_value()) {
     LOG(ERROR) << "Failed to export lxd container. Empty response.";
-    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_FAILED);
+    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     export_lxd_container_callbacks_.erase(it);
     return;
   }
@@ -2596,8 +2602,9 @@
   // otherwise this is an error.
   if (response.status() !=
       vm_tools::cicerone::ExportLxdContainerResponse::EXPORTING) {
-    LOG(ERROR) << "Failed to export container: " << response.failure_reason();
-    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_FAILED);
+    LOG(ERROR) << "Failed to export container: status=" << response.status()
+               << ", failure_reason=" << response.failure_reason();
+    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     export_lxd_container_callbacks_.erase(it);
   }
 }
@@ -2611,11 +2618,6 @@
   ExportContainerProgressStatus status;
   CrostiniResult result;
   switch (signal.status()) {
-    // TODO(joelhockey): EXPORTING_TAR and EXPORTING_COMPRESS are deprecated.
-    // Remove them once termina is updated.
-    case vm_tools::cicerone::ExportLxdContainerProgressSignal::EXPORTING_TAR:
-    case vm_tools::cicerone::ExportLxdContainerProgressSignal::
-        EXPORTING_COMPRESS:
     case vm_tools::cicerone::ExportLxdContainerProgressSignal::EXPORTING_PACK:
       exporting = true;
       status = ExportContainerProgressStatus::PACK;
@@ -2629,7 +2631,7 @@
       result = CrostiniResult::SUCCESS;
       break;
     default:
-      result = CrostiniResult::CONTAINER_EXPORT_FAILED;
+      result = CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED;
       LOG(ERROR) << "Failed during export container: " << signal.status()
                  << ", " << signal.failure_reason();
   }
@@ -2670,7 +2672,7 @@
 
   if (!reply.has_value()) {
     LOG(ERROR) << "Failed to import lxd container. Empty response.";
-    std::move(it->second).Run(CrostiniResult::CONTAINER_IMPORT_FAILED);
+    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     import_lxd_container_callbacks_.erase(it);
     return;
   }
@@ -2682,7 +2684,7 @@
   if (response.status() !=
       vm_tools::cicerone::ImportLxdContainerResponse::IMPORTING) {
     LOG(ERROR) << "Failed to import container: " << response.failure_reason();
-    std::move(it->second).Run(CrostiniResult::CONTAINER_IMPORT_FAILED);
+    std::move(it->second).Run(CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED);
     import_lxd_container_callbacks_.erase(it);
   }
 }
@@ -2708,7 +2710,7 @@
       result = CrostiniResult::SUCCESS;
       break;
     default:
-      result = CrostiniResult::CONTAINER_IMPORT_FAILED;
+      result = CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED;
       LOG(ERROR) << "Failed during import container: " << signal.status()
                  << ", " << signal.failure_reason();
   }
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index c87b20b..ed2d8e3 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -70,10 +70,9 @@
   CROSTINI_UNINSTALLER_RUNNING,
   UNKNOWN_USB_DEVICE,
   UNKNOWN_ERROR,
-  CONTAINER_EXPORT_EXPORTING,
-  CONTAINER_EXPORT_FAILED,
-  CONTAINER_IMPORT_IMPORTING,
-  CONTAINER_IMPORT_FAILED,
+  CONTAINER_EXPORT_IMPORT_FAILED,
+  CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED,
+  CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED,
   NOT_ALLOWED,
 };
 
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
index cee22a05..8add03c0 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -1166,7 +1166,7 @@
       kVmName, kContainerName, base::FilePath("export_path"),
       base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
                      base::Unretained(this), base::DoNothing::Once(),
-                     CrostiniResult::CONTAINER_EXPORT_FAILED));
+                     CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED));
 
   // Send signal to indicate 1st call is done.
   vm_tools::cicerone::ExportLxdContainerProgressSignal signal;
@@ -1185,7 +1185,7 @@
       kVmName, kContainerName, base::FilePath("export_path"),
       base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
                      base::Unretained(this), run_loop()->QuitClosure(),
-                     CrostiniResult::CONTAINER_EXPORT_FAILED));
+                     CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED));
 
   // Send signal with FAILED.
   vm_tools::cicerone::ExportLxdContainerProgressSignal signal;
@@ -1203,9 +1203,10 @@
   crostini_manager()->AddRunningVmForTesting(kVmName);
   crostini_manager()->ExportLxdContainer(
       kVmName, kContainerName, base::FilePath("export_path"),
-      base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
-                     base::Unretained(this), run_loop()->QuitClosure(),
-                     CrostiniResult::CONTAINER_EXPORT_FAILED));
+      base::BindOnce(
+          &CrostiniManagerTest::CrostiniResultCallback, base::Unretained(this),
+          run_loop()->QuitClosure(),
+          CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED));
   crostini_manager()->StopVm(kVmName, base::DoNothing());
   run_loop()->Run();
 }
@@ -1252,7 +1253,7 @@
       kVmName, kContainerName, base::FilePath("import_path"),
       base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
                      base::Unretained(this), base::DoNothing::Once(),
-                     CrostiniResult::CONTAINER_IMPORT_FAILED));
+                     CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED));
 
   // Send signal to indicate 1st call is done.
   vm_tools::cicerone::ImportLxdContainerProgressSignal signal;
@@ -1271,7 +1272,7 @@
       kVmName, kContainerName, base::FilePath("import_path"),
       base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
                      base::Unretained(this), run_loop()->QuitClosure(),
-                     CrostiniResult::CONTAINER_IMPORT_FAILED));
+                     CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED));
 
   // Send signal with FAILED.
   vm_tools::cicerone::ImportLxdContainerProgressSignal signal;
@@ -1289,9 +1290,10 @@
   crostini_manager()->AddRunningVmForTesting(kVmName);
   crostini_manager()->ImportLxdContainer(
       kVmName, kContainerName, base::FilePath("import_path"),
-      base::BindOnce(&CrostiniManagerTest::CrostiniResultCallback,
-                     base::Unretained(this), run_loop()->QuitClosure(),
-                     CrostiniResult::CONTAINER_IMPORT_FAILED));
+      base::BindOnce(
+          &CrostiniManagerTest::CrostiniResultCallback, base::Unretained(this),
+          run_loop()->QuitClosure(),
+          CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED));
   crostini_manager()->StopVm(kVmName, base::DoNothing());
   run_loop()->Run();
 }
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 41d942a..212bf8b0 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -28,11 +28,13 @@
 #include "build/build_config.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/assistant/assistant_util.h"
+#include "chrome/browser/chromeos/crostini/crostini_export_import.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 #include "chrome/browser/chromeos/printing/cups_printers_manager.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
@@ -1023,6 +1025,88 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// AutotestPrivateExportCrostiniFunction
+///////////////////////////////////////////////////////////////////////////////
+
+AutotestPrivateExportCrostiniFunction::
+    ~AutotestPrivateExportCrostiniFunction() = default;
+
+ExtensionFunction::ResponseAction AutotestPrivateExportCrostiniFunction::Run() {
+  std::unique_ptr<api::autotest_private::ExportCrostini::Params> params(
+      api::autotest_private::ExportCrostini::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+  DVLOG(1) << "AutotestPrivateExportCrostiniFunction " << params->path;
+
+  Profile* profile = Profile::FromBrowserContext(browser_context());
+  if (!crostini::IsCrostiniUIAllowedForProfile(profile)) {
+    return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
+  }
+
+  base::FilePath path(params->path);
+  if (path.ReferencesParent()) {
+    return RespondNow(Error("Invalid export path must not reference parent"));
+  }
+
+  crostini::CrostiniExportImport::GetForProfile(profile)->ExportContainer(
+      crostini::ContainerId(crostini::kCrostiniDefaultVmName,
+                            crostini::kCrostiniDefaultContainerName),
+      file_manager::util::GetDownloadsFolderForProfile(profile).Append(path),
+      base::BindOnce(&AutotestPrivateExportCrostiniFunction::CrostiniExported,
+                     this));
+
+  return RespondLater();
+}
+
+void AutotestPrivateExportCrostiniFunction::CrostiniExported(
+    crostini::CrostiniResult result) {
+  if (result == crostini::CrostiniResult::SUCCESS) {
+    Respond(NoArguments());
+  } else {
+    Respond(Error("Error exporting crostini"));
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// AutotestPrivateImportCrostiniFunction
+///////////////////////////////////////////////////////////////////////////////
+
+AutotestPrivateImportCrostiniFunction::
+    ~AutotestPrivateImportCrostiniFunction() = default;
+
+ExtensionFunction::ResponseAction AutotestPrivateImportCrostiniFunction::Run() {
+  std::unique_ptr<api::autotest_private::ImportCrostini::Params> params(
+      api::autotest_private::ImportCrostini::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params);
+  DVLOG(1) << "AutotestPrivateImportCrostiniFunction " << params->path;
+
+  Profile* profile = Profile::FromBrowserContext(browser_context());
+  if (!crostini::IsCrostiniUIAllowedForProfile(profile))
+    return RespondNow(Error(kCrostiniNotAvailableForCurrentUserError));
+
+  base::FilePath path(params->path);
+  if (path.ReferencesParent()) {
+    return RespondNow(Error("Invalid import path must not reference parent"));
+  }
+  crostini::CrostiniExportImport::GetForProfile(profile)->ImportContainer(
+      crostini::ContainerId(crostini::kCrostiniDefaultVmName,
+                            crostini::kCrostiniDefaultContainerName),
+      file_manager::util::GetDownloadsFolderForProfile(profile).Append(path),
+      base::BindOnce(&AutotestPrivateImportCrostiniFunction::CrostiniImported,
+                     this));
+
+  return RespondLater();
+}
+
+void AutotestPrivateImportCrostiniFunction::CrostiniImported(
+    crostini::CrostiniResult result) {
+  if (result == crostini::CrostiniResult::SUCCESS) {
+    Respond(NoArguments());
+  } else {
+    Respond(Error("Error importing crostini"));
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // AutotestPrivateTakeScreenshotFunction
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index 8b9ee2a..25adcbd 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -369,6 +369,30 @@
   void CrostiniRemoved(crostini::CrostiniResult);
 };
 
+class AutotestPrivateExportCrostiniFunction : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("autotestPrivate.exportCrostini",
+                             AUTOTESTPRIVATE_EXPORTCROSTINI)
+
+ private:
+  ~AutotestPrivateExportCrostiniFunction() override;
+  ResponseAction Run() override;
+
+  void CrostiniExported(crostini::CrostiniResult);
+};
+
+class AutotestPrivateImportCrostiniFunction : public UIThreadExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("autotestPrivate.importCrostini",
+                             AUTOTESTPRIVATE_IMPORTCROSTINI)
+
+ private:
+  ~AutotestPrivateImportCrostiniFunction() override;
+  ResponseAction Run() override;
+
+  void CrostiniImported(crostini::CrostiniResult);
+};
+
 class AutotestPrivateTakeScreenshotFunction : public UIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("autotestPrivate.takeScreenshot",
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc
index f24cee9..713c1b2 100644
--- a/chrome/browser/chromeos/file_manager/path_util.cc
+++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -405,7 +405,7 @@
   drive::DriveIntegrationService* integration_service = nullptr;
   if (base::FeatureList::IsEnabled(chromeos::features::kDriveFs)) {
     integration_service =
-        drive::DriveIntegrationServiceFactory::GetForProfile(primary_profile);
+        drive::util::GetIntegrationServiceByProfile(primary_profile);
   }
   if ((integration_service &&
        integration_service->GetMountPointPath().AppendRelativePath(
diff --git a/chrome/browser/chromeos/smb_client/smb_share_finder.cc b/chrome/browser/chromeos/smb_client/smb_share_finder.cc
index 76b3c0f..96334ba 100644
--- a/chrome/browser/chromeos/smb_client/smb_share_finder.cc
+++ b/chrome/browser/chromeos/smb_client/smb_share_finder.cc
@@ -7,8 +7,10 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/chromeos/smb_client/discovery/mdns_host_locator.h"
 #include "chrome/browser/chromeos/smb_client/smb_constants.h"
+#include "chrome/browser/chromeos/smb_client/smb_errors.h"
 
 namespace chromeos {
 namespace smb_client {
@@ -136,6 +138,9 @@
   DCHECK_GT(host_counter_, 0u);
   --host_counter_;
 
+  UMA_HISTOGRAM_ENUMERATION("NativeSmbFileShare.GetSharesResult",
+                            TranslateErrorToMountResult(error));
+
   if (error != smbprovider::ErrorType::ERROR_OK) {
     LOG(ERROR) << "Error finding shares: " << error;
     // Don't early out here because this could be the last host being queried,
diff --git a/chrome/browser/chromeos/usb/cros_usb_detector_unittest.cc b/chrome/browser/chromeos/usb/cros_usb_detector_unittest.cc
index c9bb14e..2b4cfd2 100644
--- a/chrome/browser/chromeos/usb/cros_usb_detector_unittest.cc
+++ b/chrome/browser/chromeos/usb/cros_usb_detector_unittest.cc
@@ -45,15 +45,15 @@
   // the FakeUsbDeviceInfo does not set up configurations for a fake device's
   // class code. This helper sets up a configuration to match a devices class
   // code so that USB devices can be filtered out.
+  auto alternate = device::mojom::UsbAlternateInterfaceInfo::New();
+  alternate->alternate_setting = 0;
+  alternate->class_code = device_class;
+  alternate->subclass_code = 0xff;
+  alternate->protocol_code = 0xff;
 
   auto interface = device::mojom::UsbInterfaceInfo::New();
   interface->interface_number = 0;
-  interface->alternates.push_back(device::mojom::UsbAlternateInterfaceInfo::New(
-      /*alternate_setting*/ 0, device_class,
-      /*subclass_code*/ 0xff,
-      /*protocol_code*/ 0xff,
-      /*interface_name*/ base::nullopt,
-      std::vector<device::mojom::UsbEndpointInfoPtr>()));
+  interface->alternates.push_back(std::move(alternate));
 
   auto config = device::mojom::UsbConfigurationInfo::New();
   config->configuration_value = kUsbConfigWithInterfaces;
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
index 0a7f640..b18953b 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/metrics/subprocess_metrics_provider.h"
@@ -26,6 +27,8 @@
 #include "components/data_reduction_proxy/core/common/uma_util.h"
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
 #include "components/prefs/pref_service.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/common/network_service_util.h"
 #include "content/public/common/service_manager_connection.h"
@@ -329,6 +332,80 @@
   EXPECT_EQ(GetBody(), kDummyBody);
 }
 
+IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest,
+                       ProxyNotUsedForWebSocket) {
+  // Expect the WebSocket handshake to be attempted with |test_server|
+  // directly.
+  base::RunLoop web_socket_handshake_loop;
+  net::EmbeddedTestServer test_server;
+  test_server.RegisterRequestHandler(
+      base::BindRepeating(&BasicResponse, kDummyBody));
+  test_server.RegisterRequestMonitor(base::BindLambdaForTesting(
+      [&web_socket_handshake_loop](
+          const net::test_server::HttpRequest& request) {
+        if (request.headers.count("upgrade") > 0u)
+          web_socket_handshake_loop.Quit();
+      }));
+  ASSERT_TRUE(test_server.Start());
+
+  // If the DRP client (erroneously) decides to proxy the WebSocket handshake,
+  // it will attempt to establish a tunnel through |drp_server|.
+  net::EmbeddedTestServer drp_server;
+  drp_server.AddDefaultHandlers(
+      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+  bool tunnel_attempted = false;
+  drp_server.RegisterRequestMonitor(base::BindLambdaForTesting(
+      [&tunnel_attempted, &web_socket_handshake_loop](
+          const net::test_server::HttpRequest& request) {
+        if (request.method == net::test_server::METHOD_CONNECT) {
+          tunnel_attempted = true;
+          web_socket_handshake_loop.Quit();
+        }
+      }));
+  ASSERT_TRUE(drp_server.Start());
+  SetConfig(CreateConfigForServer(drp_server));
+  // A network change forces the config to be fetched.
+  SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_3G);
+  WaitForConfig();
+
+  ui_test_utils::NavigateToURL(browser(),
+                               GetURLWithMockHost(test_server, "/echo"));
+
+  const std::string url =
+      base::StrCat({"ws://", kMockHost, ":", test_server.base_url().port()});
+  const std::string script = R"((url => {
+    var ws = new WebSocket(url);
+  }))";
+  EXPECT_TRUE(
+      ExecuteScript(browser()->tab_strip_model()->GetActiveWebContents(),
+                    script + "('" + url + "')"));
+  web_socket_handshake_loop.Run();
+  EXPECT_FALSE(tunnel_attempted);
+}
+
+IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest,
+                       DoesNotOverrideExistingProxyConfig) {
+  // When there's a proxy configuration provided to the browser already (system
+  // proxy, command line, etc.), the DRP proxy must not override it.
+  net::EmbeddedTestServer existing_proxy_server;
+  existing_proxy_server.RegisterRequestHandler(
+      base::BindRepeating(&BasicResponse, kDummyBody));
+  ASSERT_TRUE(existing_proxy_server.Start());
+
+  browser()->profile()->GetPrefs()->Set(
+      proxy_config::prefs::kProxy,
+      ProxyConfigDictionary::CreateFixedServers(
+          existing_proxy_server.host_port_pair().ToString(), ""));
+
+  EnableDataSaver(true);
+
+  // Proxy will be used, so it shouldn't matter if the host cannot be resolved.
+  ui_test_utils::NavigateToURL(browser(),
+                               GURL("http://does.not.resolve.com/echo"));
+
+  EXPECT_EQ(GetBody(), kDummyBody);
+}
+
 IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, UMAMetricsRecorded) {
   base::HistogramTester histogram_tester;
 
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index be377e6..59515f2 100644
--- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -98,20 +98,30 @@
                                                uint8_t subclass_code,
                                                uint8_t protocol_code) {
   std::vector<UsbEndpointInfoPtr> endpoints;
-  endpoints.push_back(UsbEndpointInfo::New(
-      /*endpoint_number=*/0x01, UsbTransferDirection::INBOUND,
-      UsbTransferType::BULK,
-      /*packet_size=*/512));
-  endpoints.push_back(UsbEndpointInfo::New(
-      /*endpoint_number=*/0x01, UsbTransferDirection::OUTBOUND,
-      UsbTransferType::BULK,
-      /*packet_size=*/512));
+  auto endpoint_1 = UsbEndpointInfo::New();
+  endpoint_1->endpoint_number = 0x01;
+  endpoint_1->direction = UsbTransferDirection::INBOUND;
+  endpoint_1->type = UsbTransferType::BULK;
+  endpoint_1->packet_size = 512;
+  endpoints.push_back(std::move(endpoint_1));
+
+  auto endpoint_2 = UsbEndpointInfo::New();
+  endpoint_2->endpoint_number = 0x01;
+  endpoint_2->direction = UsbTransferDirection::OUTBOUND;
+  endpoint_2->type = UsbTransferType::BULK;
+  endpoint_2->packet_size = 512;
+  endpoints.push_back(std::move(endpoint_2));
+
+  auto alternate = UsbAlternateInterfaceInfo::New();
+  alternate->alternate_setting = 0;
+  alternate->class_code = class_code;
+  alternate->subclass_code = subclass_code;
+  alternate->protocol_code = protocol_code;
+  alternate->endpoints = std::move(endpoints);
 
   auto interface = UsbInterfaceInfo::New();
   interface->interface_number = 0;
-  interface->alternates.push_back(UsbAlternateInterfaceInfo::New(
-      /*alternate_setting=*/0, class_code, subclass_code, protocol_code,
-      /*interface_name=*/base::nullopt, std::move(endpoints)));
+  interface->alternates.push_back(std::move(alternate));
 
   auto config = UsbConfigurationInfo::New();
   config->configuration_value = kAndroidConfigValue;
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index d1c8040c..219fbdc 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_guest_delegate.h"
 #include "chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h"
 #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h"
+#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
 #include "chrome/browser/search/instant_io_context.h"
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
@@ -101,8 +102,10 @@
       web_contents);
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
       web_contents);
-  performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
-      web_contents);
+  if (performance_manager::PerformanceManager::GetInstance()) {
+    performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
+        web_contents);
+  }
 }
 
 bool ChromeExtensionsAPIClient::ShouldHideResponseHeader(
diff --git a/chrome/browser/extensions/chrome_app_icon_loader.cc b/chrome/browser/extensions/chrome_app_icon_loader.cc
index 2126fd80..63b64a1 100644
--- a/chrome/browser/extensions/chrome_app_icon_loader.cc
+++ b/chrome/browser/extensions/chrome_app_icon_loader.cc
@@ -30,17 +30,17 @@
 }  // namespace
 
 ChromeAppIconLoader::ChromeAppIconLoader(Profile* profile,
-                                         int icon_size_in_dips,
+                                         int icon_size_in_dip,
                                          const ResizeFunction& resize_function,
                                          AppIconLoaderDelegate* delegate)
-    : AppIconLoader(profile, icon_size_in_dips, delegate),
+    : AppIconLoader(profile, icon_size_in_dip, delegate),
       resize_function_(resize_function) {}
 
 ChromeAppIconLoader::ChromeAppIconLoader(Profile* profile,
-                                         int icon_size_in_dips,
+                                         int icon_size_in_dip,
                                          AppIconLoaderDelegate* delegate)
     : ChromeAppIconLoader(profile,
-                          icon_size_in_dips,
+                          icon_size_in_dip,
                           ResizeFunction(),
                           delegate) {}
 
@@ -61,8 +61,8 @@
     return;
 
   std::unique_ptr<ChromeAppIcon> icon =
-      ChromeAppIconService::Get(profile())->CreateIcon(this, id, icon_size(),
-                                                       resize_function_);
+      ChromeAppIconService::Get(profile())->CreateIcon(
+          this, id, icon_size_in_dip(), resize_function_);
   // Triggers image loading now instead of depending on paint message. This
   // makes the temp blank image be shown for shorter time and improves user
   // experience. See http://crbug.com/146114.
diff --git a/chrome/browser/extensions/chrome_app_icon_loader.h b/chrome/browser/extensions/chrome_app_icon_loader.h
index 30ed25a..f35ca2d 100644
--- a/chrome/browser/extensions/chrome_app_icon_loader.h
+++ b/chrome/browser/extensions/chrome_app_icon_loader.h
@@ -34,11 +34,11 @@
   // IconLoader with perform the resizing. In both cases |resource_size_in_dip|
   // is used to pick the correct icon representation from resources.
   ChromeAppIconLoader(Profile* profile,
-                      int icon_size_in_dips,
+                      int icon_size_in_dip,
                       const ResizeFunction& resize_function,
                       AppIconLoaderDelegate* delegate);
   ChromeAppIconLoader(Profile* profile,
-                      int icon_size_in_dips,
+                      int icon_size_in_dip,
                       AppIconLoaderDelegate* delegate);
   ~ChromeAppIconLoader() override;
 
diff --git a/chrome/browser/extensions/chrome_extension_host_delegate.cc b/chrome/browser/extensions/chrome_extension_host_delegate.cc
index 7b5f088..5becade 100644
--- a/chrome/browser/extensions/chrome_extension_host_delegate.cc
+++ b/chrome/browser/extensions/chrome_extension_host_delegate.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
@@ -52,8 +53,11 @@
       web_contents);
   PrefsTabHelper::CreateForWebContents(web_contents);
   apps::AudioFocusWebContentsObserver::CreateForWebContents(web_contents);
-  performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
-      web_contents);
+
+  if (performance_manager::PerformanceManager::GetInstance()) {
+    performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
+        web_contents);
+  }
 }
 
 void ChromeExtensionHostDelegate::OnRenderViewCreatedForBackgroundPage(
diff --git a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
index 8997d24f..0a4dddc0 100644
--- a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
+++ b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/strings/pattern.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -12,21 +13,38 @@
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/common/value_builder.h"
 #include "extensions/test/test_extension_dir.h"
+#include "net/dns/mock_host_resolver.h"
 
 namespace extensions {
 
 namespace {
 
+// Returns true if |window.scriptExecuted| is true for the given frame.
+bool WasFrameWithScriptLoaded(content::RenderFrameHost* rfh) {
+  if (!rfh)
+    return false;
+  bool loaded = false;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      rfh, "domAutomationController.send(!!window.scriptExecuted)", &loaded));
+  return loaded;
+}
+
 class ExtensionCSPBypassTest : public ExtensionBrowserTest {
  public:
   ExtensionCSPBypassTest() {}
 
   void SetUpOnMainThread() override {
+    host_resolver()->AddRule("same-origin.com", "127.0.0.1");
+    host_resolver()->AddRule("cross-origin.com", "127.0.0.1");
     ExtensionBrowserTest::SetUpOnMainThread();
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
  protected:
+  content::WebContents* web_contents() const {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
   const Extension* AddExtension(bool is_component, bool all_urls_permission) {
     auto dir = std::make_unique<TestExtensionDir>();
 
@@ -63,8 +81,7 @@
   }
 
   bool CanLoadScript(const Extension* extension) {
-    content::RenderFrameHost* rfh =
-        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
+    content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
     std::string code = base::StringPrintf(
         R"(
         var s = document.createElement('script');
@@ -84,6 +101,11 @@
     return script_loaded;
   }
 
+  content::RenderFrameHost* GetFrameByName(const std::string& name) {
+    return content::FrameMatchingPredicate(
+        web_contents(), base::BindRepeating(&content::FrameMatchesName, name));
+  }
+
  private:
   std::vector<std::unique_ptr<TestExtensionDir>> temp_dirs_;
 
@@ -116,4 +138,44 @@
   EXPECT_FALSE(CanLoadScript(ext_without_permission));
 }
 
+// Tests that an extension can add a cross-origin iframe to a page
+// whose CSP disallows iframes. Regression test for https://crbug.com/408932.
+IN_PROC_BROWSER_TEST_F(ExtensionCSPBypassTest, InjectIframe) {
+  // Install an extension that can add a cross-origin iframe to a document.
+  const Extension* extension =
+      LoadExtension(test_data_dir_.AppendASCII("csp/add_iframe_extension"));
+  ASSERT_TRUE(extension);
+
+  // Navigate to a page that has CSP with 'frame-src: none' to block any
+  // iframes. Use the "same-origin.com" hostname as the test will add iframes to
+  // "cross-origin.com" to make clear they are cross-origin.
+  GURL test_url = embedded_test_server()->GetURL(
+      "same-origin.com", "/extensions/csp/page_with_frame_csp.html");
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
+
+  // First, verify that adding an iframe to the page from the main world will
+  // fail. Add the frame. Its onload event fires even if it's blocked
+  // (see https://crbug.com/365457), and reports back.
+  bool result = false;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents(),
+                                                   "addIframe();", &result));
+  EXPECT_TRUE(result);
+
+  // Use WasFrameWithScriptLoaded() to check whether the target frame really
+  // loaded.
+  content::RenderFrameHost* frame = GetFrameByName("added-by-page");
+  ASSERT_TRUE(frame);
+  EXPECT_FALSE(WasFrameWithScriptLoaded(frame));
+
+  // Second, verify that adding an iframe to the page from the extension will
+  // succeed. Click a button whose event handler runs in the extension's world
+  // which bypasses CSP, and adds the iframe.
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      web_contents(), "document.querySelector('#addIframeButton').click();",
+      &result));
+  frame = GetFrameByName("added-by-extension");
+  ASSERT_TRUE(frame);
+  EXPECT_TRUE(WasFrameWithScriptLoaded(frame));
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_view_host.cc b/chrome/browser/extensions/extension_view_host.cc
index 570155b1..9650fdb 100644
--- a/chrome/browser/extensions/extension_view_host.cc
+++ b/chrome/browser/extensions/extension_view_host.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/extensions/extension_view.h"
 #include "chrome/browser/extensions/window_controller.h"
 #include "chrome/browser/file_select_helper.h"
+#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
@@ -82,8 +83,10 @@
       autofill::ChromeAutofillClient::FromWebContents(host_contents()),
       g_browser_process->GetApplicationLocale(),
       autofill::AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER);
-  performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
-      host_contents());
+  if (performance_manager::PerformanceManager::GetInstance()) {
+    performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
+        host_contents());
+  }
 }
 
 ExtensionViewHost::~ExtensionViewHost() {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index a523b4a..a3ec3601 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -207,6 +207,11 @@
     "expiry_milestone": 73
   },
   {
+    "name": "autofill-enable-toolbar-status-chip",
+    "owners": [ "siyua" ],
+    "expiry_milestone": 77
+  },
+  {
     "name": "autofill-enforce-min-required-fields-for-heuristics",
     "owners": [ "rogerm" ],
     "expiry_milestone": 73
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 019e830f..33e6602 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -105,14 +105,20 @@
     "When enabled, autofill will cache the responses it receives from the "
     "crowd-sourced field type prediction server.";
 
+const char kAutofillDynamicFormsName[] = "Autofill Dynamic Forms";
+const char kAutofillDynamicFormsDescription[] =
+    "Allows autofill to fill dynamically changing forms";
+
 const char kAutofillEnableCompanyNameName[] =
     "Enable Autofill Company Name field";
 const char kAutofillEnableCompanyNameDescription[] =
     "When enabled, Company Name fields will be auto filled";
 
-const char kAutofillDynamicFormsName[] = "Autofill Dynamic Forms";
-const char kAutofillDynamicFormsDescription[] =
-    "Allows autofill to fill dynamically changing forms";
+const char kAutofillEnableToolbarStatusChipName[] =
+    "Move Autofill omnibox icons next to the profile avatar icon";
+const char kAutofillEnableToolbarStatusChipDescription[] =
+    "When enabled, Autofill data related icon will be shown in the status "
+    "chip next to the profile avatar icon in the toolbar.";
 
 const char kAutofillNoLocalSaveOnUploadSuccessName[] =
     "Disable saving local copy of uploaded card when credit card upload "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7177546..5b6a8881 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -93,11 +93,14 @@
 extern const char kAutofillCacheQueryResponsesName[];
 extern const char kAutofillCacheQueryResponsesDescription[];
 
+extern const char kAutofillDynamicFormsName[];
+extern const char kAutofillDynamicFormsDescription[];
+
 extern const char kAutofillEnableCompanyNameName[];
 extern const char kAutofillEnableCompanyNameDescription[];
 
-extern const char kAutofillDynamicFormsName[];
-extern const char kAutofillDynamicFormsDescription[];
+extern const char kAutofillEnableToolbarStatusChipName[];
+extern const char kAutofillEnableToolbarStatusChipDescription[];
 
 // Enforcing restrictions to enable/disable autofill small form support.
 extern const char kAutofillEnforceMinRequiredFieldsForHeuristicsName[];
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js
index d509eb9..e9893ba 100644
--- a/chrome/browser/resources/print_preview/data/destination.js
+++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -178,6 +178,7 @@
   COLOR: 2
 };
 
+// <if expr="chromeos">
 /**
  * Enumeration of duplex modes used by Chromium.
  * This has to coincide with |printing::DuplexModeRestriction| as defined in
@@ -193,15 +194,30 @@
 };
 
 /**
+ * Enumeration of PIN printing modes used by Chromium.
+ * This has to coincide with |printing::PinModeRestriction| as defined in
+ * printing/backend/printing_restrictions.h
+ * @enum {number}
+ */
+print_preview.PinModeRestriction = {
+  NONE: 0,
+  SECURE: 1,
+  UNSECURE: 2
+};
+
+/**
  * Policies affecting a destination.
  * @typedef {{
  *   allowedColorModes: ?print_preview.ColorMode,
  *   allowedDuplexModes: ?print_preview.DuplexModeRestriction,
+ *   allowedPinMode: ?print_preview.PinModeRestriction,
  *   defaultColorMode: ?print_preview.ColorMode,
  *   defaultDuplexMode: ?print_preview.DuplexModeRestriction,
+ *   defaultPinMode: ?print_preview.PinModeRestriction,
  * }}
  */
 print_preview.Policies;
+// </if>
 
 /**
  * @typedef {{id: string,
@@ -571,6 +587,7 @@
       }
     }
 
+    // <if expr="chromeos">
     /**
      * @return {?print_preview.Policies} Print policies affecting the
      *     destination.
@@ -586,6 +603,7 @@
     set policies(policies) {
       this.policies_ = policies;
     }
+    // </if>
 
     /**
      * @return {!print_preview.DestinationConnectionStatus} Connection status
@@ -769,6 +787,7 @@
           null;
     }
 
+    // <if expr="chromeos">
     /**
      * @return {?print_preview.ColorMode} Color mode set by policy.
      */
@@ -789,6 +808,16 @@
     }
 
     /**
+     * @return {?print_preview.PinModeRestriction} Pin mode allowed by policy.
+     */
+    get pinPolicy() {
+      return this.policies && this.policies.allowedPinModes ?
+          this.policies.allowedPinModes :
+          null;
+    }
+    // </if>
+
+    /**
      * @return {boolean} Whether the printer supports both black and white and
      *     color printing.
      */
@@ -808,6 +837,7 @@
       return hasColor && hasMonochrome;
     }
 
+    // <if expr="chromeos">
     /**
      * @return {?print_preview.ColorMode} Value of default color setting given
      *     by policy.
@@ -825,6 +855,15 @@
     }
 
     /**
+     * @return {?print_preview.PinModeRestriction} Value of default pin setting
+     *     given by policy.
+     */
+    get defaultPinPolicy() {
+      return this.policies && this.policies.defaultPinMode;
+    }
+    // </if>
+
+    /**
      * @param {boolean} isColor Whether to use a color printing mode.
      * @return {Object} Selected color option.
      */
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js
index c8d90bc..ecb1461 100644
--- a/chrome/browser/resources/print_preview/new/model.js
+++ b/chrome/browser/resources/print_preview/new/model.js
@@ -25,7 +25,8 @@
  *    isFitToPageEnabled: (boolean | undefined),
  *    isCssBackgroundEnabled: (boolean | undefined),
  *    scaling: (string | undefined),
- *    vendor_options: (Object | undefined)
+ *    vendor_options: (Object | undefined),
+ *    isPinEnabled: (boolean | undefined)
  * }}
  */
 print_preview_new.SerializedSettings;
@@ -92,6 +93,9 @@
   'fitToPage',
   'vendorItems',
 ];
+// <if expr="chromeos">
+STICKY_SETTING_NAMES.push('pin');
+// </if>
 
 /**
  * Minimum height of page in microns to allow headers and footers. Should
@@ -119,7 +123,7 @@
       type: Object,
       notify: true,
       value: function() {
-        return {
+        const value = {
           pages: {
             value: [1],
             unavailableValue: [],
@@ -297,6 +301,17 @@
             key: '',
           },
         };
+        // <if expr="chromeos">
+        value.pin = {
+          value: false,
+          unavailableValue: false,
+          valid: true,
+          available: true,
+          setByPolicy: false,
+          key: 'isPinEnabled',
+        };
+        // </if>
+        return value;
       },
     },
 
@@ -348,6 +363,7 @@
         'settings.scaling.value, settings.duplex.value, ' +
         'settings.headerFooter.value, settings.cssBackground.value, ' +
         'settings.vendorItems.value)',
+    'stickySettingsChanged_(settings.pin.value)',
   ],
 
   /** @private {boolean} */
@@ -415,6 +431,11 @@
     this.set(
         'settings.vendorItems.available', !!caps && !!caps.vendor_capability);
 
+    // <if expr="chromeos">
+    this.set(
+        'settings.pin.available', !!caps && !!caps.pin && !!caps.pin.supported);
+    // </if>
+
     if (this.documentSettings) {
       this.updateSettingsAvailabilityFromDestinationAndDocumentSettings_();
     }
@@ -806,6 +827,15 @@
           duplexValue != print_preview.DuplexModeRestriction.SIMPLEX);
     }
     this.set('settings.duplex.setByPolicy', !!duplexPolicy);
+
+    const pinPolicy = this.destination.pinPolicy;
+    const pinValue = pinPolicy ? pinPolicy : this.destination.defaultPinPolicy;
+    if (pinValue) {
+      this.set(
+          'settings.pin.value',
+          pinValue == print_preview.PinModeRestriction.SECURE);
+    }
+    this.set('settings.pin.setByPolicy', !!pinPolicy);
     this.updateManaged_();
   },
   // </if>
@@ -814,7 +844,7 @@
   updateManaged_: function() {
     let managedSettings = ['headerFooter'];
     // <if expr="chromeos">
-    managedSettings = managedSettings.concat(['color', 'duplex']);
+    managedSettings = managedSettings.concat(['color', 'duplex', 'pin']);
     // </if>
     this.controlsManaged = managedSettings.some(settingName => {
       const setting = this.getSetting(settingName);
diff --git a/chrome/browser/resources/print_preview/new/settings_behavior.js b/chrome/browser/resources/print_preview/new/settings_behavior.js
index 5935aa4..7e1784e 100644
--- a/chrome/browser/resources/print_preview/new/settings_behavior.js
+++ b/chrome/browser/resources/print_preview/new/settings_behavior.js
@@ -39,6 +39,7 @@
  *   otherOptions: !print_preview_new.Setting,
  *   ranges: !print_preview_new.Setting,
  *   pagesPerSheet: !print_preview_new.Setting,
+ *   pin: (print_preview_new.Setting|undefined),
  * }}
  */
 print_preview_new.Settings;
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
index 7be4a91..a8886059 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
@@ -297,6 +297,13 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
+void SpellcheckCustomDictionary::WaitUntilReadyToSync(base::OnceClosure done) {
+  if (is_loaded_)
+    std::move(done).Run();
+  else
+    wait_until_ready_to_sync_cb_ = std::move(done);
+}
+
 syncer::SyncMergeResult SpellcheckCustomDictionary::MergeDataAndStartSyncing(
     syncer::ModelType type,
     const syncer::SyncDataList& initial_sync_data,
@@ -436,6 +443,8 @@
   Apply(dictionary_change);
   Sync(dictionary_change);
   is_loaded_ = true;
+  if (wait_until_ready_to_sync_cb_)
+    std::move(wait_until_ready_to_sync_cb_).Run();
   for (Observer& observer : observers_)
     observer.OnCustomDictionaryLoaded();
   if (!result->is_valid_file) {
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary.h b/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
index 24cb54d..e3ba992 100644
--- a/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
+++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
@@ -147,6 +147,7 @@
   void Load() override;
 
   // Overridden from syncer::SyncableService:
+  void WaitUntilReadyToSync(base::OnceClosure done) override;
   syncer::SyncMergeResult MergeDataAndStartSyncing(
       syncer::ModelType type,
       const syncer::SyncDataList& initial_sync_data,
@@ -219,6 +220,8 @@
   // True if the dictionary has been loaded. Otherwise false.
   bool is_loaded_;
 
+  base::OnceClosure wait_until_ready_to_sync_cb_;
+
   // A post-startup task to fix the invalid custom dictionary file.
   base::CancelableOnceClosure fix_invalid_file_;
 
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index 115ba79..b0e37317 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/sync/test/integration/wallet_helper.h"
 #include "chrome/browser/web_data_service_factory.h"
 #include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_metadata.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/payments/payments_customer_data.h"
@@ -36,6 +37,7 @@
 #include "content/public/browser/notification_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
+using autofill::AutofillMetadata;
 using autofill::AutofillProfile;
 using autofill::CreditCard;
 using autofill::data_util::TruncateUTF8;
@@ -52,6 +54,8 @@
 using wallet_helper::GetDefaultCreditCard;
 using wallet_helper::GetPersonalDataManager;
 using wallet_helper::GetProfileWebDataService;
+using wallet_helper::GetServerAddressesMetadata;
+using wallet_helper::GetServerCardsMetadata;
 using wallet_helper::GetWalletDataModelTypeState;
 using wallet_helper::kDefaultBillingAddressID;
 using wallet_helper::kDefaultCardID;
@@ -416,18 +420,25 @@
                                   CreateDefaultSyncPaymentsCustomerData()});
   ASSERT_TRUE(SetupSync());
 
-  // Make sure the data is in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  EXPECT_EQ(1uL, pdm->GetCreditCards().size());
-  EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
 
-  // Turn off sync, the data should be gone.
+  // Make sure the data & metadata is in the DB.
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
+  ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
+
+  // Disable sync, the data & metadata should be gone.
   GetSyncService(0)->StopAndClear();
   WaitForNumberOfCards(pdm, 0);
 
+  EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(0uL, pdm->GetCreditCards().size());
   EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
 
   // Turn sync on again, the data should come back.
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
@@ -437,8 +448,11 @@
   // Wait until Sync restores the card and it arrives at PDM.
   WaitForNumberOfCards(pdm, 1);
 
+  EXPECT_EQ(1uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(1uL, pdm->GetCreditCards().size());
   EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  EXPECT_EQ(1U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(1U, GetServerAddressesMetadata(0).size());
 
   // No histograms for initial sync & for clearing.
   ExpectNoHistogramsForCardsDiff();
@@ -454,26 +468,36 @@
                                   CreateDefaultSyncPaymentsCustomerData()});
   ASSERT_TRUE(SetupSync());
 
-  // Make sure the data is in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  EXPECT_EQ(1uL, pdm->GetCreditCards().size());
-  EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
 
-  // Turn off sync, the card should be gone.
+  // Make sure the data & metadata is in the DB.
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
+  ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
+
+  // Stop sync, the data & metadata should be gone.
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(false);
   WaitForNumberOfCards(pdm, 0);
 
+  EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(0uL, pdm->GetCreditCards().size());
   EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
 
   // Turn sync on again, the data should come back.
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
   // Wait until Sync restores the card and it arrives at PDM.
   WaitForNumberOfCards(pdm, 1);
 
+  EXPECT_EQ(1uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(1uL, pdm->GetCreditCards().size());
   EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  EXPECT_EQ(1U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(1U, GetServerAddressesMetadata(0).size());
 
   // No histograms for initial sync & for clearing.
   ExpectNoHistogramsForCardsDiff();
@@ -490,18 +514,25 @@
                                   CreateDefaultSyncPaymentsCustomerData()});
   ASSERT_TRUE(SetupSync());
 
-  // Make sure the data is in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  EXPECT_EQ(1uL, pdm->GetCreditCards().size());
-  EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
 
-  // Turn off sync, the data should be gone.
+  // Make sure the data & metadata is in the DB.
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
+  ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
+
+  // Signout, the data & metadata should be gone.
   GetClient(0)->SignOutPrimaryAccount();
   WaitForNumberOfCards(pdm, 0);
 
+  EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(0uL, pdm->GetCreditCards().size());
   EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
 
   // No histograms for initial sync & for clearing.
   ExpectNoHistogramsForCardsDiff();
@@ -915,18 +946,25 @@
                                   CreateDefaultSyncPaymentsCustomerData()});
   ASSERT_TRUE(SetupSync());
 
-  // Make sure the data is in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  EXPECT_EQ(1uL, pdm->GetCreditCards().size());
-  EXPECT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
 
-  // Turn off autofill sync, the data should be gone.
+  // Make sure the data & metadata is in the DB.
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
+  ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
+
+  // Turn off autofill sync, the data & metadata should be gone.
   ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL));
   WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
 
+  EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(0uL, pdm->GetCreditCards().size());
   EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
 
   // No histograms for initial sync & for clearing.
   ExpectNoHistogramsForCardsDiff();
@@ -942,16 +980,27 @@
                                   CreateDefaultSyncPaymentsCustomerData()});
   ASSERT_TRUE(SetupSync());
 
-  // Make sure the card and PaymentsCustomerData are in the DB.
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   ASSERT_NE(nullptr, pdm);
-  EXPECT_EQ(1uL, pdm->GetCreditCards().size());
 
-  // Turn off the wallet autofill pref, the card should be gone as a side
-  // effect of the wallet data type controller noticing.
+  // Make sure the data & metadata is in the DB.
+  ASSERT_EQ(1uL, pdm->GetServerProfiles().size());
+  ASSERT_EQ(1uL, pdm->GetCreditCards().size());
+  ASSERT_EQ(kDefaultCustomerID, pdm->GetPaymentsCustomerData()->customer_id);
+  ASSERT_EQ(1U, GetServerCardsMetadata(0).size());
+  ASSERT_EQ(1U, GetServerAddressesMetadata(0).size());
+
+  // Turn off the wallet autofill pref, the data & metadata should be gone as a
+  // side effect of the wallet model type controller noticing.
   autofill::prefs::SetPaymentsIntegrationEnabled(GetProfile(0)->GetPrefs(),
                                                  false);
+  WaitForOnPersonalDataChanged(/*should_trigger_refresh=*/false, pdm);
+
+  EXPECT_EQ(0uL, pdm->GetServerProfiles().size());
   EXPECT_EQ(0uL, pdm->GetCreditCards().size());
+  EXPECT_EQ(nullptr, pdm->GetPaymentsCustomerData());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
 
   // No histograms for initial sync & for clearing.
   ExpectNoHistogramsForCardsDiff();
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
index 7c52cf7..7710d78f 100644
--- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -91,6 +91,8 @@
                        PersonalDataManagerSanity) {
   ASSERT_TRUE(SetupSync());
 
+  base::HistogramTester histograms;
+
   // Client0 adds a profile.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
@@ -123,6 +125,15 @@
   RemoveProfile(1, GetAllAutoFillProfiles(1)[0]->guid());
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(0U, GetAllAutoFillProfiles(0).size());
+
+  // Client1 adds a final new profile.
+  AddProfile(1, CreateAutofillProfile(PROFILE_FRASIER));
+  EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
+  EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
+
+  // Each of the clients deletes one profile.
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 2);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
@@ -160,17 +171,24 @@
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddDuplicateProfiles) {
   ASSERT_TRUE(SetupClients());
+  // TODO(crbug.com/904390): Once the investigation is over, remove the
+  // histogram checks for zero LOCAL_DELETIONS here and in all further tests.
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   ASSERT_TRUE(SetupSync());
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        SameProfileWithConflict) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   AutofillProfile profile0 = CreateAutofillProfile(PROFILE_HOMER);
   AutofillProfile profile1 = CreateAutofillProfile(PROFILE_HOMER);
@@ -182,11 +200,15 @@
   ASSERT_TRUE(SetupSync());
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        AddDuplicateProfiles_OneIsVerified) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   // Create two identical profiles where one of them is verified, additionally.
   AutofillProfile profile0 = autofill::test::GetFullProfile();
@@ -202,12 +224,16 @@
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
   EXPECT_EQ(verified_origin, GetAllAutoFillProfiles(0)[0]->origin());
   EXPECT_EQ(verified_origin, GetAllAutoFillProfiles(1)[0]->origin());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 IN_PROC_BROWSER_TEST_P(
     TwoClientAutofillProfileSyncTest,
     AddDuplicateProfiles_OneIsVerified_NonverifiedComesLater) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   AutofillProfile profile0 = autofill::test::GetFullProfile();
   AutofillProfile profile1 =
@@ -234,6 +260,9 @@
 
   EXPECT_EQ(verified_origin, GetAllAutoFillProfiles(0)[0]->origin());
   EXPECT_EQ(verified_origin, GetAllAutoFillProfiles(1)[0]->origin());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that a null profile does not get synced across clients.
@@ -249,6 +278,7 @@
 // other client when sync is running.
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddProfile) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
 
@@ -258,6 +288,9 @@
   // Make sure that both clients have one profile.
   EXPECT_EQ(1U, GetProfileCount(0));
   EXPECT_EQ(1U, GetProfileCount(1));
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that adding a profile on one client results in it being added on the
@@ -265,6 +298,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        AddProfile_BeforeSyncStart) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed";
+  base::HistogramTester histograms;
 
   // Add the new autofill profile before starting sync.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
@@ -276,6 +310,9 @@
   // Make sure that both clients have one profile.
   EXPECT_EQ(1U, GetProfileCount(0));
   EXPECT_EQ(1U, GetProfileCount(1));
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that adding the same profile on the two clients before sync is started
@@ -283,6 +320,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        ClientsAddSameProfile) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed";
+  base::HistogramTester histograms;
 
   // Add the same profile in the two clients.
   AddProfile(0, CreateUniqueAutofillProfile());
@@ -303,6 +341,9 @@
   // Make sure that they have the same GUID.
   EXPECT_EQ(GetAllAutoFillProfiles(0)[0]->guid(),
             GetAllAutoFillProfiles(1)[0]->guid());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that adding multiple profiles to one client results in all of them
@@ -310,6 +351,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        AddMultipleProfilesOnOneClient) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   AddProfile(0, CreateAutofillProfile(PROFILE_MARION));
@@ -317,6 +359,9 @@
   ASSERT_TRUE(SetupSync());
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(3U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that adding multiple profiles to two client results both clients having
@@ -324,6 +369,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        AddMultipleProfilesOnTwoClients) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   AddProfile(1, CreateAutofillProfile(PROFILE_MARION));
@@ -331,12 +377,16 @@
   ASSERT_TRUE(SetupSync());
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(3U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that deleting a profile on one client results in it being deleted on
 // the other client.
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, DeleteProfile) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   // Setup the test by making the 2 clients have the same profile.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
@@ -349,12 +399,16 @@
 
   // Make sure both clients don't have any profiles.
   EXPECT_EQ(0U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 1);
 }
 
 // Tests that modifying a profile while syncing results in the other client
 // getting the updated profile.
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, UpdateFields) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
@@ -379,6 +433,9 @@
   EXPECT_EQ(new_email,
             base::UTF16ToUTF8(GetAllAutoFillProfiles(1)[0]->GetRawInfo(
                 autofill::EMAIL_ADDRESS)));
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that modifying a profile at the same time one two clients while
@@ -387,6 +444,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        UpdateConflictingFields) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   // Make the two clients have the same profile.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
@@ -404,6 +462,9 @@
   // Don't care which write wins the conflict, only that the two clients agree.
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that modifying a profile at the same time one two clients while
@@ -412,6 +473,7 @@
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        UpdateConflictingFieldsDuringInitialMerge) {
   ASSERT_TRUE(SetupClients());
+  base::HistogramTester histograms;
 
   // Make the two clients have the same profile.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
@@ -429,6 +491,9 @@
   // Don't care which write wins the conflict, only that the two clients agree.
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Tests that modifying a profile at the same time on two clients while
@@ -436,6 +501,7 @@
 // one).
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, DeleteAndUpdate) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   // Make the two clients have the same profile.
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
@@ -450,6 +516,9 @@
   // The exact result is non-deterministic without a strong consistency model
   // server-side, but both clients should converge (either update or delete).
   EXPECT_EQ(GetAllAutoFillProfiles(0).size(), GetAllAutoFillProfiles(1).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 1);
 }
 
 // Tests that modifying a profile at the same time on two clients while
@@ -468,6 +537,7 @@
   }
 
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
   GetFakeServer()->EnableStrongConsistencyWithConflictDetectionModel();
 
   // Make the two clients have the same profile.
@@ -486,10 +556,14 @@
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size());
   EXPECT_EQ(1U, GetAllAutoFillProfiles(1).size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 1);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, MaxLength) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait());
@@ -510,10 +584,14 @@
                 max_length_string);
 
   EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, ExceedsMaxLength) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   AddProfile(0, CreateAutofillProfile(PROFILE_HOMER));
   ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait());
@@ -540,11 +618,15 @@
 
   ASSERT_TRUE(AwaitQuiescence());
   EXPECT_FALSE(ProfilesMatch(0, 1));
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Test credit cards don't sync.
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, NoCreditCardSync) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   CreditCard card;
   card.SetRawInfo(autofill::CREDIT_CARD_NUMBER,
@@ -563,11 +645,15 @@
 
   PersonalDataManager* pdm = GetPersonalDataManager(1);
   EXPECT_EQ(0U, pdm->GetCreditCards().size());
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest,
                        E2E_ONLY(TwoClientsAddAutofillProfiles)) {
   ASSERT_TRUE(SetupSync());
+  base::HistogramTester histograms;
 
   // All profiles should sync same autofill profiles.
   ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait())
@@ -588,6 +674,9 @@
     EXPECT_EQ(GetProfileCount(i), init_autofill_profiles_count + 1U)
         << "Total autofill profile count is wrong.";
   }
+
+  histograms.ExpectBucketCount("Sync.ModelTypeEntityChange3.AUTOFILL_PROFILE",
+                               LOCAL_DELETION, 0);
 }
 
 // Only parametrize the tests above that test autofill_profile, the tests below
diff --git a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc
index ae4fc635..313bd7a 100644
--- a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc
@@ -607,22 +607,14 @@
   EXPECT_EQ(0U, GetServerCreditCards(1).size());
 
   // Also check the DB directly that there is no _metadata_.
-  std::map<std::string, AutofillMetadata> cards_metadata_0;
-  GetServerCardsMetadata(0, &cards_metadata_0);
-  EXPECT_EQ(0U, cards_metadata_0.size());
-  std::map<std::string, AutofillMetadata> cards_metadata_1;
-  GetServerCardsMetadata(1, &cards_metadata_1);
-  EXPECT_EQ(0U, cards_metadata_1.size());
+  EXPECT_EQ(0U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(0U, GetServerCardsMetadata(1).size());
 
-  // Double check that cards data & metadata is intact.
+  // Double check that profiles data & metadata is intact.
   EXPECT_EQ(1U, GetServerProfiles(0).size());
   EXPECT_EQ(1U, GetServerProfiles(1).size());
-  std::map<std::string, AutofillMetadata> addresses_metadata_0;
-  GetServerAddressesMetadata(0, &addresses_metadata_0);
-  EXPECT_EQ(1U, addresses_metadata_0.size());
-  std::map<std::string, AutofillMetadata> addresses_metadata_1;
-  GetServerAddressesMetadata(1, &addresses_metadata_1);
-  EXPECT_EQ(1U, addresses_metadata_1.size());
+  EXPECT_EQ(1U, GetServerAddressesMetadata(0).size());
+  EXPECT_EQ(1U, GetServerAddressesMetadata(1).size());
 }
 
 IN_PROC_BROWSER_TEST_P(TwoClientWalletSyncTest,
@@ -664,22 +656,14 @@
   EXPECT_EQ(0U, GetServerProfiles(1).size());
 
   // Also check the DB directly that there is no _metadata_.
-  std::map<std::string, AutofillMetadata> addresses_metadata_0;
-  GetServerAddressesMetadata(0, &addresses_metadata_0);
-  EXPECT_EQ(0U, addresses_metadata_0.size());
-  std::map<std::string, AutofillMetadata> addresses_metadata_1;
-  GetServerAddressesMetadata(1, &addresses_metadata_1);
-  EXPECT_EQ(0U, addresses_metadata_1.size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(0).size());
+  EXPECT_EQ(0U, GetServerAddressesMetadata(1).size());
 
   // Double check that cards data & metadata is intact.
   EXPECT_EQ(1U, GetServerCreditCards(0).size());
   EXPECT_EQ(1U, GetServerCreditCards(1).size());
-  std::map<std::string, AutofillMetadata> cards_metadata_0;
-  GetServerCardsMetadata(0, &cards_metadata_0);
-  EXPECT_EQ(1U, cards_metadata_0.size());
-  std::map<std::string, AutofillMetadata> cards_metadata_1;
-  GetServerCardsMetadata(1, &cards_metadata_1);
-  EXPECT_EQ(1U, cards_metadata_1.size());
+  EXPECT_EQ(1U, GetServerCardsMetadata(0).size());
+  EXPECT_EQ(1U, GetServerCardsMetadata(1).size());
 }
 
 INSTANTIATE_TEST_SUITE_P(USS,
diff --git a/chrome/browser/sync/test/integration/wallet_helper.cc b/chrome/browser/sync/test/integration/wallet_helper.cc
index 7955665a..c7c83aab 100644
--- a/chrome/browser/sync/test/integration/wallet_helper.cc
+++ b/chrome/browser/sync/test/integration/wallet_helper.cc
@@ -6,9 +6,6 @@
 
 #include <stddef.h>
 
-#include <map>
-#include <utility>
-
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -276,25 +273,26 @@
   WaitForCurrentTasksToComplete(wds->GetDBTaskRunner());
 }
 
-void GetServerCardsMetadata(
-    int profile,
-    std::map<std::string, AutofillMetadata>* cards_metadata) {
+std::map<std::string, AutofillMetadata> GetServerCardsMetadata(int profile) {
+  std::map<std::string, AutofillMetadata> cards_metadata;
   scoped_refptr<AutofillWebDataService> wds = GetProfileWebDataService(profile);
   wds->GetDBTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&GetServerCardsMetadataOnDBSequence,
-                                base::Unretained(wds.get()), cards_metadata));
+                                base::Unretained(wds.get()), &cards_metadata));
   WaitForCurrentTasksToComplete(wds->GetDBTaskRunner());
+  return cards_metadata;
 }
 
-void GetServerAddressesMetadata(
-    int profile,
-    std::map<std::string, AutofillMetadata>* addresses_metadata) {
+std::map<std::string, AutofillMetadata> GetServerAddressesMetadata(
+    int profile) {
+  std::map<std::string, AutofillMetadata> addresses_metadata;
   scoped_refptr<AutofillWebDataService> wds = GetProfileWebDataService(profile);
   wds->GetDBTaskRunner()->PostTask(
       FROM_HERE,
       base::BindOnce(&GetServerAddressesMetadataOnDBSequence,
-                     base::Unretained(wds.get()), addresses_metadata));
+                     base::Unretained(wds.get()), &addresses_metadata));
   WaitForCurrentTasksToComplete(wds->GetDBTaskRunner());
+  return addresses_metadata;
 }
 
 sync_pb::ModelTypeState GetWalletDataModelTypeState(int profile) {
@@ -548,19 +546,20 @@
 bool AutofillWalletMetadataSizeChecker::IsExitConditionSatisfied() {
   // There could be trailing metadata left on one of the clients. Check that
   // metadata.size() is the same on both clients.
-  std::map<std::string, AutofillMetadata> addresses_metadata_a,
-      addresses_metadata_b;
-  wallet_helper::GetServerAddressesMetadata(profile_a_, &addresses_metadata_a);
-  wallet_helper::GetServerAddressesMetadata(profile_b_, &addresses_metadata_b);
+  std::map<std::string, AutofillMetadata> addresses_metadata_a =
+      wallet_helper::GetServerAddressesMetadata(profile_a_);
+  std::map<std::string, AutofillMetadata> addresses_metadata_b =
+      wallet_helper::GetServerAddressesMetadata(profile_b_);
   if (addresses_metadata_a.size() != addresses_metadata_b.size()) {
     LOG(WARNING) << "Server addresses metadata mismatch, expected "
                  << addresses_metadata_a.size()
                  << ", found: " << addresses_metadata_b.size();
     return false;
   }
-  std::map<std::string, AutofillMetadata> cards_metadata_a, cards_metadata_b;
-  wallet_helper::GetServerCardsMetadata(profile_a_, &cards_metadata_a);
-  wallet_helper::GetServerCardsMetadata(profile_b_, &cards_metadata_b);
+  std::map<std::string, AutofillMetadata> cards_metadata_a =
+      wallet_helper::GetServerCardsMetadata(profile_a_);
+  std::map<std::string, AutofillMetadata> cards_metadata_b =
+      wallet_helper::GetServerCardsMetadata(profile_b_);
   if (cards_metadata_a.size() != cards_metadata_b.size()) {
     LOG(WARNING) << "Server cards metadata mismatch, expected "
                  << cards_metadata_a.size() << ", found "
diff --git a/chrome/browser/sync/test/integration/wallet_helper.h b/chrome/browser/sync/test/integration/wallet_helper.h
index 6b9716ef..7b7d8e6 100644
--- a/chrome/browser/sync/test/integration/wallet_helper.h
+++ b/chrome/browser/sync/test/integration/wallet_helper.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_WALLET_HELPER_H_
 #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_WALLET_HELPER_H_
 
+#include <map>
 #include <utility>
 #include <vector>
 
@@ -65,13 +66,11 @@
     int profile,
     const autofill::AutofillProfile& server_address);
 
-void GetServerCardsMetadata(
-    int profile,
-    std::map<std::string, autofill::AutofillMetadata>* cards_metadata);
+std::map<std::string, autofill::AutofillMetadata> GetServerCardsMetadata(
+    int profile);
 
-void GetServerAddressesMetadata(
-    int profile,
-    std::map<std::string, autofill::AutofillMetadata>* addresses_metadata);
+std::map<std::string, autofill::AutofillMetadata> GetServerAddressesMetadata(
+    int profile);
 
 sync_pb::ModelTypeState GetWalletDataModelTypeState(int profile);
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 5a14a50..48db711 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -54,6 +54,8 @@
     "autofill/autofill_popup_layout_model.h",
     "autofill/autofill_popup_view.h",
     "autofill/autofill_popup_view_delegate.h",
+    "autofill/autofill_ui_util.cc",
+    "autofill/autofill_ui_util.h",
     "autofill/chrome_autofill_client.cc",
     "autofill/chrome_autofill_client.h",
     "autofill/create_card_unmask_prompt_view.h",
@@ -426,6 +428,7 @@
     "//components/heap_profiling",
     "//components/history/content/browser",
     "//components/history/core/browser",
+    "//components/history/core/common",
     "//components/image_fetcher/core",
     "//components/infobars/core",
     "//components/invalidation/impl",
@@ -1053,6 +1056,12 @@
       "task_manager/task_manager_columns.h",
       "task_manager/task_manager_table_model.cc",
       "task_manager/task_manager_table_model.h",
+      "thumbnails/thumbnail_tab_helper.cc",
+      "thumbnails/thumbnail_tab_helper.h",
+      "thumbnails/thumbnail_utils.cc",
+      "thumbnails/thumbnail_utils.h",
+      "thumbnails/thumbnailing_context.cc",
+      "thumbnails/thumbnailing_context.h",
       "toolbar/app_menu_icon_controller.cc",
       "toolbar/app_menu_icon_controller.h",
       "toolbar/app_menu_model.cc",
@@ -2847,8 +2856,12 @@
       "views/toolbar/toolbar_actions_bar_bubble_views.h",
       "views/toolbar/toolbar_button.cc",
       "views/toolbar/toolbar_button.h",
+      "views/toolbar/toolbar_icon_container_view.cc",
+      "views/toolbar/toolbar_icon_container_view.h",
       "views/toolbar/toolbar_ink_drop_util.cc",
       "views/toolbar/toolbar_ink_drop_util.h",
+      "views/toolbar/toolbar_page_action_icon_container_view.cc",
+      "views/toolbar/toolbar_page_action_icon_container_view.h",
       "views/toolbar/toolbar_view.cc",
       "views/toolbar/toolbar_view.h",
       "views/touch_uma/touch_uma.cc",
diff --git a/chrome/browser/ui/app_icon_loader.cc b/chrome/browser/ui/app_icon_loader.cc
index ff657ac..58f18c1 100644
--- a/chrome/browser/ui/app_icon_loader.cc
+++ b/chrome/browser/ui/app_icon_loader.cc
@@ -7,8 +7,10 @@
 AppIconLoader::AppIconLoader() {}
 
 AppIconLoader::AppIconLoader(Profile* profile,
-                             int icon_size,
+                             int icon_size_in_dip,
                              AppIconLoaderDelegate* delegate)
-    : profile_(profile), icon_size_(icon_size), delegate_(delegate) {}
+    : profile_(profile),
+      icon_size_in_dip_(icon_size_in_dip),
+      delegate_(delegate) {}
 
 AppIconLoader::~AppIconLoader() {}
diff --git a/chrome/browser/ui/app_icon_loader.h b/chrome/browser/ui/app_icon_loader.h
index 57b7453..ea47cae0 100644
--- a/chrome/browser/ui/app_icon_loader.h
+++ b/chrome/browser/ui/app_icon_loader.h
@@ -38,16 +38,16 @@
  protected:
   AppIconLoader();
   AppIconLoader(Profile* profile,
-                int icon_size,
+                int icon_size_in_dip,
                 AppIconLoaderDelegate* delegate);
 
   Profile* profile() { return profile_; }
-  int icon_size() const { return icon_size_; }
+  int icon_size_in_dip() const { return icon_size_in_dip_; }
   AppIconLoaderDelegate* delegate() { return delegate_; }
 
  private:
   Profile* const profile_ = nullptr;
-  const int icon_size_ = 0;
+  const int icon_size_in_dip_ = 0;
 
   // The delegate object which receives the icon images. No ownership.
   AppIconLoaderDelegate* const delegate_ = nullptr;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc
index 1388c44..7514911 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc
@@ -10,9 +10,9 @@
 #include "ui/gfx/image/image_skia_operations.h"
 
 ArcAppIconLoader::ArcAppIconLoader(Profile* profile,
-                                   int icon_size,
+                                   int icon_size_in_dip,
                                    AppIconLoaderDelegate* delegate)
-    : AppIconLoader(profile, icon_size, delegate),
+    : AppIconLoader(profile, icon_size_in_dip, delegate),
       arc_prefs_(ArcAppListPrefs::Get(profile)) {
   DCHECK(arc_prefs_);
   arc_prefs_->AddObserver(this);
@@ -32,10 +32,10 @@
   if (icon_map_.find(app_id) != icon_map_.end())
     return;  // Already loading the image.
 
-  // Note, ARC icon is available only for 48x48 dips. In case |icon_size_|
-  // differs from this size, re-scale is required.
+  // Note, ARC icon is available only for 48x48 dips. In case
+  // |icon_size_in_dip_| differs from this size, re-scale is required.
   std::unique_ptr<ArcAppIcon> icon =
-      std::make_unique<ArcAppIcon>(profile(), app_id, icon_size(), this);
+      std::make_unique<ArcAppIcon>(profile(), app_id, icon_size_in_dip(), this);
   icon->image_skia().EnsureRepsForSupportedScales();
   icon_map_[app_id] = std::move(icon);
   UpdateImage(app_id);
@@ -51,8 +51,8 @@
     return;
 
   gfx::ImageSkia image = it->second->image_skia();
-  DCHECK_EQ(icon_size(), image.width());
-  DCHECK_EQ(icon_size(), image.height());
+  DCHECK_EQ(icon_size_in_dip(), image.width());
+  DCHECK_EQ(icon_size_in_dip(), image.height());
 
   std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
       arc_prefs_->GetApp(app_id);
@@ -81,7 +81,7 @@
 void ArcAppIconLoader::OnAppIconUpdated(
     const std::string& app_id,
     const ArcAppIconDescriptor& descriptor) {
-  if (descriptor.dip_size != icon_size())
+  if (descriptor.dip_size != icon_size_in_dip())
     return;
   AppIDToIconMap::const_iterator it = icon_map_.find(app_id);
   if (it == icon_map_.end())
diff --git a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h
index 0d0cd9f..f87a3ef 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h
@@ -23,7 +23,7 @@
                          public ArcAppIcon::Observer {
  public:
   ArcAppIconLoader(Profile* profile,
-                   int icon_size,
+                   int icon_size_in_dip,
                    AppIconLoaderDelegate* delegate);
   ~ArcAppIconLoader() override;
 
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc b/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc
index 0411c72..c554f2f8 100644
--- a/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc
+++ b/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc
@@ -35,8 +35,8 @@
   if (icon_map_.find(app_id) != icon_map_.end())
     return;
 
-  std::unique_ptr<CrostiniAppIcon> icon =
-      std::make_unique<CrostiniAppIcon>(profile(), app_id, icon_size(), this);
+  std::unique_ptr<CrostiniAppIcon> icon = std::make_unique<CrostiniAppIcon>(
+      profile(), app_id, icon_size_in_dip(), this);
   icon->image_skia().EnsureRepsForSupportedScales();
   icon_map_[app_id] = std::move(icon);
   UpdateImage(app_id);
diff --git a/chrome/browser/ui/autofill/autofill_ui_util.cc b/chrome/browser/ui/autofill/autofill_ui_util.cc
new file mode 100644
index 0000000..8bcc5c35
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_ui_util.cc
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/autofill_ui_util.h"
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/location_bar/location_bar.h"
+#include "chrome/browser/ui/page_action/page_action_icon_container.h"
+#include "components/autofill/core/common/autofill_features.h"
+
+namespace autofill {
+
+void UpdateLocalCardMigrationIcon(content::WebContents* web_contents) {
+#if !defined(OS_ANDROID)
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+  if (!browser)
+    return;
+
+  // If feature is enabled, icon will be in the
+  // ToolbarPageActionIconContainerView.
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableToolbarStatusChip)) {
+    PageActionIconContainer* toolbar_page_action_container =
+        browser->window()->GetToolbarPageActionIconContainer();
+    if (!toolbar_page_action_container)
+      return;
+
+    toolbar_page_action_container->UpdatePageActionIcon(
+        PageActionIconType::kLocalCardMigration);
+  } else {
+    // Otherwise the icon will be in the LocationBar.
+    LocationBar* location_bar = browser->window()->GetLocationBar();
+    if (!location_bar)
+      return;
+
+    location_bar->UpdateLocalCardMigrationIcon();
+  }
+#endif
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_ui_util.h b/chrome/browser/ui/autofill/autofill_ui_util.h
new file mode 100644
index 0000000..9f3c054d
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_ui_util.h
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_UI_UTIL_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_UI_UTIL_H_
+
+#include "content/public/browser/web_contents.h"
+
+namespace autofill {
+
+// TODO(crbug.com/932818): Clean this up and move the logic to
+// ToolbarPageActionContainerView once the status chip is fully
+// launched.
+
+// Update the state of local card migration icon view.
+void UpdateLocalCardMigrationIcon(content::WebContents* web_contents);
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_UI_UTIL_H_
diff --git a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
index 46730f63..2e14924 100644
--- a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
@@ -8,12 +8,12 @@
 
 #include "chrome/browser/autofill/strike_database_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/autofill_ui_util.h"
 #include "chrome/browser/ui/autofill/local_card_migration_bubble.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/location_bar/location_bar.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/local_card_migration_strike_database.h"
 #include "components/autofill/core/browser/payments/strike_database.h"
@@ -100,11 +100,9 @@
 
 void LocalCardMigrationBubbleControllerImpl::OnBubbleClosed() {
   local_card_migration_bubble_ = nullptr;
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   if (should_add_strikes_on_bubble_close_ &&
       base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2) &&
-      base::FeatureList::IsEnabled(
           features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
     should_add_strikes_on_bubble_close_ = false;
     AddStrikesForBubbleClose();
@@ -143,7 +141,7 @@
     local_card_migration_bubble_->Hide();
     OnBubbleClosed();
   } else {
-    UpdateIcon();
+    UpdateLocalCardMigrationIcon(web_contents());
   }
 
   AutofillMetrics::LogLocalCardMigrationBubbleUserInteractionMetric(
@@ -169,32 +167,22 @@
   DCHECK(local_card_migration_bubble_closure_);
   DCHECK(!local_card_migration_bubble_);
 
-  // Need to create location bar icon before bubble, otherwise bubble will be
-  // unanchored.
-  UpdateIcon();
+  // Update the visibility and toggled state of the credit card icon in either
+  // Location bar or in Status Chip.
+  UpdateLocalCardMigrationIcon(web_contents());
 
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
   local_card_migration_bubble_ =
       browser->window()->ShowLocalCardMigrationBubble(web_contents(), this,
                                                       is_reshow_);
   DCHECK(local_card_migration_bubble_);
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   timer_.reset(new base::ElapsedTimer());
 
   AutofillMetrics::LogLocalCardMigrationBubbleOfferMetric(
       AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, is_reshow_);
 }
 
-void LocalCardMigrationBubbleControllerImpl::UpdateIcon() {
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-  if (!browser)
-    return;
-  LocationBar* location_bar = browser->window()->GetLocationBar();
-  if (!location_bar)
-    return;
-  location_bar->UpdateLocalCardMigrationIcon();
-}
-
 void LocalCardMigrationBubbleControllerImpl::AddStrikesForBubbleClose() {
   LocalCardMigrationStrikeDatabase local_card_migration_strike_database(
       StrikeDatabaseFactory::GetForProfile(
diff --git a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
index 42df8e8..c531971 100644
--- a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
@@ -69,9 +69,6 @@
 
   void ShowBubbleImplementation();
 
-  // Update the visibility and toggled state of the Omnibox save card icon.
-  void UpdateIcon();
-
   // Add strikes for local card migration, to be called on user closing the
   // promo bubble.
   void AddStrikesForBubbleClose();
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc
index 75f4255..38549bd 100644
--- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc
@@ -16,13 +16,13 @@
 #include "build/build_config.h"
 #include "chrome/browser/autofill/strike_database_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/autofill_ui_util.h"
 #include "chrome/browser/ui/autofill/local_card_migration_dialog.h"
 #include "chrome/browser/ui/autofill/local_card_migration_dialog_factory.h"
 #include "chrome/browser/ui/autofill/local_card_migration_dialog_state.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/location_bar/location_bar.h"
 #include "components/autofill/core/browser/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/local_card_migration_manager.h"
 #include "components/autofill/core/browser/payments/local_card_migration_strike_database.h"
@@ -68,14 +68,14 @@
 
   view_state_ = LocalCardMigrationDialogState::kOffered;
   // Need to create the icon first otherwise the dialog will not be shown.
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   local_card_migration_dialog_ =
       CreateLocalCardMigrationDialogView(this, web_contents());
   start_migrating_cards_callback_ = std::move(start_migrating_cards_callback);
   migratable_credit_cards_ = migratable_credit_cards;
   user_email_ = user_email;
   local_card_migration_dialog_->ShowDialog();
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   dialog_is_visible_duration_timer_ = base::ElapsedTimer();
 
   AutofillMetrics::LogLocalCardMigrationDialogOfferMetric(
@@ -101,7 +101,7 @@
       break;
     }
   }
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
 }
 
 void LocalCardMigrationDialogControllerImpl::ShowFeedbackDialog() {
@@ -111,7 +111,7 @@
   local_card_migration_dialog_ =
       CreateLocalCardMigrationDialogView(this, web_contents());
   local_card_migration_dialog_->ShowDialog();
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   dialog_is_visible_duration_timer_ = base::ElapsedTimer();
 }
 
@@ -121,7 +121,7 @@
 
   local_card_migration_dialog_ =
       CreateLocalCardMigrationErrorDialogView(this, web_contents());
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
   local_card_migration_dialog_->ShowDialog();
   dialog_is_visible_duration_timer_ = base::ElapsedTimer();
 }
@@ -175,8 +175,6 @@
 void LocalCardMigrationDialogControllerImpl::OnCancelButtonClicked() {
   // Add strikes for local card migration due to user closing the main dialog.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2) &&
-      base::FeatureList::IsEnabled(
           features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
     LocalCardMigrationStrikeDatabase local_card_migration_strike_database(
         StrikeDatabaseFactory::GetForProfile(
@@ -244,7 +242,7 @@
   if (local_card_migration_dialog_)
     local_card_migration_dialog_ = nullptr;
 
-  UpdateIcon();
+  UpdateLocalCardMigrationIcon(web_contents());
 }
 
 bool LocalCardMigrationDialogControllerImpl::AllCardsInvalid() const {
@@ -274,14 +272,6 @@
       ui::PAGE_TRANSITION_LINK, false));
 }
 
-void LocalCardMigrationDialogControllerImpl::UpdateIcon() {
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-  DCHECK(browser);
-  LocationBar* location_bar = browser->window()->GetLocationBar();
-  DCHECK(location_bar);
-  location_bar->UpdateLocalCardMigrationIcon();
-}
-
 bool LocalCardMigrationDialogControllerImpl::HasFailedCard() const {
   return std::find_if(
              migratable_credit_cards_.begin(), migratable_credit_cards_.end(),
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h
index 6c53370..9f8aa52 100644
--- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h
@@ -86,8 +86,6 @@
 
   void OpenUrl(const GURL& url);
 
-  void UpdateIcon();
-
   // The dialog is showing cards of which the migration failed. We will show
   // the "Almost done" dialog in this case.
   bool HasFailedCard() const;
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 009cf8a1..4cbaca2d 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -234,6 +234,12 @@
   // Returns the container of page action icons.
   virtual PageActionIconContainer* GetPageActionIconContainer() = 0;
 
+  // Returns the container of toolbar page action icons. The page action icon
+  // container above is in the omnibox. The toolbar page action icon container
+  // is in the toolbar which contains user-account-related data icons and the
+  // profile avatar icon.
+  virtual PageActionIconContainer* GetToolbarPageActionIconContainer() = 0;
+
   // Returns the location bar.
   virtual LocationBar* GetLocationBar() const = 0;
 
diff --git a/chrome/browser/ui/page_action/page_action_icon_container.h b/chrome/browser/ui/page_action/page_action_icon_container.h
index 773bb18..7d01f70 100644
--- a/chrome/browser/ui/page_action/page_action_icon_container.h
+++ b/chrome/browser/ui/page_action/page_action_icon_container.h
@@ -9,6 +9,7 @@
   // TODO(https://crbug.com/788051): Migrate page action icon update methods out
   // of LocationBar to this interface.
   kFind,
+  kLocalCardMigration,
   kManagePasswords,
   kPwaInstall,
   kTranslate,
diff --git a/chrome/browser/thumbnails/OWNERS b/chrome/browser/ui/thumbnails/OWNERS
similarity index 100%
rename from chrome/browser/thumbnails/OWNERS
rename to chrome/browser/ui/thumbnails/OWNERS
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
similarity index 97%
rename from chrome/browser/thumbnails/thumbnail_tab_helper.cc
rename to chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
index 72477dcf..56c4fa6 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/thumbnails/thumbnail_tab_helper.h"
+#include "chrome/browser/ui/thumbnails/thumbnail_tab_helper.h"
 
 #include "base/bind.h"
 #include "base/feature_list.h"
@@ -10,7 +10,7 @@
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/thumbnails/thumbnail_utils.h"
+#include "chrome/browser/ui/thumbnails/thumbnail_utils.h"
 #include "chrome/common/chrome_features.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -298,9 +298,9 @@
         FROM_HERE,
         {base::TaskPriority::BEST_EFFORT,
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-        base::Bind(&ComputeThumbnailScore, bitmap, thumbnailing_context_),
-        base::Bind(&ThumbnailTabHelper::StoreThumbnail,
-                   weak_factory_.GetWeakPtr(), bitmap));
+        base::BindOnce(&ComputeThumbnailScore, bitmap, thumbnailing_context_),
+        base::BindOnce(&ThumbnailTabHelper::StoreThumbnail,
+                       weak_factory_.GetWeakPtr(), bitmap));
   } else {
     LogThumbnailingOutcome(
         trigger, was_canceled ? Outcome::CANCELED : Outcome::READBACK_FAILED);
diff --git a/chrome/browser/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
similarity index 93%
rename from chrome/browser/thumbnails/thumbnail_tab_helper.h
rename to chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
index 6619d68..d589d502 100644
--- a/chrome/browser/thumbnails/thumbnail_tab_helper.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
-#define CHROME_BROWSER_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
+#ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
+#define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
-#include "chrome/browser/thumbnails/thumbnailing_context.h"
+#include "chrome/browser/ui/thumbnails/thumbnailing_context.h"
 #include "content/public/browser/render_widget_host_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -118,4 +118,4 @@
   DISALLOW_COPY_AND_ASSIGN(ThumbnailTabHelper);
 };
 
-#endif  // CHROME_BROWSER_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
+#endif  // CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_TAB_HELPER_H_
diff --git a/chrome/browser/thumbnails/thumbnail_utils.cc b/chrome/browser/ui/thumbnails/thumbnail_utils.cc
similarity index 98%
rename from chrome/browser/thumbnails/thumbnail_utils.cc
rename to chrome/browser/ui/thumbnails/thumbnail_utils.cc
index 00bea8d..2c91f596 100644
--- a/chrome/browser/thumbnails/thumbnail_utils.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/thumbnails/thumbnail_utils.h"
+#include "chrome/browser/ui/thumbnails/thumbnail_utils.h"
 
 #include <algorithm>
 
diff --git a/chrome/browser/thumbnails/thumbnail_utils.h b/chrome/browser/ui/thumbnails/thumbnail_utils.h
similarity index 93%
rename from chrome/browser/thumbnails/thumbnail_utils.h
rename to chrome/browser/ui/thumbnails/thumbnail_utils.h
index 5f39954..6435c32 100644
--- a/chrome/browser/thumbnails/thumbnail_utils.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_utils.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 CHROME_BROWSER_THUMBNAILS_THUMBNAIL_UTILS_H_
-#define CHROME_BROWSER_THUMBNAILS_THUMBNAIL_UTILS_H_
+#ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_UTILS_H_
+#define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_UTILS_H_
 
 #include "base/macros.h"
 #include "ui/base/resource/scale_factor.h"
@@ -60,4 +60,4 @@
 
 }  // namespace thumbnails
 
-#endif  // CHROME_BROWSER_THUMBNAILS_THUMBNAIL_UTILS_H_
+#endif  // CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_UTILS_H_
diff --git a/chrome/browser/thumbnails/thumbnail_utils_unittest.cc b/chrome/browser/ui/thumbnails/thumbnail_utils_unittest.cc
similarity index 97%
rename from chrome/browser/thumbnails/thumbnail_utils_unittest.cc
rename to chrome/browser/ui/thumbnails/thumbnail_utils_unittest.cc
index a765a35a..d4536496 100644
--- a/chrome/browser/thumbnails/thumbnail_utils_unittest.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_utils_unittest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/thumbnails/thumbnail_utils.h"
+#include "chrome/browser/ui/thumbnails/thumbnail_utils.h"
 
-#include "chrome/browser/thumbnails/thumbnailing_context.h"
+#include "chrome/browser/ui/thumbnails/thumbnailing_context.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/test/mock_render_process_host.h"
diff --git a/chrome/browser/thumbnails/thumbnailing_context.cc b/chrome/browser/ui/thumbnails/thumbnailing_context.cc
similarity index 89%
rename from chrome/browser/thumbnails/thumbnailing_context.cc
rename to chrome/browser/ui/thumbnails/thumbnailing_context.cc
index 606d22c..dbb3932 100644
--- a/chrome/browser/thumbnails/thumbnailing_context.cc
+++ b/chrome/browser/ui/thumbnails/thumbnailing_context.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/thumbnails/thumbnailing_context.h"
+#include "chrome/browser/ui/thumbnails/thumbnailing_context.h"
 
 namespace thumbnails {
 
diff --git a/chrome/browser/thumbnails/thumbnailing_context.h b/chrome/browser/ui/thumbnails/thumbnailing_context.h
similarity index 76%
rename from chrome/browser/thumbnails/thumbnailing_context.h
rename to chrome/browser/ui/thumbnails/thumbnailing_context.h
index 5a127182..3be4a12 100644
--- a/chrome/browser/thumbnails/thumbnailing_context.h
+++ b/chrome/browser/ui/thumbnails/thumbnailing_context.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_THUMBNAILS_THUMBNAILING_CONTEXT_H_
-#define CHROME_BROWSER_THUMBNAILS_THUMBNAILING_CONTEXT_H_
+#ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAILING_CONTEXT_H_
+#define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAILING_CONTEXT_H_
 
 #include "base/memory/ref_counted.h"
-#include "chrome/browser/thumbnails/thumbnail_utils.h"
+#include "chrome/browser/ui/thumbnails/thumbnail_utils.h"
 #include "components/history/core/common/thumbnail_score.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
@@ -30,4 +30,4 @@
 
 }  // namespace thumbnails
 
-#endif  // CHROME_BROWSER_THUMBNAILS_THUMBNAILING_CONTEXT_H_
+#endif  // CHROME_BROWSER_UI_THUMBNAILS_THUMBNAILING_CONTEXT_H_
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
index e364636..fbcff33 100644
--- a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/views/autofill/migratable_card_view.h"
 #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -308,7 +309,7 @@
   }
 
   void ClickOnView(views::View* view) {
-    DCHECK(view);
+    CHECK(view);
     ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
                            ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
                            ui::EF_LEFT_MOUSE_BUTTON);
@@ -323,7 +324,7 @@
   void ClickOnDialogViewAndWait(
       views::View* view,
       views::DialogDelegateView* local_card_migration_view) {
-    DCHECK(local_card_migration_view);
+    CHECK(local_card_migration_view);
     views::test::WidgetDestroyedWaiter destroyed_waiter(
         local_card_migration_view->GetWidget());
     local_card_migration_view->GetDialogClientView()
@@ -341,7 +342,7 @@
   views::View* FindViewInDialogById(
       DialogViewId view_id,
       views::DialogDelegateView* local_card_migration_view) {
-    DCHECK(local_card_migration_view);
+    CHECK(local_card_migration_view);
 
     views::View* specified_view =
         local_card_migration_view->GetViewByID(static_cast<int>(view_id));
@@ -393,20 +394,33 @@
             ->local_card_migration_dialog_view());
   }
 
-  LocalCardMigrationIconView* GetLocalCardMigrationIconView() {
+  LocalCardMigrationIconView* GetLocalCardMigrationIconView(
+      bool icon_in_status_chip) {
+    LocalCardMigrationIconView* icon_view = nullptr;
     if (!browser())
-      return nullptr;
-    LocationBarView* location_bar_view =
-        static_cast<LocationBarView*>(browser()->window()->GetLocationBar());
-    DCHECK(location_bar_view->local_card_migration_icon_view());
-    return location_bar_view->local_card_migration_icon_view();
+      return icon_view;
+
+    if (icon_in_status_chip) {
+      ToolbarPageActionIconContainerView*
+          toolbar_page_action_icon_container_view =
+              static_cast<ToolbarPageActionIconContainerView*>(
+                  browser()->window()->GetToolbarPageActionIconContainer());
+      icon_view = toolbar_page_action_icon_container_view
+                      ->local_card_migration_icon_view();
+    } else {
+      LocationBarView* location_bar_view =
+          static_cast<LocationBarView*>(browser()->window()->GetLocationBar());
+      icon_view = location_bar_view->local_card_migration_icon_view();
+    }
+    CHECK(icon_view);
+    return icon_view;
   }
 
   views::View* GetCloseButton() {
     LocalCardMigrationBubbleViews* local_card_migration_bubble_views =
         static_cast<LocalCardMigrationBubbleViews*>(
             GetLocalCardMigrationOfferBubbleViews());
-    DCHECK(local_card_migration_bubble_views);
+    CHECK(local_card_migration_bubble_views);
     return local_card_migration_bubble_views->GetBubbleFrameView()
         ->GetCloseButtonForTest();
   }
@@ -456,6 +470,26 @@
   DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationBrowserTest);
 };
 
+// TODO(crbug.com/932818): Remove this class after experiment flag is cleaned
+// up. Otherwise we need it because the toolbar is init-ed before each test is
+// set up. Thus need to enable the feature in the general browsertest SetUp().
+class LocalCardMigrationBrowserTestForStatusChip
+    : public LocalCardMigrationBrowserTest {
+ protected:
+  LocalCardMigrationBrowserTestForStatusChip()
+      : LocalCardMigrationBrowserTest() {}
+
+  ~LocalCardMigrationBrowserTestForStatusChip() override {}
+
+  void SetUp() override {
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitAndEnableFeature(
+        features::kAutofillEnableToolbarStatusChip);
+
+    LocalCardMigrationBrowserTest::SetUp();
+  }
+};
+
 // Ensures that migration is not offered when user saves a new card.
 IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                        UsingNewCardDoesNotShowIntermediateMigrationOffer) {
@@ -597,6 +631,17 @@
       AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
 }
 
+// Ensures that the credit card icon will show in location bar.
+IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
+                       CreditCardIconShownInLocationBar) {
+  SaveServerCard(kFirstCardNumber);
+  SaveLocalCard(kSecondCardNumber);
+  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+
+  EXPECT_TRUE(
+      GetLocalCardMigrationIconView(/*icon_in_status_chip=*/false)->visible());
+}
+
 // Ensures that clicking on the credit card icon in the omnibox reopens the
 // offer bubble after closing it.
 IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
@@ -608,7 +653,7 @@
   UseCardAndWaitForMigrationOffer(kFirstCardNumber);
   ClickOnDialogViewAndWait(GetCloseButton(),
                            GetLocalCardMigrationOfferBubbleViews());
-  ClickOnView(GetLocalCardMigrationIconView());
+  ClickOnView(GetLocalCardMigrationIconView(/*icon_in_status_chip=*/false));
 
   // Clicking the icon should reshow the bubble.
   EXPECT_TRUE(
@@ -768,12 +813,8 @@
 IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                        ClosingDialogAddsLocalCardMigrationStrikes) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystemV2,
-       features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
-      // Disabled
-      {});
+  scoped_feature_list.InitAndEnableFeature(
+      features::kAutofillLocalCardMigrationUsesStrikeSystemV2);
   base::HistogramTester histogram_tester;
 
   SaveLocalCard(kFirstCardNumber);
@@ -793,12 +834,8 @@
 IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                        ClosingBubbleAddsLocalCardMigrationStrikes) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystemV2,
-       features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
-      // Disabled
-      {});
+  scoped_feature_list.InitAndEnableFeature(
+      features::kAutofillLocalCardMigrationUsesStrikeSystemV2);
   base::HistogramTester histogram_tester;
 
   SaveLocalCard(kFirstCardNumber);
@@ -820,12 +857,8 @@
 IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
                        ReshowingBubbleDoesNotAddStrikes) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystemV2,
-       features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
-      // Disabled
-      {});
+  scoped_feature_list.InitAndEnableFeature(
+      features::kAutofillLocalCardMigrationUsesStrikeSystemV2);
 
   SaveLocalCard(kFirstCardNumber);
   SaveLocalCard(kSecondCardNumber);
@@ -833,7 +866,7 @@
   ClickOnDialogViewAndWait(GetCloseButton(),
                            GetLocalCardMigrationOfferBubbleViews());
   base::HistogramTester histogram_tester;
-  ClickOnView(GetLocalCardMigrationIconView());
+  ClickOnView(GetLocalCardMigrationIconView(/*icon_in_status_chip=*/false));
 
   // Clicking the icon should reshow the bubble.
   EXPECT_TRUE(
@@ -849,6 +882,48 @@
       "Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
 }
 
+// Ensures that the credit card icon will show in status chip.
+IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
+                       CreditCardIconShownInStatusChip) {
+  SaveServerCard(kFirstCardNumber);
+  SaveLocalCard(kSecondCardNumber);
+  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+
+  EXPECT_TRUE(
+      GetLocalCardMigrationIconView(/*icon_in_status_chip=*/true)->visible());
+}
+
+// Ensures that clicking on the credit card icon in the status chip reopens the
+// offer bubble after closing it.
+IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTestForStatusChip,
+                       ClickingOmniboxIconReshowsBubble) {
+  base::HistogramTester histogram_tester;
+
+  SaveLocalCard(kFirstCardNumber);
+  SaveLocalCard(kSecondCardNumber);
+  UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+  ClickOnDialogViewAndWait(GetCloseButton(),
+                           GetLocalCardMigrationOfferBubbleViews());
+  ClickOnView(GetLocalCardMigrationIconView(/*icon_in_status_chip=*/true));
+
+  // Clicking the icon should reshow the bubble.
+  EXPECT_TRUE(
+      FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
+                           GetLocalCardMigrationOfferBubbleViews())
+          ->visible());
+  // Metrics
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(
+          "Autofill.LocalCardMigrationOrigin.UseOfLocalCard"),
+      ElementsAre(Bucket(AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1)));
+  EXPECT_THAT(
+      histogram_tester.GetAllSamples(
+          "Autofill.LocalCardMigrationBubbleOffer.Reshows"),
+      ElementsAre(
+          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
+          Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
+}
+
 // TODO(crbug.com/897998):
 // - Update test set-up and add navagation tests.
 // - Add more tests for feedback dialog.
diff --git a/chrome/browser/ui/views/chrome_web_dialog_view.cc b/chrome/browser/ui/views/chrome_web_dialog_view.cc
index 05301bd7..d2262d08 100644
--- a/chrome/browser/ui/views/chrome_web_dialog_view.cc
+++ b/chrome/browser/ui/views/chrome_web_dialog_view.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client.h"
+#include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/user.h"
 #endif  // defined(OS_CHROMEOS)
 
@@ -70,8 +71,10 @@
   const user_manager::User* user =
       chromeos::ProfileHelper::Get()->GetUserByProfile(
           Profile::FromBrowserContext(context));
-  if (user) {
-    // Dialogs should not be shown for other users when logged in.
+  if (user && session_manager::SessionManager::Get()->session_state() ==
+                  session_manager::SessionState::ACTIVE) {
+    // Dialogs should not be shown for other users when logged in and the
+    // session is active.
     MultiUserWindowManagerClient::GetInstance()->SetWindowOwner(
         window, user->GetAccountId());
   }
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 7976b11..cd6cfb1 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -103,6 +103,7 @@
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
 #include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
 #include "chrome/browser/ui/views/toolbar/reload_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/browser/ui/views/translate/translate_bubble_view.h"
 #include "chrome/browser/ui/views/update_recommended_message_box.h"
@@ -119,6 +120,7 @@
 #include "components/app_modal/app_modal_dialog_queue.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
 #include "components/app_modal/native_app_modal_dialog.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/browser/omnibox_popup_view.h"
 #include "components/omnibox/browser/omnibox_view.h"
@@ -1071,6 +1073,10 @@
   return toolbar_button_provider_->GetPageActionIconContainerView();
 }
 
+PageActionIconContainer* BrowserView::GetToolbarPageActionIconContainer() {
+  return toolbar_ ? toolbar_->toolbar_page_action_container() : nullptr;
+}
+
 LocationBar* BrowserView::GetLocationBar() const {
   return GetLocationBarView();
 }
@@ -1354,14 +1360,29 @@
     content::WebContents* web_contents,
     autofill::LocalCardMigrationBubbleController* controller,
     bool user_gesture) {
-  LocationBarView* location_bar = GetLocationBarView();
-  PageActionIconView* card_view =
-      location_bar->local_card_migration_icon_view();
-  autofill::LocalCardMigrationBubbleViews* bubble =
-      new autofill::LocalCardMigrationBubbleViews(location_bar, gfx::Point(),
-                                                  web_contents, controller);
-  if (card_view)
-    bubble->SetHighlightedButton(card_view);
+  autofill::LocalCardMigrationBubbleViews* bubble = nullptr;
+  PageActionIconView* icon_view = nullptr;
+
+  if (base::FeatureList::IsEnabled(
+          autofill::features::kAutofillEnableToolbarStatusChip)) {
+    // Icon will be shown in the status chip when feature is enabled. The anchor
+    // view for the bubble is the status chip container.
+    ToolbarPageActionIconContainerView* toolbar_page_action_container =
+        toolbar_->toolbar_page_action_container();
+    icon_view = toolbar_page_action_container->GetIconView(
+        PageActionIconType::kLocalCardMigration);
+    bubble = new autofill::LocalCardMigrationBubbleViews(
+        toolbar_page_action_container, gfx::Point(), web_contents, controller);
+  } else {
+    // Otherwise the bubble is anchored to the credit card icon in the location
+    // bar. This will be removed when the feature is fully enabled.
+    LocationBarView* location_bar = GetLocationBarView();
+    icon_view = location_bar->local_card_migration_icon_view();
+    bubble = new autofill::LocalCardMigrationBubbleViews(
+        location_bar, gfx::Point(), web_contents, controller);
+  }
+  if (icon_view)
+    bubble->SetHighlightedButton(icon_view);
 
   views::BubbleDialogDelegateView::CreateBubble(bubble);
   bubble->Show(user_gesture
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index b36a7ee8..08629a2 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -67,6 +67,7 @@
 class FullscreenControlHost;
 class InfoBarContainerView;
 class LocationBarView;
+class PageActionIconContainer;
 class StatusBubbleViews;
 class TabStrip;
 class ToolbarButtonProvider;
@@ -340,6 +341,7 @@
   bool IsFullscreen() const override;
   bool IsFullscreenBubbleVisible() const override;
   PageActionIconContainer* GetPageActionIconContainer() override;
+  PageActionIconContainer* GetToolbarPageActionIconContainer() override;
   LocationBar* GetLocationBar() const override;
   void SetFocusToLocationBar() override;
   void UpdateReloadStopState(bool is_loading, bool force) override;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index c47155f..b2c944b 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -59,6 +59,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/favicon/content/content_favicon_driver.h"
 #include "components/omnibox/browser/location_bar_model.h"
@@ -239,13 +240,19 @@
   AddChildView(page_action_icon_container_view_);
 
   if (browser_) {
-    save_credit_card_icon_view_ = new autofill::SaveCardIconView(
-        command_updater(), browser_, this, font_list);
-    page_action_icons_.push_back(save_credit_card_icon_view_);
+    // Add icons only when feature is not enabled. Otherwise icons will
+    // be added to the ToolbarPageActionIconContainerView.
+    if (!base::FeatureList::IsEnabled(
+            autofill::features::kAutofillEnableToolbarStatusChip)) {
+      save_credit_card_icon_view_ = new autofill::SaveCardIconView(
+          command_updater(), browser_, this, font_list);
+      page_action_icons_.push_back(save_credit_card_icon_view_);
 
-    local_card_migration_icon_view_ = new autofill::LocalCardMigrationIconView(
-        command_updater(), browser_, this, font_list);
-    page_action_icons_.push_back(local_card_migration_icon_view_);
+      local_card_migration_icon_view_ =
+          new autofill::LocalCardMigrationIconView(command_updater(), browser_,
+                                                   this, font_list);
+      page_action_icons_.push_back(local_card_migration_icon_view_);
+    }
 
 #if defined(OS_CHROMEOS)
     page_action_icons_.push_back(intent_picker_view_ =
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
index fdc0b9c6..e38c809f 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
@@ -59,6 +59,9 @@
                                   params.page_action_icon_delegate);
         page_action_icons_.push_back(zoom_view_);
         break;
+      case PageActionIconType::kLocalCardMigration:
+        NOTREACHED();
+        break;
     }
   }
 
@@ -94,6 +97,9 @@
       return translate_icon_;
     case PageActionIconType::kZoom:
       return zoom_view_;
+    case PageActionIconType::kLocalCardMigration:
+      NOTREACHED();
+      return nullptr;
   }
   return nullptr;
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
new file mode 100644
index 0000000..f4cd0e9
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h"
+
+#include <memory>
+
+#include "ui/views/layout/flex_layout.h"
+
+ToolbarIconContainerView::ToolbarIconContainerView() {
+  SetLayoutManager(std::make_unique<views::FlexLayout>());
+}
+
+ToolbarIconContainerView::~ToolbarIconContainerView() = default;
+
+void ToolbarIconContainerView::UpdateAllIcons() {}
+
+void ToolbarIconContainerView::ChildPreferredSizeChanged(views::View* child) {
+  PreferredSizeChanged();
+}
+
+void ToolbarIconContainerView::ChildVisibilityChanged(views::View* child) {
+  PreferredSizeChanged();
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
new file mode 100644
index 0000000..0d89b3d
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
@@ -0,0 +1,28 @@
+// 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_TOOLBAR_TOOLBAR_ICON_CONTAINER_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ICON_CONTAINER_VIEW_H_
+
+#include "base/macros.h"
+#include "ui/views/view.h"
+
+// A general view container for any type of toolbar icons.
+class ToolbarIconContainerView : public views::View {
+ public:
+  ToolbarIconContainerView();
+  ~ToolbarIconContainerView() override;
+
+  // Update all the icons it contains. Override by subclass.
+  virtual void UpdateAllIcons();
+
+ private:
+  // views::View
+  void ChildPreferredSizeChanged(views::View* child) override;
+  void ChildVisibilityChanged(views::View* child) override;
+
+  DISALLOW_COPY_AND_ASSIGN(ToolbarIconContainerView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ICON_CONTAINER_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc
new file mode 100644
index 0000000..5e097da
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc
@@ -0,0 +1,61 @@
+// 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/toolbar/toolbar_page_action_icon_container_view.h"
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/autofill/local_card_migration_icon_view.h"
+#include "chrome/browser/ui/views/autofill/save_card_icon_view.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
+
+ToolbarPageActionIconContainerView::ToolbarPageActionIconContainerView(
+    CommandUpdater* command_updater,
+    Browser* browser)
+    : ToolbarIconContainerView(), browser_(browser) {
+  local_card_migration_icon_view_ = new autofill::LocalCardMigrationIconView(
+      command_updater, browser, this,
+      // TODO(932818): The font list and the icon color may not be what we want
+      // here. Put placeholders for now.
+      views::style::GetFont(CONTEXT_TOOLBAR_BUTTON,
+                            views::style::STYLE_PRIMARY));
+  local_card_migration_icon_view_->Init();
+  local_card_migration_icon_view_->SetVisible(false);
+  AddChildView(local_card_migration_icon_view_);
+}
+
+ToolbarPageActionIconContainerView::~ToolbarPageActionIconContainerView() =
+    default;
+
+void ToolbarPageActionIconContainerView::UpdateAllIcons() {
+  if (local_card_migration_icon_view_)
+    local_card_migration_icon_view_->Update();
+}
+
+PageActionIconView* ToolbarPageActionIconContainerView::GetIconView(
+    PageActionIconType icon_type) {
+  switch (icon_type) {
+    case PageActionIconType::kLocalCardMigration:
+      return local_card_migration_icon_view_;
+    default:
+      return nullptr;
+  }
+}
+
+void ToolbarPageActionIconContainerView::UpdatePageActionIcon(
+    PageActionIconType icon_type) {
+  PageActionIconView* icon = GetIconView(icon_type);
+  if (icon)
+    icon->Update();
+}
+
+SkColor ToolbarPageActionIconContainerView::GetPageActionInkDropColor() const {
+  return GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_TextfieldDefaultColor);
+}
+
+content::WebContents*
+ToolbarPageActionIconContainerView::GetWebContentsForPageActionIconView() {
+  return browser_->tab_strip_model()->GetActiveWebContents();
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h
new file mode 100644
index 0000000..5b208ebb
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h
@@ -0,0 +1,57 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_PAGE_ACTION_ICON_CONTAINER_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_PAGE_ACTION_ICON_CONTAINER_VIEW_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/page_action/page_action_icon_container.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h"
+
+class Browser;
+class CommandUpdater;
+
+namespace autofill {
+class LocalCardMigrationIconView;
+}  // namespace autofill
+
+// A container view for user-account-related PageActionIconViews and the profile
+// avatar icon. This container view is in the toolbar while the other
+// PageActionIconContainerView is in the omnibox and it is used to handle other
+// non user-account-related page action icons.
+class ToolbarPageActionIconContainerView : public ToolbarIconContainerView,
+                                           public PageActionIconContainer,
+                                           public PageActionIconView::Delegate {
+ public:
+  ToolbarPageActionIconContainerView(CommandUpdater* command_updater,
+                                     Browser* browser);
+  ~ToolbarPageActionIconContainerView() override;
+
+  PageActionIconView* GetIconView(PageActionIconType icon_type);
+
+  // ToolbarIconContainerView:
+  void UpdateAllIcons() override;
+
+  // PageActionIconContainer:
+  void UpdatePageActionIcon(PageActionIconType icon_type) override;
+
+  // PageActionIconView::Delegate:
+  SkColor GetPageActionInkDropColor() const override;
+  content::WebContents* GetWebContentsForPageActionIconView() override;
+
+  autofill::LocalCardMigrationIconView* local_card_migration_icon_view() {
+    return local_card_migration_icon_view_;
+  }
+
+ private:
+  autofill::LocalCardMigrationIconView* local_card_migration_icon_view_ =
+      nullptr;
+
+  Browser* const browser_;
+
+  DISALLOW_COPY_AND_ASSIGN(ToolbarPageActionIconContainerView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_PAGE_ACTION_ICON_CONTAINER_VIEW_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index fa70d696..1d225eb 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -44,12 +44,14 @@
 #include "chrome/browser/ui/views/toolbar/home_button.h"
 #include "chrome/browser/ui/views/toolbar/reload_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
@@ -229,6 +231,14 @@
   if (media_router::MediaRouterEnabled(browser_->profile()))
     cast_ = media_router::CastToolbarButton::Create(browser_).release();
 
+#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
+  if (base::FeatureList::IsEnabled(
+          autofill::features::kAutofillEnableToolbarStatusChip)) {
+    toolbar_page_action_container_ = new ToolbarPageActionIconContainerView(
+        browser_->command_controller(), browser_);
+  }
+#endif  // !defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
+
   bool show_avatar_toolbar_button = true;
 #if defined(OS_CHROMEOS)
   // ChromeOS only badges Incognito and Guest icons in the browser window.
@@ -255,8 +265,13 @@
   AddChildView(browser_actions_);
   if (cast_)
     AddChildView(cast_);
+
+  if (toolbar_page_action_container_)
+    AddChildView(toolbar_page_action_container_);
+
   if (avatar_)
     AddChildView(avatar_);
+
   AddChildView(app_menu_button_);
 
   LoadImages();
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 70cf85e..c1f9574 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -43,6 +43,7 @@
 class HomeButton;
 class ReloadButton;
 class ToolbarButton;
+class ToolbarPageActionIconContainerView;
 
 namespace bookmarks {
 class BookmarkBubbleObserver;
@@ -130,6 +131,9 @@
   LocationBarView* location_bar() const { return location_bar_; }
   CustomTabBarView* custom_tab_bar() { return custom_tab_bar_; }
   media_router::CastToolbarButton* cast_button() const { return cast_; }
+  ToolbarPageActionIconContainerView* toolbar_page_action_container() const {
+    return toolbar_page_action_container_;
+  }
   AvatarToolbarButton* avatar_button() const { return avatar_; }
   BrowserAppMenuButton* app_menu_button() const { return app_menu_button_; }
   HomeButton* home_button() const { return home_; }
@@ -249,6 +253,7 @@
   LocationBarView* location_bar_ = nullptr;
   BrowserActionsContainer* browser_actions_ = nullptr;
   media_router::CastToolbarButton* cast_ = nullptr;
+  ToolbarPageActionIconContainerView* toolbar_page_action_container_ = nullptr;
   AvatarToolbarButton* avatar_ = nullptr;
   BrowserAppMenuButton* app_menu_button_ = nullptr;
 
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 605023b..70f0048 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -14,6 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "chrome/browser/browser_features.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_util.h"
@@ -51,6 +52,7 @@
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/gfx/animation/animation.h"
 #include "ui/gfx/color_utils.h"
+#include "ui/native_theme/native_theme.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -134,7 +136,12 @@
 }  // namespace
 
 NTPResourceCache::NTPResourceCache(Profile* profile)
-    : profile_(profile), is_swipe_tracking_from_scroll_events_enabled_(false) {
+    : profile_(profile),
+      is_swipe_tracking_from_scroll_events_enabled_(false),
+      dark_mode_observer_(
+          ui::NativeTheme::GetInstanceForNativeUi(),
+          base::BindRepeating(&NTPResourceCache::OnDarkModeChanged,
+                              base::Unretained(this))) {
   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
                  content::Source<ThemeService>(
                      ThemeServiceFactory::GetForProfile(profile)));
@@ -150,6 +157,8 @@
   profile_pref_change_registrar_.Add(prefs::kSignInPromoShowNTPBubble,
                                      callback);
   profile_pref_change_registrar_.Add(prefs::kHideWebStoreIcon, callback);
+
+  dark_mode_observer_.Start();
 }
 
 NTPResourceCache::~NTPResourceCache() {}
@@ -230,6 +239,10 @@
   Invalidate();
 }
 
+void NTPResourceCache::OnDarkModeChanged(bool /*dark_mode*/) {
+  Invalidate();
+}
+
 void NTPResourceCache::OnPreferenceChanged() {
   // A change occurred to one of the preferences we care about, so flush the
   // cache.
@@ -338,6 +351,8 @@
       l10n_util::GetStringUTF16(guest_tab_link_ids));
   localized_strings.SetString("learnMoreLink", guest_tab_link);
 
+  SetDarkKey(&localized_strings);
+
   const std::string& app_locale = g_browser_process->GetApplicationLocale();
   webui::SetLoadTimeDataDefaults(app_locale, &localized_strings);
 
@@ -461,6 +476,8 @@
       "isUserSignedIn",
       IdentityManagerFactory::GetForProfile(profile_)->HasPrimaryAccount());
 
+  SetDarkKey(&load_time_data);
+
   // Load the new tab page appropriate for this build.
   base::StringPiece new_tab_html(
       ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
@@ -574,3 +591,11 @@
       ui::ReplaceTemplateExpressions(new_tab_theme_css, substitutions);
   new_tab_css_ = base::RefCountedString::TakeString(&css_string);
 }
+
+void NTPResourceCache::SetDarkKey(base::Value* dict) {
+  DCHECK(dict && dict->is_dict());
+  bool enabled = base::FeatureList::IsEnabled(features::kWebUIDarkMode);
+  dict->SetKey(
+      "dark",
+      base::Value(enabled && dark_mode_observer_.InDarkMode() ? "dark" : ""));
+}
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
index 827b2ee..d3a0791 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
@@ -8,6 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "chrome/browser/ui/dark_mode_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "content/public/browser/notification_observer.h"
@@ -17,6 +18,7 @@
 
 namespace base {
 class RefCountedMemory;
+class Value;
 }
 
 namespace content {
@@ -53,6 +55,8 @@
  private:
   void OnPreferenceChanged();
 
+  void OnDarkModeChanged(bool dark_mode);
+
   // Invalidates the NTPResourceCache.
   void Invalidate();
 
@@ -70,6 +74,8 @@
 
   void CreateNewTabGuestHTML();
 
+  void SetDarkKey(base::Value* dict);
+
   Profile* profile_;
 
   scoped_refptr<base::RefCountedMemory> new_tab_html_;
@@ -84,6 +90,8 @@
   // Set based on platform_util::IsSwipeTrackingFromScrollEventsEnabled.
   bool is_swipe_tracking_from_scroll_events_enabled_;
 
+  DarkModeObserver dark_mode_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(NTPResourceCache);
 };
 
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index c14ef97..dab1b70 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -195,10 +195,15 @@
       policies.SetKey(
           kAllowedDuplexModes,
           base::Value(prefs->GetInteger(prefs::kPrintingAllowedDuplexModes)));
+      policies.SetKey(
+          kAllowedPinModes,
+          base::Value(prefs->GetInteger(prefs::kPrintingAllowedPinModes)));
       policies.SetKey(kDefaultColorMode,
                       base::Value(prefs->Get(prefs::kPrintingColorDefault)));
       policies.SetKey(kDefaultDuplexMode,
                       base::Value(prefs->Get(prefs::kPrintingDuplexDefault)));
+      policies.SetKey(kDefaultPinMode,
+                      base::Value(prefs->Get(prefs::kPrintingPinDefault)));
       // fetch settings on the blocking pool and invoke callback.
       FetchCapabilities(std::move(printer), std::move(policies), std::move(cb));
       return;
diff --git a/chrome/chrome_cleaner/os/system_util_cleaner_unittest.cc b/chrome/chrome_cleaner/os/system_util_cleaner_unittest.cc
index f3d2f76..7db3b8d 100644
--- a/chrome/chrome_cleaner/os/system_util_cleaner_unittest.cc
+++ b/chrome/chrome_cleaner/os/system_util_cleaner_unittest.cc
@@ -85,7 +85,8 @@
   EXPECT_FALSE(DoesServiceExist(service_handle.service_name()));
 }
 
-TEST_F(ServiceUtilCleanerTest, StopAndDeleteRunningService) {
+// Flaky. https://crbug.com/871784
+TEST_F(ServiceUtilCleanerTest, DISABLED_StopAndDeleteRunningService) {
   // Install and launch the service.
   TestScopedServiceHandle service_handle;
   ASSERT_TRUE(service_handle.InstallService());
@@ -108,7 +109,8 @@
   EXPECT_FALSE(IsProcessRunning(kTestServiceExecutableName));
 }
 
-TEST_F(ServiceUtilCleanerTest, DeleteRunningService) {
+// Flaky. https://crbug.com/871784
+TEST_F(ServiceUtilCleanerTest, DISABLED_DeleteRunningService) {
   // Install and launch the service.
   TestScopedServiceHandle service_handle;
   ASSERT_TRUE(service_handle.InstallService());
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl
index ed28d97..0cd2f60 100644
--- a/chrome/common/extensions/api/autotest_private.idl
+++ b/chrome/common/extensions/api/autotest_private.idl
@@ -292,6 +292,16 @@
     // |callback|: Called when the operation has completed.
     static void setCrostiniEnabled(boolean enabled, VoidCallback callback);
 
+    // Export the crostini container.
+    // |path|: The path in Downloads to save the export.
+    // |callback|: Called when the operation has completed.
+    static void exportCrostini(DOMString path, VoidCallback callback);
+
+    // Import the crostini container.
+    // |path|: The path in Downloads to read the import.
+    // |callback|: Called when the operation has completed.
+    static void importCrostini(DOMString path, VoidCallback callback);
+
     // Takes a screenshot and returns the data in base64 encoded PNG format.
     static void takeScreenshot(TakeScreenshotCallback callback);
 
diff --git a/chrome/renderer/extensions/extension_localization_peer.cc b/chrome/renderer/extensions/extension_localization_peer.cc
index e487ffd..1cae6d6 100644
--- a/chrome/renderer/extensions/extension_localization_peer.cc
+++ b/chrome/renderer/extensions/extension_localization_peer.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
@@ -19,7 +18,6 @@
 #include "ipc/ipc_sender.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
-#include "third_party/blink/public/common/features.h"
 
 namespace {
 
@@ -92,8 +90,6 @@
 
 void ExtensionLocalizationPeer::OnStartLoadingResponseBody(
     mojo::ScopedDataPipeConsumerHandle body) {
-  DCHECK(!response_source_.has_value());
-  response_source_ = ResponseSource::kDataPipe;
   data_pipe_state_.body_state_ = DataPipeState::BodyState::kReadingBody;
   data_pipe_state_.source_handle_ = std::move(body);
   data_pipe_state_.source_watcher_.Watch(
@@ -105,12 +101,8 @@
   data_pipe_state_.source_watcher_.ArmOrNotify();
 }
 
-void ExtensionLocalizationPeer::OnReceivedData(
-    std::unique_ptr<ReceivedData> data) {
-  if (!response_source_.has_value())
-    response_source_ = ResponseSource::kNonDataPipe;
-  DCHECK_EQ(ResponseSource::kNonDataPipe, response_source_.value());
-  data_.append(data->payload(), data->length());
+void ExtensionLocalizationPeer::OnReceivedData(std::unique_ptr<ReceivedData>) {
+  NOTREACHED();
 }
 
 void ExtensionLocalizationPeer::OnTransferSizeUpdated(int transfer_size_diff) {
@@ -122,37 +114,25 @@
   if (completion_status_.has_value()) {
     // This means that we've already returned error status to the original peer
     // due to an error on the data pipe.
-    DCHECK_EQ(ResponseSource::kDataPipe, response_source_.value());
     return;
   }
   completion_status_ = status;
-  if (response_source_ &&
-      response_source_.value() == ResponseSource::kDataPipe) {
-    if (status.error_code != net::OK) {
-      data_pipe_state_.source_watcher_.Cancel();
-      data_pipe_state_.source_handle_.reset();
-      data_pipe_state_.destination_watcher_.Cancel();
-      data_pipe_state_.destination_handle_.reset();
-      data_pipe_state_.body_state_ = DataPipeState::BodyState::kDone;
-    }
 
-    if (data_pipe_state_.body_state_ != DataPipeState::BodyState::kDone) {
-      // Still reading, or sending the body. Wait until all data has been read,
-      // and sent to the |original_peer_|.
-      return;
-    }
+  if (status.error_code != net::OK) {
+    data_pipe_state_.source_watcher_.Cancel();
+    data_pipe_state_.source_handle_.reset();
+    data_pipe_state_.destination_watcher_.Cancel();
+    data_pipe_state_.destination_handle_.reset();
+    data_pipe_state_.body_state_ = DataPipeState::BodyState::kDone;
+  }
 
-    // We've sent all the body to the peer. Complete the request.
-    CompleteRequest();
+  if (data_pipe_state_.body_state_ != DataPipeState::BodyState::kDone) {
+    // Still reading, or sending the body. Wait until all data has been read,
+    // and sent to the |original_peer_|.
     return;
   }
 
-  DCHECK(!response_source_.has_value() ||
-         response_source_.value() == ResponseSource::kNonDataPipe);
-
-  original_peer_->OnReceivedResponse(response_info_);
-  if (status.error_code == net::OK)
-    ReplaceMessages();
+  // We've sent all the body to the peer. Complete the request.
   CompleteRequest();
 }
 
@@ -163,7 +143,6 @@
 void ExtensionLocalizationPeer::OnReadableBody(
     MojoResult,
     const mojo::HandleSignalsState&) {
-  DCHECK_EQ(ResponseSource::kDataPipe, response_source_.value());
   DCHECK(data_pipe_state_.source_handle_.is_valid());
   DCHECK_EQ(DataPipeState::BodyState::kReadingBody,
             data_pipe_state_.body_state_);
@@ -203,7 +182,6 @@
 }
 
 void ExtensionLocalizationPeer::StartSendingBody() {
-  DCHECK_EQ(ResponseSource::kDataPipe, response_source_.value());
   DCHECK(!data_pipe_state_.source_handle_.is_valid());
   DCHECK_EQ(DataPipeState::BodyState::kReadingBody,
             data_pipe_state_.body_state_);
@@ -238,7 +216,6 @@
 void ExtensionLocalizationPeer::OnWritableBody(
     MojoResult,
     const mojo::HandleSignalsState&) {
-  DCHECK_EQ(ResponseSource::kDataPipe, response_source_.value());
   DCHECK(data_pipe_state_.destination_handle_.is_valid());
   DCHECK_EQ(DataPipeState::BodyState::kSendingBody,
             data_pipe_state_.body_state_);
@@ -315,8 +292,7 @@
   DCHECK(completion_status_.has_value());
   // Body should have been sent to the origial peer at this point when it's
   // from a data pipe.
-  DCHECK(response_source_ != ResponseSource::kDataPipe ||
-         data_pipe_state_.body_state_ == DataPipeState::BodyState::kDone);
+  DCHECK_EQ(DataPipeState::BodyState::kDone, data_pipe_state_.body_state_);
 
   if (completion_status_->error_code != net::OK) {
     // We failed to load the resource.
@@ -327,29 +303,5 @@
     return;
   }
 
-  // Empty body.
-  if (!response_source_.has_value()) {
-    if (base::FeatureList::IsEnabled(
-            blink::features::kResourceLoadViaDataPipe)) {
-      mojo::ScopedDataPipeConsumerHandle consumer_to_send;
-      MojoResult result = mojo::CreateDataPipe(
-          nullptr, &data_pipe_state_.destination_handle_, &consumer_to_send);
-      if (result != MOJO_RESULT_OK) {
-        original_peer_->OnCompletedRequest(network::URLLoaderCompletionStatus(
-            net::ERR_INSUFFICIENT_RESOURCES));
-        return;
-      }
-
-      // Call OnStartLoadingResponseBody() to align with other loaders:
-      // https://crbug.com/826868.
-      original_peer_->OnStartLoadingResponseBody(std::move(consumer_to_send));
-      data_pipe_state_.destination_handle_.reset();
-    }
-    original_peer_->OnCompletedRequest(completion_status_.value());
-    return;
-  }
-
-  if (response_source_.value() == ResponseSource::kNonDataPipe)
-    original_peer_->OnReceivedData(std::make_unique<StringData>(data_));
   original_peer_->OnCompletedRequest(completion_status_.value());
 }
diff --git a/chrome/renderer/extensions/extension_localization_peer.h b/chrome/renderer/extensions/extension_localization_peer.h
index b1cd57a..21ee03a 100644
--- a/chrome/renderer/extensions/extension_localization_peer.h
+++ b/chrome/renderer/extensions/extension_localization_peer.h
@@ -28,17 +28,7 @@
 // Call the factory method CreateExtensionLocalizationPeer() to obtain an
 // instance of ExtensionLocalizationPeer based on the original Peer.
 //
-// Currently there are two cases of how to process the body: DataPipe and
-// non-DataPipe.
-//
-// If it's non-DataPipe, the main flow of method calls would be like this:
-// 1. OnReceivedResponse() when the response header is ready.
-// 2. OnReceivedData() multiple times until the entire body is ready.
-// 3. OnCompletedRequest() when the body is ready. It replaces the content using
-//    the message catalogs, and send the body and the status to the original
-//    peer.
-//
-// If it's DataPipe, the main flow of method calls is like this:
+// The main flow of method calls is like this:
 // 1.   OnReceivedResponse() when the response header is ready.
 // 2-a. OnStartLoadingResponseBody() when the body streaming starts. It starts
 //      to read the body from the data pipe. After finishing to read the whole
@@ -49,6 +39,9 @@
 //      is stored as a member.
 // 3.   CompleteRequest() when both of 2-a and 2-b finish. Sends the stored
 //      status code to the original peer.
+//
+// Note that OnCompletedRequest() can be called at any time, even before
+// OnReceivedResponse().
 class ExtensionLocalizationPeer : public content::RequestPeer {
  public:
   ~ExtensionLocalizationPeer() override;
@@ -80,7 +73,6 @@
                             IPC::Sender* message_sender,
                             const GURL& request_url);
 
-  // Used only when |response_source_| is ResponseSource::kDataPipe.
   void OnReadableBody(MojoResult, const mojo::HandleSignalsState&);
   void StartSendingBody();
   void OnWritableBody(MojoResult, const mojo::HandleSignalsState&);
@@ -97,13 +89,6 @@
   // We just pass though the response info. This holds the copy of the original.
   network::ResourceResponseInfo response_info_;
 
-  // If the body is provided by OnReceivedData(), it's kNonDataPipe.
-  // If the body is provided by OnStartLoadingResponseBody, it's kDataPipe.
-  // See the class-level comment for the details.
-  enum class ResponseSource { kDataPipe, kNonDataPipe };
-  base::Optional<ResponseSource> response_source_;
-
-  // Contains states used only when |response_source_| is kDataPipe.
   struct DataPipeState {
     DataPipeState();
     ~DataPipeState();
diff --git a/chrome/renderer/extensions/extension_localization_peer_unittest.cc b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
index 1bb149b..fc5412e 100644
--- a/chrome/renderer/extensions/extension_localization_peer_unittest.cc
+++ b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
@@ -86,11 +86,10 @@
                             base::Unretained(this)));
   }
   MOCK_METHOD2(OnDownloadedData, void(int len, int encoded_data_length));
-  void OnReceivedData(
-      std::unique_ptr<RequestPeer::ReceivedData> data) override {
-    OnReceivedDataInternal(data->payload(), data->length());
+  void OnReceivedData(std::unique_ptr<RequestPeer::ReceivedData>) override {
+    NOTREACHED();
   }
-  MOCK_METHOD2(OnReceivedDataInternal, void(const char* data, int data_length));
+  MOCK_METHOD1(OnReceivedDataInternal, void(std::string data));
   MOCK_METHOD1(OnTransferSizeUpdated, void(int transfer_size_diff));
   MOCK_METHOD1(OnCompletedRequest,
                void(const network::URLLoaderCompletionStatus& status));
@@ -118,7 +117,7 @@
 
     if (result == MOJO_RESULT_FAILED_PRECONDITION) {
       body_watcher_.Cancel();
-      OnReceivedDataInternal(body_.data(), body_.size());
+      OnReceivedDataInternal(body_);
       DCHECK(wait_for_body_callback_);
       std::move(wait_for_body_callback_).Run();
       return;
@@ -147,7 +146,8 @@
 
   void SetUpExtensionLocalizationPeer(const std::string& mime_type,
                                       const GURL& request_url) {
-    std::unique_ptr<MockRequestPeer> original_peer(new MockRequestPeer());
+    auto original_peer =
+        std::make_unique<testing::StrictMock<MockRequestPeer>>();
     original_peer_ = original_peer.get();
     auto extension_peer =
         ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
@@ -159,8 +159,26 @@
   std::string GetData() { return filter_peer_->data_; }
 
   void SetData(const std::string& data) {
-    filter_peer_->OnReceivedData(
-        std::make_unique<content::FixedReceivedData>(data.data(), data.size()));
+    MojoCreateDataPipeOptions options;
+    options.struct_size = sizeof(MojoCreateDataPipeOptions);
+    options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+    options.element_num_bytes = 1;
+    options.capacity_num_bytes = data.size();
+    mojo::ScopedDataPipeProducerHandle producer;
+    mojo::ScopedDataPipeConsumerHandle consumer;
+    MojoResult result = mojo::CreateDataPipe(&options, &producer, &consumer);
+    EXPECT_EQ(MOJO_RESULT_OK, result);
+    filter_peer_->OnStartLoadingResponseBody(std::move(consumer));
+    mojo::BlockingCopyFromString(data, producer);
+    producer.reset();
+  }
+
+  mojo::ScopedDataPipeConsumerHandle CreateEmptyBodyDataPipe() const {
+    mojo::ScopedDataPipeConsumerHandle consumer;
+    mojo::ScopedDataPipeProducerHandle producer;
+    MojoResult result = mojo::CreateDataPipe(nullptr, &producer, &consumer);
+    DCHECK_EQ(MOJO_RESULT_OK, result);
+    return consumer;
   }
 
   base::test::ScopedTaskEnvironment scoped_environment_;
@@ -181,27 +199,12 @@
   EXPECT_TRUE(NULL != filter_peer_.get());
 }
 
-TEST_F(ExtensionLocalizationPeerTest, OnReceivedData) {
-  SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
-  EXPECT_TRUE(GetData().empty());
-
-  const std::string data_chunk("12345");
-  filter_peer_->OnReceivedData(std::make_unique<content::FixedReceivedData>(
-      data_chunk.data(), data_chunk.length()));
-
-  EXPECT_EQ(data_chunk, GetData());
-
-  filter_peer_->OnReceivedData(std::make_unique<content::FixedReceivedData>(
-      data_chunk.data(), data_chunk.length()));
-  EXPECT_EQ(data_chunk + data_chunk, GetData());
-}
-
 MATCHER_P(IsURLRequestEqual, status, "") { return arg.status() == status; }
 
 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestBadURLRequestStatus) {
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
 
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  // This test simulates completion before receiving the response header.
   network::URLLoaderCompletionStatus status(net::ERR_ABORTED);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
 
@@ -211,47 +214,45 @@
 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestEmptyData) {
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
 
-  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(_, _)).Times(0);
+  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(std::string()));
   EXPECT_CALL(*sender_, Send(_)).Times(0);
 
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
   network::URLLoaderCompletionStatus status(net::OK);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
 
+  filter_peer_->OnStartLoadingResponseBody(CreateEmptyBodyDataPipe());
   filter_peer_->OnCompletedRequest(status);
+  original_peer_->RunUntilBodyBecomesReady();
 }
 
 TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestNoCatalogs) {
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
 
-  SetData("some text");
-
+  const std::string kExpectedData = "some text";
   EXPECT_CALL(*sender_, Send(_));
 
-  std::string data = GetData();
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(1);
-  EXPECT_CALL(*original_peer_,
-              OnReceivedDataInternal(StrEq(data.c_str()), data.length()))
-      .Times(1);
+  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(kExpectedData)).Times(1);
   network::URLLoaderCompletionStatus status(net::OK);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(status)).Times(1);
 
+  SetData(kExpectedData);
   filter_peer_->OnCompletedRequest(status);
+  original_peer_->RunUntilBodyBecomesReady();
 
   // Test if Send gets called again (it shouldn't be) when first call returned
   // an empty dictionary.
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_1));
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_)).Times(1);
-  EXPECT_CALL(*original_peer_,
-              OnReceivedDataInternal(StrEq(data.c_str()), data.length()))
-      .Times(1);
+  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(kExpectedData)).Times(1);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(status)).Times(1);
-  SetData("some text");
+  SetData(kExpectedData);
   filter_peer_->OnCompletedRequest(status);
+  original_peer_->RunUntilBodyBecomesReady();
 }
 
-TEST_F(ExtensionLocalizationPeerTest,
-       OnCompletedRequestWithCatalogs_WithNonDataPipe) {
+TEST_F(ExtensionLocalizationPeerTest, OnCompletedRequestWithCatalogs) {
   SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
 
   extensions::L10nMessagesMap messages;
@@ -260,55 +261,18 @@
       *extensions::GetExtensionToL10nMessagesMap();
   l10n_messages_map["some_id2"] = messages;
 
+  // We already have messages in memory, Send will be skipped.
+  EXPECT_CALL(*sender_, Send(_)).Times(0);
+
+  // __MSG_text__ gets replaced with "new text".
+  std::string data("some new text");
+  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
+  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(data));
+
+  network::URLLoaderCompletionStatus status(net::OK);
+  EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
+
   SetData("some __MSG_text__");
-
-  // We already have messages in memory, Send will be skipped.
-  EXPECT_CALL(*sender_, Send(_)).Times(0);
-
-  // __MSG_text__ gets replaced with "new text".
-  std::string data("some new text");
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_,
-              OnReceivedDataInternal(StrEq(data.c_str()), data.length()));
-
-  network::URLLoaderCompletionStatus status(net::OK);
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
-
-  filter_peer_->OnCompletedRequest(status);
-}
-
-TEST_F(ExtensionLocalizationPeerTest,
-       OnCompletedRequestWithCatalogs_WithDataPipe) {
-  SetUpExtensionLocalizationPeer("text/css", GURL(kExtensionUrl_2));
-
-  extensions::L10nMessagesMap messages;
-  messages.insert(std::make_pair("text", "new text"));
-  extensions::ExtensionToL10nMessagesMap& l10n_messages_map =
-      *extensions::GetExtensionToL10nMessagesMap();
-  l10n_messages_map["some_id2"] = messages;
-
-  mojo::ScopedDataPipeConsumerHandle consumer;
-  mojo::ScopedDataPipeProducerHandle producer;
-  ASSERT_EQ(MOJO_RESULT_OK,
-            mojo::CreateDataPipe(nullptr, &producer, &consumer));
-  filter_peer_->OnStartLoadingResponseBody(std::move(consumer));
-
-  // We already have messages in memory, Send will be skipped.
-  EXPECT_CALL(*sender_, Send(_)).Times(0);
-
-  // __MSG_text__ gets replaced with "new text".
-  std::string data("some new text");
-  EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_,
-              OnReceivedDataInternal(StrEq(data.c_str()), data.length()));
-
-  network::URLLoaderCompletionStatus status(net::OK);
-  EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
-
-  // When the entire body is ready and also OnCompletedRequest() is called, the
-  // replaced body will be streamed to the original peer.
-  mojo::BlockingCopyFromString("some __MSG_text__", producer);
-  producer.reset();
   filter_peer_->OnCompletedRequest(status);
   original_peer_->RunUntilBodyBecomesReady();
 }
@@ -323,18 +287,18 @@
   l10n_messages_map["some_id3"] = messages;
 
   std::string message("some __MSG_missing_message__");
-  SetData(message);
 
   // We already have messages in memory, Send will be skipped.
   EXPECT_CALL(*sender_, Send(_)).Times(0);
 
   // __MSG_missing_message__ is missing, so message stays the same.
   EXPECT_CALL(*original_peer_, OnReceivedResponse(_));
-  EXPECT_CALL(*original_peer_,
-              OnReceivedDataInternal(StrEq(message.c_str()), message.length()));
+  EXPECT_CALL(*original_peer_, OnReceivedDataInternal(message));
 
   network::URLLoaderCompletionStatus status(net::OK);
   EXPECT_CALL(*original_peer_, OnCompletedRequest(status));
 
+  SetData(message);
   filter_peer_->OnCompletedRequest(status);
+  original_peer_->RunUntilBodyBecomesReady();
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 7fb3a19..f8cbe2c 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2902,7 +2902,6 @@
     "../browser/sync/session_sync_service_factory_unittest.cc",
     "../browser/sync/sessions/sync_sessions_web_contents_router_unittest.cc",
     "../browser/sync/sync_startup_tracker_unittest.cc",
-    "../browser/thumbnails/thumbnail_utils_unittest.cc",
     "../browser/tracing/background_tracing_field_trial_unittest.cc",
     "../browser/tracing/trace_event_system_stats_monitor_unittest.cc",
     "../browser/translate/chrome_translate_client_unittest.cc",
@@ -3025,6 +3024,7 @@
     sources += [
       "../browser/component_updater/crl_set_component_installer_unittest.cc",
       "../browser/ui/hats/hats_unittest.cc",
+      "../browser/ui/thumbnails/thumbnail_utils_unittest.cc",
       "../browser/ui/toolbar/app_menu_icon_controller_unittest.cc",
     ]
   }
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc
index e39f47f7..204f2a73 100644
--- a/chrome/test/base/test_browser_window.cc
+++ b/chrome/test/base/test_browser_window.cc
@@ -140,6 +140,11 @@
   return &page_action_icon_container_;
 }
 
+PageActionIconContainer*
+TestBrowserWindow::GetToolbarPageActionIconContainer() {
+  return nullptr;
+}
+
 ToolbarActionsBar* TestBrowserWindow::GetToolbarActionsBar() {
   return nullptr;
 }
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index b892b9d..610669df 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -88,6 +88,7 @@
   bool IsFullscreenBubbleVisible() const override;
   LocationBar* GetLocationBar() const override;
   PageActionIconContainer* GetPageActionIconContainer() override;
+  PageActionIconContainer* GetToolbarPageActionIconContainer() override;
   void SetFocusToLocationBar() override {}
   void UpdateReloadStopState(bool is_loading, bool force) override {}
   void UpdateToolbar(content::WebContents* contents) override {}
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js
index e64e54b2..895febc 100644
--- a/chrome/test/data/extensions/api_test/autotest_private/test.js
+++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -209,6 +209,14 @@
     chrome.autotestPrivate.runCrostiniUninstaller(chrome.test.callbackFail(
         'Crostini is not available for the current user'));
   },
+  function exportCrostini() {
+    chrome.autotestPrivate.exportCrostini('backup', chrome.test.callbackFail(
+        'Crostini is not available for the current user'));
+  },
+  function importCrostini() {
+    chrome.autotestPrivate.importCrostini('backup', chrome.test.callbackFail(
+        'Crostini is not available for the current user'));
+  },
   function takeScreenshot() {
     chrome.autotestPrivate.takeScreenshot(
       function(base64Png) {
diff --git a/chrome/test/data/extensions/csp/add_iframe_extension/content_script.js b/chrome/test/data/extensions/csp/add_iframe_extension/content_script.js
new file mode 100644
index 0000000..96771149
--- /dev/null
+++ b/chrome/test/data/extensions/csp/add_iframe_extension/content_script.js
@@ -0,0 +1,19 @@
+// 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.
+
+// Add a button to the page that can add a cross-origin iframe.
+const button = document.createElement('button');
+button.id = 'addIframeButton';
+button.innerText = 'Add Iframe';
+document.body.appendChild(button);
+
+// Adds an iframe. Notifies the test if it succeeds or fails.
+button.onclick = () => {
+  const frame = document.createElement('iframe');
+  frame.name = 'added-by-extension';
+  frame.src = `http://cross-origin.com:${location.port}` +
+      '/extensions/csp/success.html';
+  frame.onload = () => { window.domAutomationController.send(true); };
+  document.body.appendChild(frame);
+};
diff --git a/chrome/test/data/extensions/csp/add_iframe_extension/manifest.json b/chrome/test/data/extensions/csp/add_iframe_extension/manifest.json
new file mode 100644
index 0000000..c9fa5f1
--- /dev/null
+++ b/chrome/test/data/extensions/csp/add_iframe_extension/manifest.json
@@ -0,0 +1,12 @@
+{
+    "name": "Add iframe",
+    "version": "1",
+    "manifest_version": 2,
+    "content_scripts": [{
+        "js": ["content_script.js"],
+        "matches": ["*://*/*"]
+    }],
+    "permissions": [
+        "*://*/*"
+    ]
+}
diff --git a/chrome/test/data/extensions/csp/page_with_frame_csp.html b/chrome/test/data/extensions/csp/page_with_frame_csp.html
new file mode 100644
index 0000000..b07066f
--- /dev/null
+++ b/chrome/test/data/extensions/csp/page_with_frame_csp.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<title>page with frame csp</title>
+<script>
+function addIframe() {
+  const frame = document.createElement('iframe');
+  frame.name = 'added-by-page';
+  frame.src = `http://cross-origin.com:${location.port}` +
+      '/extensions/csp/success.html';
+  frame.onload = () => { window.domAutomationController.send(true); };
+  document.body.appendChild(frame);
+}
+</script>
+</html>
diff --git a/chrome/test/data/extensions/csp/page_with_frame_csp.html.mock-http-headers b/chrome/test/data/extensions/csp/page_with_frame_csp.html.mock-http-headers
new file mode 100644
index 0000000..6aa1fc9
--- /dev/null
+++ b/chrome/test/data/extensions/csp/page_with_frame_csp.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Content-Security-Policy: frame-src 'none'
diff --git a/chrome/test/data/extensions/csp/success.html b/chrome/test/data/extensions/csp/success.html
new file mode 100644
index 0000000..f3d7fd46
--- /dev/null
+++ b/chrome/test/data/extensions/csp/success.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Success</title>
+<script>
+// The test checks that this is set in order to see if the page loaded
+// successfully. The onload/onerror events on iframe are insufficient
+// because onload fires even if the frame is blocked due to CSP,
+// see https://crbug.com/365457.
+window.scriptExecuted = true;
+</script>
diff --git a/chrome/test/data/webui/print_preview/model_settings_availability_test.js b/chrome/test/data/webui/print_preview/model_settings_availability_test.js
index 0dd8f377..53906dc3 100644
--- a/chrome/test/data/webui/print_preview/model_settings_availability_test.js
+++ b/chrome/test/data/webui/print_preview/model_settings_availability_test.js
@@ -478,5 +478,27 @@
       model.set('documentSettings.isModifiable', false);
       assertFalse(model.settings.selectionOnly.available);
     });
+
+    if (cr.isChromeOS) {
+      test('pin', function() {
+        assertTrue(model.settings.pin.available);
+
+        // Remove pin capability.
+        let capabilities =
+            print_preview_test_utils.getCddTemplate(model.destination.id)
+                .capabilities;
+        delete capabilities.printer.pin;
+        model.set('destination.capabilities', capabilities);
+        assertFalse(model.settings.pin.available);
+
+        // Set not supported pin capability.
+        capabilities =
+            print_preview_test_utils.getCddTemplate(model.destination.id)
+                .capabilities;
+        capabilities.printer.pin.supported = false;
+        model.set('destination.capabilities', capabilities);
+        assertFalse(model.settings.pin.available);
+      });
+    }
   });
 });
diff --git a/chrome/test/data/webui/print_preview/model_settings_policy_test.js b/chrome/test/data/webui/print_preview/model_settings_policy_test.js
index dd5edc81..563132c4 100644
--- a/chrome/test/data/webui/print_preview/model_settings_policy_test.js
+++ b/chrome/test/data/webui/print_preview/model_settings_policy_test.js
@@ -194,5 +194,92 @@
             subtestParams.expectedEnforced, model.settings.duplex.setByPolicy);
       });
     });
+
+    test('pin managed', function() {
+      // Remove pin capability.
+      let capabilities =
+          print_preview_test_utils.getCddTemplate(model.destination.id)
+              .capabilities;
+      delete capabilities.printer.pin;
+
+      [{
+        // No policies, settings is modifiable.
+        pinCap: {supported: true},
+        expectedValue: false,
+        expectedAvailable: true,
+        expectedManaged: false,
+        expectedEnforced: false,
+      },
+       {
+         // Policy has no effect, setting unavailable.
+         pinCap: {},
+         pinPolicy: print_preview.PinModeRestriction.SECURE,
+         pinDefault: print_preview.PinModeRestriction.SECURE,
+         expectedValue: false,
+         expectedAvailable: false,
+         expectedManaged: false,
+         expectedEnforced: true,
+       },
+       {
+         // Policy has no effect, setting is not supported.
+         pinCap: {supported: false},
+         pinPolicy: print_preview.PinModeRestriction.NONE,
+         pinDefault: print_preview.PinModeRestriction.SECURE,
+         expectedValue: false,
+         expectedAvailable: false,
+         expectedManaged: false,
+         expectedEnforced: false,
+       },
+       {
+         // No restriction policy, setting is modifiable.
+         pinCap: {supported: true},
+         pinPolicy: print_preview.PinModeRestriction.NONE,
+         pinDefault: print_preview.PinModeRestriction.UNSECURE,
+         expectedValue: false,
+         expectedAvailable: true,
+         expectedManaged: false,
+         expectedEnforced: false,
+       },
+       {
+         // Policy overrides default.
+         pinCap: {supported: true},
+         pinPolicy: print_preview.PinModeRestriction.SECURE,
+         // Default mismatches restriction and is ignored.
+         pinDefault: print_preview.PinModeRestriction.UNSECURE,
+         expectedValue: true,
+         expectedAvailable: true,
+         expectedManaged: true,
+         expectedEnforced: true,
+       },
+       {
+         // Default defined by policy but setting is modifiable.
+         pinCap: {supported: true},
+         pinDefault: print_preview.PinModeRestriction.SECURE,
+         expectedValue: true,
+         expectedAvailable: true,
+         expectedManaged: false,
+         expectedEnforced: false,
+       }].forEach(subtestParams => {
+        capabilities =
+            print_preview_test_utils.getCddTemplate(model.destination.id)
+                .capabilities;
+        capabilities.printer.pin = subtestParams.pinCap;
+        const policies = {
+          allowedPinModes: subtestParams.pinPolicy,
+          defaultPinMode: subtestParams.pinDefault,
+        };
+        // In practice |capabilities| are always set after |policies| and
+        // observers only check for |capabilities|, so the order is important.
+        model.set('destination.policies', policies);
+        model.set('destination.capabilities', capabilities);
+        model.applyDestinationSpecificPolicies();
+        assertEquals(subtestParams.expectedValue, model.getSettingValue('pin'));
+        assertEquals(
+            subtestParams.expectedAvailable, model.settings.pin.available);
+        assertEquals(subtestParams.expectedManaged, model.controlsManaged);
+        assertEquals(
+            subtestParams.expectedEnforced, model.settings.pin.setByPolicy);
+      });
+    });
   });
 });
diff --git a/chrome/test/data/webui/print_preview/print_preview_test_utils.js b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
index 34dfce9..a047807 100644
--- a/chrome/test/data/webui/print_preview/print_preview_test_utils.js
+++ b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
@@ -28,7 +28,7 @@
    * @return {!print_preview.PrinterCapabilitiesResponse}
    */
   function getCddTemplate(printerId, opt_printerName) {
-    return {
+    const template = {
       printer: {
         deviceName: printerId,
         printerName: opt_printerName || '',
@@ -83,6 +83,10 @@
         }
       }
     };
+    if (cr.isChromeOS) {
+      template.capabilities.printer.pin = {supported: true};
+    }
+    return template;
   }
 
   /**
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 5cb6984..39f75fe 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -538,6 +538,26 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
+  void StartPluginVmDispatcher(PluginVmDispatcherCallback callback) override {
+    dbus::MethodCall method_call(debugd::kDebugdInterface,
+                                 debugd::kStartVmPluginDispatcher);
+    dbus::MessageWriter writer(&method_call);
+    debugdaemon_proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&DebugDaemonClientImpl::OnStartPluginVmDispatcher,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void StopPluginVmDispatcher(PluginVmDispatcherCallback callback) override {
+    dbus::MethodCall method_call(debugd::kDebugdInterface,
+                                 debugd::kStopVmPluginDispatcher);
+    dbus::MessageWriter writer(&method_call);
+    debugdaemon_proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&DebugDaemonClientImpl::OnStopPluginVmDispatcher,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
   void SetRlzPingSent(SetRlzPingSentCallback callback) override {
     dbus::MethodCall method_call(debugd::kDebugdInterface,
                                  debugd::kSetRlzPingSent);
@@ -751,10 +771,9 @@
                       dbus::Response* response,
                       dbus::ErrorResponse* err_response) {
     int32_t result;
-    dbus::MessageReader reader(response);
 
     // If we get a normal response, we need not examine the error response.
-    if (response && reader.PopInt32(&result)) {
+    if (response && dbus::MessageReader(response).PopInt32(&result)) {
       DCHECK_GE(result, 0);
       std::move(callback).Run(result);
       return;
@@ -775,18 +794,16 @@
                         const base::Closure& error_callback,
                         dbus::Response* response) {
     bool result = false;
-    dbus::MessageReader reader(response);
-    if (response && reader.PopBool(&result)) {
+    if (response && dbus::MessageReader(response).PopBool(&result))
       callback.Run(result);
-    } else {
+    else
       error_callback.Run();
-    }
   }
 
   void OnStartConcierge(ConciergeCallback callback, dbus::Response* response) {
     bool result = false;
-    dbus::MessageReader reader(response);
     if (response) {
+      dbus::MessageReader reader(response);
       reader.PopBool(&result);
     }
     std::move(callback).Run(result);
@@ -798,11 +815,28 @@
     std::move(callback).Run(response != nullptr);
   }
 
+  void OnStartPluginVmDispatcher(PluginVmDispatcherCallback callback,
+                                 dbus::Response* response) {
+    bool result = false;
+    if (response) {
+      dbus::MessageReader reader(response);
+      reader.PopBool(&result);
+    }
+    std::move(callback).Run(result);
+  }
+
+  void OnStopPluginVmDispatcher(PluginVmDispatcherCallback callback,
+                                dbus::Response* response) {
+    // Debugd just sends back an empty response, so we just check if
+    // the response exists
+    std::move(callback).Run(response != nullptr);
+  }
+
   void OnSetRlzPingSent(SetRlzPingSentCallback callback,
                         dbus::Response* response) {
     bool result = false;
-    dbus::MessageReader reader(response);
     if (response) {
+      dbus::MessageReader reader(response);
       reader.PopBool(&result);
     }
     std::move(callback).Run(result);
diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon_client.h
index a882ab6..ddd3a59 100644
--- a/chromeos/dbus/debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon_client.h
@@ -231,6 +231,16 @@
   // |callback| is called when the method finishes.
   virtual void StopConcierge(ConciergeCallback callback) = 0;
 
+  // A callback to handle the result of
+  // StartPluginVmDispatcher/StopPluginVmDispatcher.
+  using PluginVmDispatcherCallback = base::OnceCallback<void(bool success)>;
+  // Calls debugd::kStartVmPluginDispatcher, which starts the PluginVm
+  // dispatcher service. |callback| is called when the method finishes.
+  virtual void StartPluginVmDispatcher(PluginVmDispatcherCallback callback) = 0;
+  // Calls debug::kStopVmPluginDispatcher, which stops the PluginVm dispatcher
+  // service. |callback| is called when the method finishes.
+  virtual void StopPluginVmDispatcher(PluginVmDispatcherCallback callback) = 0;
+
   // A callback to handle the result of SetRlzPingSent.
   using SetRlzPingSentCallback = base::OnceCallback<void(bool success)>;
   // Calls debugd::kSetRlzPingSent, which sets |should_send_rlz_ping| in RW_VPD
diff --git a/chromeos/dbus/fake_debug_daemon_client.cc b/chromeos/dbus/fake_debug_daemon_client.cc
index 61395f6..146274bfe 100644
--- a/chromeos/dbus/fake_debug_daemon_client.cc
+++ b/chromeos/dbus/fake_debug_daemon_client.cc
@@ -268,6 +268,18 @@
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
+void FakeDebugDaemonClient::StartPluginVmDispatcher(
+    PluginVmDispatcherCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), true));
+}
+
+void FakeDebugDaemonClient::StopPluginVmDispatcher(
+    PluginVmDispatcherCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), true));
+}
+
 void FakeDebugDaemonClient::SetRlzPingSent(SetRlzPingSentCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), true));
diff --git a/chromeos/dbus/fake_debug_daemon_client.h b/chromeos/dbus/fake_debug_daemon_client.h
index 24879d04..dc9f235 100644
--- a/chromeos/dbus/fake_debug_daemon_client.h
+++ b/chromeos/dbus/fake_debug_daemon_client.h
@@ -89,6 +89,8 @@
                          const base::Closure& error_callback) override;
   void StartConcierge(ConciergeCallback callback) override;
   void StopConcierge(ConciergeCallback callback) override;
+  void StartPluginVmDispatcher(PluginVmDispatcherCallback callback) override;
+  void StopPluginVmDispatcher(PluginVmDispatcherCallback callback) override;
   void SetRlzPingSent(SetRlzPingSentCallback callback) override;
   void SetSchedulerConfiguration(const std::string& config_name,
                                  VoidDBusMethodCallback callback) override;
diff --git a/chromeos/services/ime/public/cpp/shared_lib/interfaces.h b/chromeos/services/ime/public/cpp/shared_lib/interfaces.h
index babb647..e1eb5e8 100644
--- a/chromeos/services/ime/public/cpp/shared_lib/interfaces.h
+++ b/chromeos/services/ime/public/cpp/shared_lib/interfaces.h
@@ -66,7 +66,7 @@
 // `ImeEngineMainEntry` and be always owned by the IME service.
 class Platform {
  protected:
-  ~Platform() = default;
+  virtual ~Platform() = default;
 
  public:
   // The three methods below are Getters of the local data directories on the
@@ -95,7 +95,7 @@
 // IME service will create then pass it to the engine.
 class ImeClientDelegate {
  protected:
-  ~ImeClientDelegate() = default;
+  virtual ~ImeClientDelegate() = default;
 
  public:
   // Returns the c_str() of the internal IME specification of ImeClientDelegate.
@@ -118,7 +118,7 @@
 // function to the IME service.
 class ImeEngineMainEntry {
  protected:
-  ~ImeEngineMainEntry() = default;
+  virtual ~ImeEngineMainEntry() = default;
 
  public:
   // Returns whether a specific IME is supported by this IME shared library.
diff --git a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
index e293d4f..87033ee 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
+++ b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
@@ -47,6 +47,23 @@
 
 AutofillWalletModelTypeController::~AutofillWalletModelTypeController() {}
 
+void AutofillWalletModelTypeController::Stop(
+    syncer::ShutdownReason shutdown_reason,
+    StopCallback callback) {
+  DCHECK(CalledOnValidThread());
+  switch (shutdown_reason) {
+    case syncer::STOP_SYNC:
+      // Special case: For AUTOFILL_WALLET_DATA and AUTOFILL_WALLET_METADATA, we
+      // want to clear all data even when Sync is stopped temporarily.
+      shutdown_reason = syncer::DISABLE_SYNC;
+      break;
+    case syncer::DISABLE_SYNC:
+    case syncer::BROWSER_SHUTDOWN:
+      break;
+  }
+  ModelTypeController::Stop(shutdown_reason, std::move(callback));
+}
+
 bool AutofillWalletModelTypeController::ReadyForStart() const {
   DCHECK(CalledOnValidThread());
   return currently_enabled_;
diff --git a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
index 33726ed..ecfd8ec 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
+++ b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
@@ -39,6 +39,8 @@
   ~AutofillWalletModelTypeController() override;
 
   // DataTypeController overrides.
+  void Stop(syncer::ShutdownReason shutdown_reason,
+            StopCallback callback) override;
   bool ReadyForStart() const override;
 
  private:
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index 7ce02840..d61ac32e 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -88,7 +88,9 @@
   // This is to initialize StrikeDatabase is if it hasn't been already, so that
   // its cache would be loaded and ready to use when the first CCSM is created.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+          features::kAutofillSaveCreditCardUsesStrikeSystemV2) ||
+      base::FeatureList::IsEnabled(
+          features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
     // Only init when |kAutofillSaveCreditCardUsesStrikeSystemV2| is enabled. If
     // flag is off and LegacyStrikeDatabase instead of StrikeDatabase is used,
     // this init will cause failure on GetStrikes().
@@ -584,13 +586,6 @@
             /*is_local=*/true,
             GetCreditCardSaveStrikeDatabase()->GetStrikes(base::UTF16ToUTF8(
                 local_card_save_candidate_.LastFourDigits())));
-        if (base::FeatureList::IsEnabled(
-                features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
-          GetLocalCardMigrationStrikeDatabase()->RemoveStrikes(
-              LocalCardMigrationStrikeDatabase::
-                  kStrikesToRemoveWhenLocalCardAdded);
-        }
-
         // Clear all CreditCardSave strikes for this card, in case it is later
         // removed.
         GetCreditCardSaveStrikeDatabase()->ClearStrikes(
@@ -613,6 +608,12 @@
                 base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())),
             base::DoNothing());
       }
+      if (base::FeatureList::IsEnabled(
+              features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
+        GetLocalCardMigrationStrikeDatabase()->RemoveStrikes(
+            LocalCardMigrationStrikeDatabase::
+                kStrikesToRemoveWhenLocalCardAdded);
+      }
 
       personal_data_manager_->OnAcceptedLocalCreditCardSave(
           local_card_save_candidate_);
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
index d0d990d..28a19571 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -5404,7 +5404,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
@@ -5460,7 +5459,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager.cc b/components/autofill/core/browser/payments/local_card_migration_manager.cc
index 2091f743..2db9d14b 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager.cc
@@ -45,7 +45,9 @@
   // This is to initialize StrikeDatabase is if it hasn't been already, so that
   // its cache would be loaded and ready to use when the first LCMM is created.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+          features::kAutofillSaveCreditCardUsesStrikeSystemV2) ||
+      base::FeatureList::IsEnabled(
+          features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
     // Only init when |kAutofillSaveCreditCardUsesStrikeSystemV2| is enabled. If
     // flag is off and LegacyStrikeDatabase instead of StrikeDatabase is used,
     // this init will cause failure on GetStrikes().
@@ -76,8 +78,6 @@
 
   // Don't show the prompt if max strike count was reached.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2) &&
-      base::FeatureList::IsEnabled(
           features::kAutofillLocalCardMigrationUsesStrikeSystemV2) &&
       GetLocalCardMigrationStrikeDatabase()->IsMaxStrikesLimitReached()) {
     switch (imported_credit_card_record_type) {
@@ -153,8 +153,6 @@
 
   // Log number of LocalCardMigration strikes when migration was accepted.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2) &&
-      base::FeatureList::IsEnabled(
           features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
     base::UmaHistogramCounts1000(
         "Autofill.StrikeDatabase.StrikesPresentWhenLocalCardMigrationAccepted",
@@ -164,8 +162,6 @@
   // If there are cards which aren't selected, add 3 strikes to
   // LocalCardMigrationStrikeDatabase.
   if (base::FeatureList::IsEnabled(
-          features::kAutofillSaveCreditCardUsesStrikeSystemV2) &&
-      base::FeatureList::IsEnabled(
           features::kAutofillLocalCardMigrationUsesStrikeSystemV2) &&
       (selected_card_guids.size() < migratable_credit_cards_.size())) {
     GetLocalCardMigrationStrikeDatabase()->AddStrikes(
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
index 4313fc85..2dc5cf0f 100644
--- a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -1107,7 +1107,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
@@ -1157,7 +1156,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
@@ -1211,7 +1209,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
@@ -1243,7 +1240,6 @@
   scoped_feature_list_.InitWithFeatures(
       // Enabled
       {features::kAutofillCreditCardLocalCardMigration,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2,
        features::kAutofillLocalCardMigrationUsesStrikeSystemV2},
       // Disabled
       {});
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
index ef98a6c..d5eab46 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -406,6 +406,27 @@
       entity_data.specifics.wallet_metadata().id());
 }
 
+void AutofillWalletMetadataSyncBridge::ApplyStopSyncChanges(
+    std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) {
+  // If a metadata change list gets passed in, that means sync is actually
+  // disabled, so we want to delete the data as well (i.e. the wallet metadata
+  // entities).
+  if (delete_metadata_change_list) {
+    bool is_any_local_modified = false;
+    for (const std::pair<std::string, AutofillMetadata>& pair : cache_) {
+      TypeAndMetadataId parsed_storage_key =
+          ParseWalletMetadataStorageKey(pair.first);
+      is_any_local_modified |=
+          RemoveServerMetadata(GetAutofillTable(), parsed_storage_key.type,
+                               parsed_storage_key.metadata_id);
+    }
+    cache_.clear();
+    if (is_any_local_modified) {
+      web_data_backend_->NotifyOfMultipleAutofillChanges();
+    }
+  }
+}
+
 void AutofillWalletMetadataSyncBridge::AutofillProfileChanged(
     const AutofillProfileChange& change) {
   // Skip local profiles (if possible, i.e. if it is not a deletion where
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
index 940094f..59428a9 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
@@ -74,6 +74,8 @@
   void GetAllDataForDebugging(DataCallback callback) override;
   std::string GetClientTag(const syncer::EntityData& entity_data) override;
   std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+  void ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList>
+                                delete_metadata_change_list) override;
 
   // AutofillWebDataServiceObserverOnDBSequence implementation.
   void AutofillProfileChanged(const AutofillProfileChange& change) override;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
index 0635a8d..d58556f 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
@@ -293,6 +293,12 @@
         mock_processor_.CreateForwardingProcessor(), &backend_));
   }
 
+  void StopSyncing() {
+    real_processor_->OnSyncStopping(syncer::CLEAR_METADATA);
+  }
+
+  void Shutdown() { real_processor_->OnSyncStopping(syncer::KEEP_METADATA); }
+
   void StartSyncing(
       const std::vector<WalletMetadataSpecifics>& remote_data = {}) {
     base::RunLoop loop;
@@ -564,6 +570,47 @@
                                    EqualsSpecifics(card_specifics)));
 }
 
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+       ApplyStopSyncChanges_ShouldWipeLocalDataWhenSyncStopped) {
+  // Perform initial sync to create sync data & metadata.
+  ResetBridge(/*initial_sync_done=*/false);
+  WalletMetadataSpecifics profile =
+      CreateWalletMetadataSpecificsForAddressWithDetails(
+          kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
+  WalletMetadataSpecifics card =
+      CreateWalletMetadataSpecificsForCardWithDetails(
+          kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40);
+  StartSyncing({profile, card});
+
+  // Now stop sync. This should wipe the data and notify the backend.
+  EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  StopSyncing();
+
+  EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+       ApplyStopSyncChanges_ShouldKeepLocalDataOnShutdown) {
+  // Perform initial sync to create sync data & metadata.
+  ResetBridge(/*initial_sync_done=*/false);
+  WalletMetadataSpecifics profile =
+      CreateWalletMetadataSpecificsForAddressWithDetails(
+          kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20);
+  WalletMetadataSpecifics card =
+      CreateWalletMetadataSpecificsForCardWithDetails(
+          kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40);
+  StartSyncing({profile, card});
+
+  // Now simulate shutting down the browser. This should not touch any of the
+  // data and thus also not notify the backend.
+  EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+  Shutdown();
+
+  EXPECT_THAT(
+      GetAllLocalDataInclRestart(),
+      UnorderedElementsAre(EqualsSpecifics(profile), EqualsSpecifics(card)));
+}
+
 // Verify that lower values of metadata are not sent to the sync server when
 // local metadata is updated.
 TEST_F(AutofillWalletMetadataSyncBridgeTest,
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index 6fe3627..cbbf98e 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -198,7 +198,9 @@
     return error;
   }
 
-  SetSyncData(entity_data);
+  // We want to notify the metadata bridge about all changes so that the
+  // metadata bridge can track changes in the data bridge and react accordingly.
+  SetSyncData(entity_data, /*notify_metadata_bridge=*/true);
 
   // After the first sync, we are sure that initial sync is done.
   if (!initial_sync_done_) {
@@ -277,7 +279,10 @@
       SyncWalletDataRecordClearedEntitiesCount(count);
     }
 
-    SetSyncData(syncer::EntityChangeList());
+    // Do not notify the metadata bridge because we do not want to upstream the
+    // deletions. The metadata bridge deletes its data independently when sync
+    // gets stopped.
+    SetSyncData(syncer::EntityChangeList(), /*notify_metadata_bridge=*/false);
 
     initial_sync_done_ = false;
   }
@@ -323,7 +328,8 @@
 }
 
 void AutofillWalletSyncBridge::SetSyncData(
-    const syncer::EntityChangeList& entity_data) {
+    const syncer::EntityChangeList& entity_data,
+    bool notify_metadata_bridge) {
   bool wallet_data_changed = false;
 
   // Extract the Autofill types from the sync |entity_data|.
@@ -336,10 +342,10 @@
   bool should_log_diff;
   wallet_data_changed |=
       SetPaymentsCustomerData(std::move(customer_data), &should_log_diff);
-  wallet_data_changed |=
-      SetWalletCards(std::move(wallet_cards), should_log_diff);
-  wallet_data_changed |=
-      SetWalletAddresses(std::move(wallet_addresses), should_log_diff);
+  wallet_data_changed |= SetWalletCards(
+      std::move(wallet_cards), should_log_diff, notify_metadata_bridge);
+  wallet_data_changed |= SetWalletAddresses(
+      std::move(wallet_addresses), should_log_diff, notify_metadata_bridge);
 
   if (web_data_backend_ && wallet_data_changed)
     web_data_backend_->NotifyOfMultipleAutofillChanges();
@@ -347,7 +353,8 @@
 
 bool AutofillWalletSyncBridge::SetWalletCards(
     std::vector<CreditCard> wallet_cards,
-    bool log_diff) {
+    bool log_diff,
+    bool notify_metadata_bridge) {
   // Users can set billing address of the server credit card locally, but that
   // information does not propagate to either Chrome Sync or Google Payments
   // server. To preserve user's preferred billing address and most recent use
@@ -379,8 +386,11 @@
     } else {
       table->SetServerCreditCards(wallet_cards);
     }
-    for (const CreditCardChange& change : diff.changes)
-      web_data_backend_->NotifyOfCreditCardChanged(change);
+    if (notify_metadata_bridge) {
+      for (const CreditCardChange& change : diff.changes) {
+        web_data_backend_->NotifyOfCreditCardChanged(change);
+      }
+    }
     return true;
   }
   return false;
@@ -388,7 +398,8 @@
 
 bool AutofillWalletSyncBridge::SetWalletAddresses(
     std::vector<AutofillProfile> wallet_addresses,
-    bool log_diff) {
+    bool log_diff,
+    bool notify_metadata_bridge) {
   // In the common case, the database won't have changed. Committing an update
   // to the database will require at least one DB page write and will schedule
   // a fsync. To avoid this I/O, it should be more efficient to do a read and
@@ -415,8 +426,11 @@
     } else {
       table->SetServerProfiles(wallet_addresses);
     }
-    for (const AutofillProfileChange& change : diff.changes)
-      web_data_backend_->NotifyOfAutofillProfileChanged(change);
+    if (notify_metadata_bridge) {
+      for (const AutofillProfileChange& change : diff.changes) {
+        web_data_backend_->NotifyOfAutofillProfileChanged(change);
+      }
+    }
     return true;
   }
   return false;
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
index 3f91a3c..3fbf638 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -88,8 +88,10 @@
   void GetAllDataImpl(DataCallback callback, bool enforce_utf8);
 
   // Sets the wallet data from |entity_data| to this client and records metrics
-  // about added/deleted data.
-  void SetSyncData(const syncer::EntityChangeList& entity_data);
+  // about added/deleted data. If |notify_metadata_bridge|, it also notifies
+  // the metadata sync bridge about individual changes.
+  void SetSyncData(const syncer::EntityChangeList& entity_data,
+                   bool notify_metadata_bridge);
 
   // Sets |customer_data| to this client and returns whether any change has been
   // applied (i.e., whether |customer_data| was different from local data) and
@@ -100,14 +102,21 @@
 
   // Sets |wallet_cards| to this client, records metrics about added/deleted
   // data (if |log_diff| is true) and returns whether any change has been
-  // applied (i.e., whether |wallet_cards| was different from local data).
-  bool SetWalletCards(std::vector<CreditCard> wallet_cards, bool log_diff);
+  // applied (i.e., whether |wallet_cards| was different from local data). If
+  // |notify_metadata_bridge|, it also notifies via WebDataBackend about any
+  // individual entity changes.
+  bool SetWalletCards(std::vector<CreditCard> wallet_cards,
+                      bool log_diff,
+                      bool notify_metadata_bridge);
 
   // Sets |wallet_addresses| to this client, records metrics about added/deleted
   // data (if |log_diff| is true) and returns whether any change has been
   // applied (i.e., whether |wallet_addresses| was different from local data).
+  // If |notify_metadata_bridge|, it also notifies via WebDataBackend about any
+  // individual entity changes.
   bool SetWalletAddresses(std::vector<AutofillProfile> wallet_addresses,
-                          bool log_diff);
+                          bool log_diff,
+                          bool notify_metadata_bridge);
 
   // Computes a "diff" (items added, items removed) of two vectors of items,
   // which should be either CreditCard or AutofillProfile. This is used for
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index af355624..abcc0b2 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -818,10 +818,9 @@
   table()->SetServerCreditCards({local_card});
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
-  EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
-                              RemoveChange(local_profile.server_id())));
-  EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
+  EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0);
+  EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0);
+
   // Passing in a non-null metadata change list indicates to the bridge that
   // sync is stopping because it was disabled.
   bridge()->ApplyStopSyncChanges(
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 4783ffa..c89587fb 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -106,6 +106,11 @@
     "AutofillEnableLocalCardMigrationForNonSyncUser",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// When enabled, Autofill data related icons will be shown in the status
+// chip in toolbar along with the avatar toolbar button.
+const base::Feature kAutofillEnableToolbarStatusChip{
+    "AutofillEnableToolbarStatusChip", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // When enabled, no local copy of server card will be saved when upload
 // succeeds.
 const base::Feature kAutofillNoLocalSaveOnUploadSuccess{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 492f662a..e9c0156 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -41,6 +41,7 @@
 extern const base::Feature kAutofillEnableCompanyName;
 extern const base::Feature kAutofillEnableIFrameSupportOniOS;
 extern const base::Feature kAutofillEnableLocalCardMigrationForNonSyncUser;
+extern const base::Feature kAutofillEnableToolbarStatusChip;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForQuery;
 extern const base::Feature kAutofillEnforceMinRequiredFieldsForUpload;
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index eac9c919..303cb650 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -448,8 +448,9 @@
       sync_prefs_.AsWeakPtr());
 
   // Clear any old errors the first time sync starts.
-  if (!IsFirstSetupComplete())
-    ClearStaleErrors();
+  if (!IsFirstSetupComplete()) {
+    last_actionable_error_ = syncer::SyncProtocolError();
+  }
 
   if (!sync_thread_) {
     sync_thread_ = std::make_unique<base::Thread>("Chrome_SyncThread");
@@ -757,14 +758,6 @@
     observer.OnSyncShutdown(this);
 }
 
-void ProfileSyncService::ClearStaleErrors() {
-  ClearUnrecoverableError();
-  last_actionable_error_ = syncer::SyncProtocolError();
-  // Clear the data type errors as well.
-  if (data_type_manager_)
-    data_type_manager_->ResetDataTypeErrors();
-}
-
 void ProfileSyncService::ClearUnrecoverableError() {
   unrecoverable_error_reason_ = ERROR_REASON_UNSET;
   unrecoverable_error_message_.clear();
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 94118ad..6a228f2b 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -424,8 +424,6 @@
   void NotifySyncCycleCompleted();
   void NotifyShutdown();
 
-  void ClearStaleErrors();
-
   void ClearUnrecoverableError();
 
   // Kicks off asynchronous initialization of the SyncEngine.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 3a54223..169d63ae 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -664,6 +664,10 @@
       // Hostnames with no dot in them.
       "<local>,"
 
+      // WebSockets
+      "ws://*,"
+      "wss://*,"
+
       // RFC6890 current network (only valid as source address).
       "0.0.0.0/8,"
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index 4b3a1d1..c34ddde5 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -389,12 +389,17 @@
 
   // Set an alternate proxy list to be used for media requests which only
   // contains proxies supporting the media resource type.
-  net::ProxyList media_proxies;
+  std::vector<DataReductionProxyServer> media_proxies;
   for (const auto& proxy : proxies_for_http) {
     if (proxy.SupportsResourceType(ResourceTypeProvider::CONTENT_TYPE_MEDIA))
-      media_proxies.AddProxyServer(proxy.proxy_server());
+      media_proxies.push_back(proxy);
   }
-  config->alternate_proxy_list = media_proxies;
+  config->alternate_rules =
+      configurator_
+          ->CreateProxyConfig(true /* probe_url_config */,
+                              config_->GetNetworkPropertiesManager(),
+                              media_proxies)
+          .proxy_rules();
 
   net::EffectiveConnectionType type = GetEffectiveConnectionType();
   if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index ca981e2a..9ebaa95 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -275,7 +275,7 @@
   EXPECT_TRUE(
       client.config->pre_cache_headers.HasHeader(chrome_proxy_ect_header()));
   // Alternate proxy list should be empty because there are no core proxies.
-  EXPECT_TRUE(client.config->alternate_proxy_list.IsEmpty());
+  EXPECT_TRUE(client.config->alternate_rules.empty());
 }
 
 TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigUpdatedOnECTChange) {
@@ -400,9 +400,12 @@
   io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
   base::RunLoop().RunUntilIdle();
 
-  net::ProxyList expected_proxy_list;
-  expected_proxy_list.SetSingleProxyServer(core_proxy_server);
-  EXPECT_TRUE(client.config->alternate_proxy_list.Equals(expected_proxy_list));
+  net::ProxyConfig::ProxyRules expected_rules;
+  expected_rules.type =
+      net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
+  expected_rules.proxies_for_http.AddProxyServer(core_proxy_server);
+  expected_rules.proxies_for_http.AddProxyServer(net::ProxyServer::Direct());
+  EXPECT_TRUE(client.config->alternate_rules.Equals(expected_rules));
 }
 
 }  // namespace data_reduction_proxy
diff --git a/components/leveldb_proto/internal/proto_database_impl.h b/components/leveldb_proto/internal/proto_database_impl.h
index 61a7c0f..0b23b981 100644
--- a/components/leveldb_proto/internal/proto_database_impl.h
+++ b/components/leveldb_proto/internal/proto_database_impl.h
@@ -198,12 +198,11 @@
 template <typename P>
 std::unique_ptr<P> ParseToProto(const std::string& serialized_entry) {
   auto proto = std::make_unique<P>();
-  if (proto->ParseFromString(serialized_entry)) {
-    return proto;
-  } else {
+  if (!proto->ParseFromString(serialized_entry)) {
     DLOG(WARNING) << "Unable to parse leveldb_proto entry";
-    return std::make_unique<P>();
+    proto.reset(new P);
   }
+  return proto;
 }
 
 template <typename P,
diff --git a/components/password_manager/core/browser/new_password_form_manager.cc b/components/password_manager/core/browser/new_password_form_manager.cc
index f06f8b19..014f915f 100644
--- a/components/password_manager/core/browser/new_password_form_manager.cc
+++ b/components/password_manager/core/browser/new_password_form_manager.cc
@@ -152,12 +152,6 @@
   if (owned_form_fetcher_)
     owned_form_fetcher_->Fetch();
   form_fetcher_->AddConsumer(this);
-
-  // The following code is for development and debugging purposes.
-  // TODO(https://crbug.com/831123): remove it when NewPasswordFormManager will
-  // be production ready.
-  if (password_manager_util::IsLoggingActive(client_))
-    ParseFormAndMakeLogging(observed_form_, FormDataParser::Mode::kFilling);
 }
 NewPasswordFormManager::~NewPasswordFormManager() = default;
 
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 758ecfef..2b9aeb40 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -463,6 +463,7 @@
     "model_impl/sync_metadata_store_change_list.h",
     "model_impl/syncable_service_based_bridge.cc",
     "model_impl/syncable_service_based_bridge.h",
+    "nigori/nigori_sync_bridge.h",
     "protocol/proto_enum_conversions.cc",
     "protocol/proto_enum_conversions.h",
     "protocol/proto_memory_estimations.cc",
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc
index 7fd22ee..7398c6ca 100644
--- a/components/sync/driver/model_type_controller.cc
+++ b/components/sync/driver/model_type_controller.cc
@@ -162,13 +162,6 @@
   SyncStopMetadataFate metadata_fate = KEEP_METADATA;
   switch (shutdown_reason) {
     case STOP_SYNC:
-      // Special case: For AUTOFILL_WALLET_DATA, we want to clear all data even
-      // when Sync is stopped temporarily.
-      // TODO(crbug.com/890361,crbug.com/890737): Move this into the
-      // Wallet-specific ModelTypeController once we have one.
-      if (type() == AUTOFILL_WALLET_DATA) {
-        metadata_fate = CLEAR_METADATA;
-      }
       break;
     case DISABLE_SYNC:
       metadata_fate = CLEAR_METADATA;
diff --git a/components/sync/nigori/DEPS b/components/sync/nigori/DEPS
new file mode 100644
index 0000000..8117313
--- /dev/null
+++ b/components/sync/nigori/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/sync/model",
+]
diff --git a/components/sync/nigori/nigori_sync_bridge.h b/components/sync/nigori/nigori_sync_bridge.h
new file mode 100644
index 0000000..3c1944ff
--- /dev/null
+++ b/components/sync/nigori/nigori_sync_bridge.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_H_
+#define COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "components/sync/model/conflict_resolution.h"
+#include "components/sync/model/model_error.h"
+
+namespace syncer {
+
+struct EntityData;
+
+// Interface implemented by Nigori model to receive Nigori updates from sync via
+// a ModelTypeChangeProcessor. Provides a way for sync to update the data and
+// metadata for Nigori entities, as well as the model type state.
+class NigoriSyncBridge {
+ public:
+  NigoriSyncBridge() = default;
+
+  virtual ~NigoriSyncBridge() = default;
+
+  // Perform the initial merge between local and sync data.
+  virtual base::Optional<ModelError> MergeSyncData(
+      const base::Optional<EntityData>& data) = 0;
+
+  // Apply changes from the sync server locally.
+  virtual base::Optional<ModelError> ApplySyncChanges(
+      const EntityData& data) = 0;
+
+  // Retrieve Nigori sync data.
+  virtual std::unique_ptr<EntityData> GetData() = 0;
+
+  // Resolve a conflict between the client and server versions of data. They are
+  // guaranteed not to match (both be deleted or have identical specifics).
+  virtual ConflictResolution ResolveConflict(const EntityData& local_data,
+                                             const EntityData& remote_data) = 0;
+
+  // Informs the bridge that sync has been disabed. The bridge is responsible
+  // for deleting all data and metadata upon disabling sync.
+  virtual void ApplyDisableSyncChanges() = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NigoriSyncBridge);
+};
+
+}  // namespace syncer
+
+#endif  // COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_H_
diff --git a/components/sync/syncable/nigori_util.cc b/components/sync/syncable/nigori_util.cc
index e331b4a..c4c62ce 100644
--- a/components/sync/syncable/nigori_util.cc
+++ b/components/sync/syncable/nigori_util.cc
@@ -13,6 +13,7 @@
 
 #include "base/containers/queue.h"
 #include "base/json/json_writer.h"
+#include "base/metrics/histogram_macros.h"
 #include "components/sync/base/cryptographer.h"
 #include "components/sync/base/passphrase_enums.h"
 #include "components/sync/syncable/directory.h"
@@ -211,6 +212,9 @@
           generated_specifics.SerializeAsString()) {
     DVLOG(2) << "Specifics of type " << ModelTypeToString(type)
              << " already match, dropping change.";
+    UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeRedundantPut",
+                              ModelTypeToHistogramInt(type),
+                              static_cast<int>(MODEL_TYPE_COUNT));
     return true;
   }
 
diff --git a/components/viz/test/data/rotated_drop_shadow_filter_gl.png b/components/viz/test/data/rotated_drop_shadow_filter_gl.png
index e4cf583..4daba0dd 100644
--- a/components/viz/test/data/rotated_drop_shadow_filter_gl.png
+++ b/components/viz/test/data/rotated_drop_shadow_filter_gl.png
Binary files differ
diff --git a/components/viz/test/data/rotated_filter_gl.png b/components/viz/test/data/rotated_filter_gl.png
index a4e3cede..0554cdc 100644
--- a/components/viz/test/data/rotated_filter_gl.png
+++ b/components/viz/test/data/rotated_filter_gl.png
Binary files differ
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 5408e38e..37d18bd 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -477,8 +477,6 @@
     "background_fetch/storage/start_next_pending_request_task.h",
     "background_sync/background_sync_context_impl.cc",
     "background_sync/background_sync_context_impl.h",
-    "background_sync/background_sync_launcher.cc",
-    "background_sync/background_sync_launcher.h",
     "background_sync/background_sync_manager.cc",
     "background_sync/background_sync_manager.h",
     "background_sync/background_sync_metrics.cc",
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 10581cd4..8138c80 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -156,6 +156,9 @@
     case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
       FireDescriptionChangedEvent(node);
       break;
+    case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
+      FireEvent(node, ax::mojom::Event::kInvalidStatusChanged);
+      break;
     default:
       // Need to implement.
       break;
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index a33f7bc..6ee7a8e 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -281,8 +281,9 @@
   RunEventTest(FILE_PATH_LITERAL("aria-spinbutton-valuetext-change.html"));
 }
 
+// https://crbug.com/941919
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
-                       AccessibilityEventsAddAlert) {
+                       DISABLED_AccessibilityEventsAddAlert) {
   RunEventTest(FILE_PATH_LITERAL("add-alert.html"));
 }
 
@@ -324,6 +325,11 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
+                       AccessibilityEventsCheckboxValidity) {
+  RunEventTest(FILE_PATH_LITERAL("checkbox-validity.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
                        AccessibilityEventsCSSDisplay) {
   RunEventTest(FILE_PATH_LITERAL("css-display.html"));
 }
diff --git a/content/browser/background_sync/background_sync_context_impl.cc b/content/browser/background_sync/background_sync_context_impl.cc
index 231111d..e2e9b9ce 100644
--- a/content/browser/background_sync/background_sync_context_impl.cc
+++ b/content/browser/background_sync/background_sync_context_impl.cc
@@ -9,8 +9,6 @@
 #include "base/bind.h"
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
-#include "build/build_config.h"
-#include "content/browser/background_sync/background_sync_launcher.h"
 #include "content/browser/background_sync/background_sync_manager.h"
 #include "content/browser/background_sync/background_sync_service_impl.h"
 #include "content/browser/devtools/devtools_background_services_context.h"
@@ -82,32 +80,10 @@
   background_sync_manager_ = std::move(manager);
 }
 
-void BackgroundSyncContextImpl::set_wakeup_delta_for_testing(
-    base::TimeDelta wakeup_delta) {
-  test_wakeup_delta_ = wakeup_delta;
-}
-
-base::TimeDelta BackgroundSyncContextImpl::GetSoonestWakeupDelta() {
-  if (!test_wakeup_delta_.is_max())
-    return test_wakeup_delta_;
-
-  if (!background_sync_manager_)
-    return base::TimeDelta::Max();
-
-  return background_sync_manager_->GetSoonestWakeupDelta();
-}
-
-void BackgroundSyncContextImpl::GetSoonestWakeupDeltaAcrossPartitions(
-    BrowserContext* browser_context,
-    base::OnceCallback<void(base::TimeDelta)> callback) {
-  DCHECK(browser_context);
-
-  BackgroundSyncLauncher::GetSoonestWakeupDelta(browser_context,
-                                                std::move(callback));
-}
-
-void BackgroundSyncContextImpl::FireBackgroundSyncEvents(
+void BackgroundSyncContextImpl::FireBackgroundSyncEventsForStoragePartition(
+    content::StoragePartition* storage_partition,
     base::OnceClosure done_closure) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!background_sync_manager_) {
     std::move(done_closure).Run();
     return;
@@ -116,15 +92,6 @@
       std::move(done_closure));
 }
 
-#if defined(OS_ANDROID)
-void BackgroundSyncContextImpl::FireBackgroundSyncEventsAcrossPartitions(
-    BrowserContext* browser_context,
-    const base::android::JavaParamRef<jobject>& j_runnable) {
-  DCHECK(browser_context);
-  BackgroundSyncLauncher::FireBackgroundSyncEvents(browser_context, j_runnable);
-}
-#endif
-
 void BackgroundSyncContextImpl::CreateBackgroundSyncManager(
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
     scoped_refptr<DevToolsBackgroundServicesContext> devtools_context) {
diff --git a/content/browser/background_sync/background_sync_context_impl.h b/content/browser/background_sync/background_sync_context_impl.h
index 68c33276..9365f80b 100644
--- a/content/browser/background_sync/background_sync_context_impl.h
+++ b/content/browser/background_sync/background_sync_context_impl.h
@@ -11,8 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/background_sync_context.h"
 #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h"
@@ -56,16 +54,9 @@
   BackgroundSyncManager* background_sync_manager() const;
 
   // BackgroundSyncContext implementation.
-  void FireBackgroundSyncEvents(base::OnceClosure done_closure) override;
-#if defined(OS_ANDROID)
-  void FireBackgroundSyncEventsAcrossPartitions(
-      BrowserContext* browser_context,
-      const base::android::JavaParamRef<jobject>& j_runnable) override;
-#endif
-  base::TimeDelta GetSoonestWakeupDelta() override;
-  void GetSoonestWakeupDeltaAcrossPartitions(
-      BrowserContext* browser_context,
-      base::OnceCallback<void(base::TimeDelta)> callback) override;
+  void FireBackgroundSyncEventsForStoragePartition(
+      content::StoragePartition* storage_partition,
+      base::OnceClosure done_closure) override;
 
  protected:
   friend class base::RefCountedDeleteOnSequence<BackgroundSyncContextImpl>;
@@ -74,11 +65,9 @@
 
   void set_background_sync_manager_for_testing(
       std::unique_ptr<BackgroundSyncManager> manager);
-  void set_wakeup_delta_for_testing(base::TimeDelta wakeup_delta);
 
  private:
   friend class BackgroundSyncServiceImplTest;
-  friend class BackgroundSyncLauncherTest;
 
   virtual void CreateBackgroundSyncManager(
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
@@ -98,7 +87,6 @@
   std::map<BackgroundSyncServiceImpl*,
            std::unique_ptr<BackgroundSyncServiceImpl>>
       services_;
-  base::TimeDelta test_wakeup_delta_ = base::TimeDelta::Max();
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundSyncContextImpl);
 };
diff --git a/content/browser/background_sync/background_sync_launcher.cc b/content/browser/background_sync/background_sync_launcher.cc
deleted file mode 100644
index efab1e5..0000000
--- a/content/browser/background_sync/background_sync_launcher.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/background_sync/background_sync_launcher.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/public/browser/background_sync_context.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/storage_partition.h"
-#if defined(OS_ANDROID)
-#include "base/android/callback_android.h"
-#include "base/barrier_closure.h"
-#endif
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<BackgroundSyncLauncher>::DestructorAtExit
-    g_background_sync_launcher = LAZY_INSTANCE_INITIALIZER;
-
-#if defined(OS_ANDROID)
-unsigned int GetStoragePartitionCount(BrowserContext* browser_context) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(browser_context);
-
-  int num_partitions = 0;
-  BrowserContext::ForEachStoragePartition(
-      browser_context,
-      base::BindRepeating(
-          [](int* num_partitions, StoragePartition* storage_partition) {
-            (*num_partitions)++;
-          },
-          &num_partitions));
-
-  // It's valid for a profile to not have any storage partitions. This DCHECK
-  // is to ensure that we're not waking up Chrome for no reason, because that's
-  // expensive and unnecessary.
-  DCHECK(num_partitions);
-
-  return num_partitions;
-}
-#endif
-
-}  // namespace
-
-// static
-BackgroundSyncLauncher* BackgroundSyncLauncher::Get() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  return g_background_sync_launcher.Pointer();
-}
-
-// static
-void BackgroundSyncLauncher::GetSoonestWakeupDelta(
-    BrowserContext* browser_context,
-    base::OnceCallback<void(base::TimeDelta)> callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
-  BrowserContext::ForEachStoragePartition(
-      browser_context, base::BindRepeating(
-                           [](base::TimeDelta* soonest_wakeup_delta,
-                              StoragePartition* storage_partition) {
-                             BackgroundSyncContext* sync_context =
-                                 storage_partition->GetBackgroundSyncContext();
-                             DCHECK(sync_context);
-
-                             base::TimeDelta wakeup_delta =
-                                 sync_context->GetSoonestWakeupDelta();
-                             if (wakeup_delta < *soonest_wakeup_delta)
-                               *soonest_wakeup_delta = wakeup_delta;
-                           },
-                           &soonest_wakeup_delta));
-  std::move(callback).Run(soonest_wakeup_delta);
-}
-
-// static
-#if defined(OS_ANDROID)
-void BackgroundSyncLauncher::FireBackgroundSyncEvents(
-    BrowserContext* browser_context,
-    const base::android::JavaParamRef<jobject>& j_runnable) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(browser_context);
-
-  base::RepeatingClosure done_closure = base::BarrierClosure(
-      GetStoragePartitionCount(browser_context),
-      base::BindOnce(base::android::RunRunnableAndroid,
-                     base::android::ScopedJavaGlobalRef<jobject>(j_runnable)));
-
-  BrowserContext::ForEachStoragePartition(
-      browser_context,
-      base::BindRepeating(
-          [](base::RepeatingClosure done_closure,
-             StoragePartition* storage_partition) {
-            BackgroundSyncContext* sync_context =
-                storage_partition->GetBackgroundSyncContext();
-            DCHECK(sync_context);
-            sync_context->FireBackgroundSyncEvents(std::move(done_closure));
-          },
-          std::move(done_closure)));
-}
-#endif
-
-BackgroundSyncLauncher::BackgroundSyncLauncher() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-BackgroundSyncLauncher::~BackgroundSyncLauncher() {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-}  // namespace content
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_launcher.h b/content/browser/background_sync/background_sync_launcher.h
deleted file mode 100644
index 28d6acba..0000000
--- a/content/browser/background_sync/background_sync_launcher.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
-#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
-
-#include "base/callback_forward.h"
-#include "base/lazy_instance.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#endif
-
-namespace content {
-
-class BrowserContext;
-
-class CONTENT_EXPORT BackgroundSyncLauncher {
- public:
-  static BackgroundSyncLauncher* Get();
-  static void GetSoonestWakeupDelta(
-      BrowserContext* browser_context,
-      base::OnceCallback<void(base::TimeDelta)> callback);
-#if defined(OS_ANDROID)
-  static void FireBackgroundSyncEvents(
-      BrowserContext* browser_context,
-      const base::android::JavaParamRef<jobject>& j_runnable);
-#endif
-
- private:
-  friend struct base::LazyInstanceTraitsBase<BackgroundSyncLauncher>;
-  friend class BackgroundSyncLauncherTest;
-
-  // Constructor and destructor marked private to enforce singleton.
-  BackgroundSyncLauncher();
-  ~BackgroundSyncLauncher();
-
-  base::TimeDelta soonest_wakeup_delta_ = base::TimeDelta::Max();
-  DISALLOW_COPY_AND_ASSIGN(BackgroundSyncLauncher);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_LAUNCHER_H_
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_launcher_unittest.cc b/content/browser/background_sync/background_sync_launcher_unittest.cc
deleted file mode 100644
index 6a81ee3..0000000
--- a/content/browser/background_sync/background_sync_launcher_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/background_sync/background_sync_launcher.h"
-
-#include <map>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/time/time.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/background_sync_context.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/content_client.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-const char kUrl_1[] = "https://example.com";
-const char kUrl_2[] = "https://whereswaldo.com";
-
-class TestBrowserClient : public ContentBrowserClient {
- public:
-  TestBrowserClient() = default;
-  ~TestBrowserClient() override = default;
-
-  void GetStoragePartitionConfigForSite(BrowserContext* browser_context,
-                                        const GURL& site,
-                                        bool can_be_default,
-                                        std::string* partition_domain,
-                                        std::string* partition_name,
-                                        bool* in_memory) override {
-    DCHECK(browser_context);
-    DCHECK(partition_domain);
-    DCHECK(partition_name);
-
-    auto partition_num = std::to_string(++partition_count_);
-    *partition_domain = std::string("PartitionDomain") + partition_num;
-    *partition_name = std::string("Partition") + partition_num;
-    *in_memory = false;
-  }
-
- private:
-  int partition_count_ = 0;
-};
-
-}  // namespace
-
-class BackgroundSyncLauncherTest : public testing::Test {
- public:
-  BackgroundSyncLauncherTest()
-      : browser_thread_bundle_(TestBrowserThreadBundle::MainThreadType::UI) {}
-
-  void SetUpBrowserContext(const std::vector<GURL>& urls,
-                           const std::map<GURL, int>& wakeup_deltas = {}) {
-    DCHECK(!urls.empty());
-
-    for (const auto& url : urls) {
-      auto* storage_partition = BrowserContext::GetStoragePartitionForSite(
-          &test_browser_context_, url);
-
-      auto iter = wakeup_deltas.find(url);
-      if (iter == wakeup_deltas.end())
-        continue;
-
-      static_cast<StoragePartitionImpl*>(storage_partition)
-          ->GetBackgroundSyncContext()
-          ->set_wakeup_delta_for_testing(
-              base::TimeDelta::FromMilliseconds(iter->second));
-    }
-  }
-
-  void SetUp() override {
-    original_client_ = SetBrowserClientForTesting(&browser_client_);
-  }
-
-  void TearDown() override { SetBrowserClientForTesting(original_client_); }
-
-  base::TimeDelta GetSoonestWakeupDelta() {
-    base::TimeDelta to_return;
-    BackgroundSyncLauncher::GetSoonestWakeupDelta(
-        &test_browser_context_, base::BindOnce(
-                                    [](base::TimeDelta* to_return,
-                                       base::TimeDelta soonest_wakeup_delta) {
-                                      DCHECK(to_return);
-                                      *to_return = soonest_wakeup_delta;
-                                    },
-                                    &to_return));
-    browser_thread_bundle_.RunUntilIdle();
-    return to_return;
-  }
-
- protected:
-  TestBrowserClient browser_client_;
-  ContentBrowserClient* original_client_;
-  TestBrowserThreadBundle browser_thread_bundle_;
-  TestBrowserContext test_browser_context_;
-};
-
-// Tests that we pick the correct wake up delta for the one-shot Background
-// Sync wake up task, across all storage partitions.
-TEST_F(BackgroundSyncLauncherTest, CorrectSoonestWakeupDeltaIsPicked) {
-  std::vector<GURL> urls = {GURL(kUrl_1), GURL(kUrl_2)};
-
-  // Add two storage partitions. Verify that we set the soonest wake up delta
-  // to base::TimeDelta::Max(). This will cause cancellation of the wakeup
-  // task.
-  SetUpBrowserContext(urls);
-  EXPECT_TRUE(GetSoonestWakeupDelta().is_max());
-
-  // Add two more storage partitions, this time with wakeup_deltas.
-  // Verify that we pick the smaller of the two.
-  int delta_ms = 0;
-  std::map<GURL, int> wakeup_deltas;
-  for (const auto& url : urls)
-    wakeup_deltas[url] = delta_ms += 1000;
-  SetUpBrowserContext(urls, wakeup_deltas);
-
-  EXPECT_EQ(GetSoonestWakeupDelta().InMilliseconds(), 1000);
-}
-
-}  // namespace content
\ No newline at end of file
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index de713b19..4a2803b 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -122,13 +122,15 @@
 }
 
 void RunInBackgroundOnUIThread(
-    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper) {
+    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
+    bool enabled,
+    int64_t min_ms) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BackgroundSyncController* background_sync_controller =
       GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
   if (background_sync_controller) {
-    background_sync_controller->RunInBackground();
+    background_sync_controller->RunInBackground(enabled, min_ms);
   }
 }
 
@@ -960,10 +962,10 @@
   return AreOptionConditionsMet();
 }
 
-base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta() {
+void BackgroundSyncManager::RunInBackgroundIfNecessary() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
   base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
+
   for (const auto& sw_id_and_registrations : active_registrations_) {
     for (const auto& key_and_registration :
          sw_id_and_registrations.second.registration_map) {
@@ -990,14 +992,6 @@
     soonest_wakeup_delta = parameters_->min_sync_recovery_time;
   }
 
-  return soonest_wakeup_delta;
-}
-
-void BackgroundSyncManager::RunInBackgroundIfNecessary() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  base::TimeDelta soonest_wakeup_delta = GetSoonestWakeupDelta();
-
   // Try firing again after the wakeup delta.
   if (!soonest_wakeup_delta.is_max() && !soonest_wakeup_delta.is_zero()) {
     delayed_sync_task_.Reset(base::Bind(&BackgroundSyncManager::FireReadyEvents,
@@ -1006,11 +1000,14 @@
   }
 
   // In case the browser closes (or to prevent it from closing), call
-  // RunInBackground to wake up the browser at the soonest wakeup delta across
-  // all the storage partitions.
+  // RunInBackground to either wake up the browser at the wakeup delta or to
+  // keep the browser running.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(RunInBackgroundOnUIThread, service_worker_context_));
+      base::BindOnce(
+          RunInBackgroundOnUIThread, service_worker_context_,
+          !soonest_wakeup_delta.is_max() /* should run in background */,
+          soonest_wakeup_delta.InMilliseconds()));
 }
 
 void BackgroundSyncManager::FireReadyEvents() {
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h
index 19f9917..299b17d 100644
--- a/content/browser/background_sync/background_sync_manager.h
+++ b/content/browser/background_sync/background_sync_manager.h
@@ -124,10 +124,6 @@
   // Once all of this is done, invokes |callback|.
   void FireReadyEventsThenRunCallback(base::OnceClosure callback);
 
-  // Gets the soonest delta after which the browser should be woken up to send
-  // a Background Sync event. If set to max, the browser won't be woken up.
-  virtual base::TimeDelta GetSoonestWakeupDelta();
-
  protected:
   BackgroundSyncManager(
       scoped_refptr<ServiceWorkerContextWrapper> context,
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index b6c3d96..902679c4 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -1254,29 +1254,30 @@
   // The BackgroundSyncManager should declare in initialization
   // that it doesn't need to be woken up since it has no registrations.
   EXPECT_LT(0, GetController()->run_in_background_count());
-  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
+  EXPECT_FALSE(GetController()->run_in_background_enabled());
 
   SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE);
-  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
+  EXPECT_FALSE(GetController()->run_in_background_enabled());
 
   // Register a one-shot but it can't fire due to lack of network, wake up is
   // required.
   Register(sync_options_1_);
-  EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
+  EXPECT_TRUE(GetController()->run_in_background_enabled());
 
   // Start the event but it will pause mid-sync due to
   // InitDelayedSyncEventTest() above.
   SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI);
-  EXPECT_TRUE(test_background_sync_manager_->IsBrowserWakeupScheduled());
-  EXPECT_TRUE(test_background_sync_manager_->EqualsSoonestWakeupDelta(
-      test_background_sync_manager_->background_sync_parameters()
-          ->min_sync_recovery_time));
+  EXPECT_TRUE(GetController()->run_in_background_enabled());
+  EXPECT_EQ(test_background_sync_manager_->background_sync_parameters()
+                ->min_sync_recovery_time,
+            base::TimeDelta::FromMilliseconds(
+                GetController()->run_in_background_min_ms()));
 
   // Finish the sync.
   ASSERT_TRUE(sync_fired_callback_);
   std::move(sync_fired_callback_).Run(blink::ServiceWorkerStatusCode::kOk);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(test_background_sync_manager_->IsBrowserWakeupScheduled());
+  EXPECT_FALSE(GetController()->run_in_background_enabled());
 }
 
 TEST_F(BackgroundSyncManagerTest, OneAttempt) {
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 5406b61f..4251538 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -1275,10 +1275,6 @@
     const network::URLLoaderCompletionStatus& status) {
   DCHECK_NE(status.error_code, net::OK);
 
-  // The |loader_|'s job is finished. It must not call the NavigationRequest
-  // anymore from now.
-  loader_.reset();
-
   bool collapse_frame =
       status.extended_error_code ==
       static_cast<int>(blink::ResourceRequestBlockedReason::kCollapsedByClient);
@@ -1295,6 +1291,11 @@
   DCHECK(state_ == STARTED || state_ == RESPONSE_STARTED);
   DCHECK(!(status.error_code == net::ERR_ABORTED &&
            error_page_content.has_value()));
+
+  // The request failed, the |loader_| must not call the NavigationRequest
+  // anymore from now while the error page is being loaded.
+  loader_.reset();
+
   common_params_.previews_state = content::PREVIEWS_OFF;
   if (status.ssl_info.has_value())
     ssl_info_ = status.ssl_info;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 1e834cc..c5aa6b7b 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1602,7 +1602,7 @@
   return frame_input_handler_.get();
 }
 
-bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
+bool RenderFrameHostImpl::CreateRenderFrame(int previous_routing_id,
                                             int opener_routing_id,
                                             int parent_routing_id,
                                             int previous_sibling_routing_id) {
@@ -1636,7 +1636,7 @@
       std::move(document_interface_broker_blink_info));
 
   params->routing_id = routing_id_;
-  params->proxy_routing_id = proxy_routing_id;
+  params->previous_routing_id = previous_routing_id;
   params->opener_routing_id = opener_routing_id;
   params->parent_routing_id = parent_routing_id;
   params->previous_sibling_routing_id = previous_sibling_routing_id;
@@ -1682,9 +1682,9 @@
     rwhv->Hide();
   }
 
-  if (proxy_routing_id != MSG_ROUTING_NONE) {
+  if (previous_routing_id != MSG_ROUTING_NONE) {
     RenderFrameProxyHost* proxy = RenderFrameProxyHost::FromID(
-        GetProcess()->GetID(), proxy_routing_id);
+        GetProcess()->GetID(), previous_routing_id);
     // We have also created a RenderFrameProxy in CreateFrame above, so
     // remember that.
     proxy->set_render_frame_proxy_created(true);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 926ad8d..e91feba 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -317,7 +317,7 @@
   }
 
   // Creates a RenderFrame in the renderer process.
-  bool CreateRenderFrame(int proxy_routing_id,
+  bool CreateRenderFrame(int previous_routing_id,
                          int opener_routing_id,
                          int parent_routing_id,
                          int previous_sibling_routing_id);
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index cd28cde1..ad9bf0b 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -2132,18 +2132,21 @@
   // SiteInstance as its RenderFrameHost. This is only the case until the
   // RenderFrameHost commits, at which point it will replace and delete the
   // RenderFrameProxyHost.
-  int proxy_routing_id = MSG_ROUTING_NONE;
+  // TODO(arthursonzogni): Implement same-process RenderFrame swap. In this case
+  // |previous_routing_id| can represent not only a RenderFrameProxyHost, but
+  // can also represent a RenderFrameHost.
+  int previous_routing_id = MSG_ROUTING_NONE;
   RenderFrameProxyHost* existing_proxy = GetRenderFrameProxyHost(site_instance);
   if (existing_proxy) {
-    proxy_routing_id = existing_proxy->GetRoutingID();
-    CHECK_NE(proxy_routing_id, MSG_ROUTING_NONE);
+    previous_routing_id = existing_proxy->GetRoutingID();
+    CHECK_NE(previous_routing_id, MSG_ROUTING_NONE);
     if (!existing_proxy->is_render_frame_proxy_live())
       existing_proxy->InitRenderFrameProxy();
   }
 
   return delegate_->CreateRenderFrameForRenderManager(
-      render_frame_host, proxy_routing_id, opener_routing_id, parent_routing_id,
-      previous_sibling_routing_id);
+      render_frame_host, previous_routing_id, opener_routing_id,
+      parent_routing_id, previous_sibling_routing_id);
 }
 
 bool RenderFrameHostManager::ReinitializeRenderFrame(
diff --git a/content/browser/indexed_db/cursor_impl.cc b/content/browser/indexed_db/cursor_impl.cc
index 687e5cb9..a934920 100644
--- a/content/browser/indexed_db/cursor_impl.cc
+++ b/content/browser/indexed_db/cursor_impl.cc
@@ -10,50 +10,18 @@
 #include "content/browser/indexed_db/indexed_db_cursor.h"
 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
 
-using blink::IndexedDBKey;
-
 namespace content {
 
-// TODO(cmp): Flatten calls / remove this class once IDB task runner CL settles.
-class CursorImpl::IDBSequenceHelper {
- public:
-  explicit IDBSequenceHelper(std::unique_ptr<IndexedDBCursor> cursor,
-                             base::SequencedTaskRunner* idb_runner);
-  ~IDBSequenceHelper();
-
-  void Advance(uint32_t count,
-               base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-               blink::mojom::IDBCursor::AdvanceCallback callback);
-  void Continue(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-                const IndexedDBKey& key,
-                const IndexedDBKey& primary_key,
-                blink::mojom::IDBCursor::CursorContinueCallback callback);
-  void Prefetch(base::WeakPtr<IndexedDBDispatcherHost> dispatcher_host,
-                int32_t count,
-                blink::mojom::IDBCursor::PrefetchCallback callback);
-  void PrefetchReset(int32_t used_prefetches, int32_t unused_prefetches);
-
-  void OnRemoveBinding(base::OnceClosure remove_binding_cb);
-
- private:
-  std::unique_ptr<IndexedDBCursor> cursor_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(IDBSequenceHelper);
-};
-
 CursorImpl::CursorImpl(std::unique_ptr<IndexedDBCursor> cursor,
                        const url::Origin& origin,
                        IndexedDBDispatcherHost* dispatcher_host,
                        scoped_refptr<base::SequencedTaskRunner> idb_runner)
     : dispatcher_host_(dispatcher_host),
       origin_(origin),
-      idb_runner_(std::move(idb_runner)) {
+      idb_runner_(std::move(idb_runner)),
+      cursor_(std::move(cursor)) {
   DCHECK(idb_runner_);
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_ = base::WrapUnique(
-      new IDBSequenceHelper(std::move(cursor), idb_runner_.get()));
 }
 
 CursorImpl::~CursorImpl() {
@@ -63,81 +31,32 @@
 void CursorImpl::Advance(uint32_t count,
                          blink::mojom::IDBCursor::AdvanceCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_->Advance(count, dispatcher_host_->AsWeakPtr(), std::move(callback));
+  cursor_->Advance(count, dispatcher_host_->AsWeakPtr(), std::move(callback));
 }
 
 void CursorImpl::CursorContinue(
-    const IndexedDBKey& key,
-    const IndexedDBKey& primary_key,
+    const blink::IndexedDBKey& key,
+    const blink::IndexedDBKey& primary_key,
     blink::mojom::IDBCursor::CursorContinueCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_->Continue(dispatcher_host_->AsWeakPtr(), key, primary_key,
-                    std::move(callback));
+  cursor_->Continue(
+      dispatcher_host_->AsWeakPtr(),
+      key.IsValid() ? std::make_unique<blink::IndexedDBKey>(key) : nullptr,
+      primary_key.IsValid() ? std::make_unique<blink::IndexedDBKey>(primary_key)
+                            : nullptr,
+      std::move(callback));
 }
 
 void CursorImpl::Prefetch(int32_t count,
                           blink::mojom::IDBCursor::PrefetchCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_->Prefetch(dispatcher_host_->AsWeakPtr(), count, std::move(callback));
+  cursor_->PrefetchContinue(dispatcher_host_->AsWeakPtr(), count,
+                            std::move(callback));
 }
 
 void CursorImpl::PrefetchReset(int32_t used_prefetches,
                                int32_t unused_prefetches) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_->PrefetchReset(used_prefetches, unused_prefetches);
-}
-
-void CursorImpl::OnRemoveBinding(base::OnceClosure remove_binding_cb) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  helper_->OnRemoveBinding(std::move(remove_binding_cb));
-}
-
-CursorImpl::IDBSequenceHelper::IDBSequenceHelper(
-    std::unique_ptr<IndexedDBCursor> cursor,
-    base::SequencedTaskRunner* idb_runner)
-    : cursor_(std::move(cursor)) {
-  DCHECK(idb_runner->RunsTasksInCurrentSequence());
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-}
-
-CursorImpl::IDBSequenceHelper::~IDBSequenceHelper() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-}
-
-void CursorImpl::IDBSequenceHelper::Advance(
-    uint32_t count,
-    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
-    blink::mojom::IDBCursor::AdvanceCallback callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  cursor_->Advance(count, std::move(dispatcher_host), std::move(callback));
-}
-
-void CursorImpl::IDBSequenceHelper::Continue(
-    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
-    const IndexedDBKey& key,
-    const IndexedDBKey& primary_key,
-    blink::mojom::IDBCursor::CursorContinueCallback callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  cursor_->Continue(
-      std::move(dispatcher_host),
-      key.IsValid() ? std::make_unique<IndexedDBKey>(key) : nullptr,
-      primary_key.IsValid() ? std::make_unique<IndexedDBKey>(primary_key)
-                            : nullptr,
-      std::move(callback));
-}
-
-void CursorImpl::IDBSequenceHelper::Prefetch(
-    base::WeakPtr<content::IndexedDBDispatcherHost> dispatcher_host,
-    int32_t count,
-    blink::mojom::IDBCursor::PrefetchCallback callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  cursor_->PrefetchContinue(std::move(dispatcher_host), count,
-                            std::move(callback));
-}
-
-void CursorImpl::IDBSequenceHelper::PrefetchReset(int32_t used_prefetches,
-                                                  int32_t unused_prefetches) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   leveldb::Status s =
       cursor_->PrefetchReset(used_prefetches, unused_prefetches);
   // TODO(cmumford): Handle this error (crbug.com/363397)
@@ -145,8 +64,7 @@
     DLOG(ERROR) << "Unable to reset prefetch";
 }
 
-void CursorImpl::IDBSequenceHelper::OnRemoveBinding(
-    base::OnceClosure remove_binding_cb) {
+void CursorImpl::OnRemoveBinding(base::OnceClosure remove_binding_cb) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   cursor_->OnRemoveBinding(std::move(remove_binding_cb));
 }
diff --git a/content/browser/indexed_db/cursor_impl.h b/content/browser/indexed_db/cursor_impl.h
index feb7f89..8d16415 100644
--- a/content/browser/indexed_db/cursor_impl.h
+++ b/content/browser/indexed_db/cursor_impl.h
@@ -45,14 +45,12 @@
   void OnRemoveBinding(base::OnceClosure remove_binding_cb);
 
  private:
-  class IDBSequenceHelper;
-
-  std::unique_ptr<IDBSequenceHelper> helper_;
   // This raw pointer is safe because all CursorImpl instances are owned by an
   // IndexedDBDispatcherHost.
   IndexedDBDispatcherHost* dispatcher_host_;
   const url::Origin origin_;
   scoped_refptr<base::SequencedTaskRunner> idb_runner_;
+  std::unique_ptr<IndexedDBCursor> cursor_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index 1411491..068a7c8 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1027,6 +1027,14 @@
     url_loader_removed_headers_ = removed_headers;
     url_loader_modified_headers_ = modified_headers;
 
+    // Don't send Accept: application/signed-exchange for fallback redirects.
+    if (redirect_info_.is_signed_exchange_fallback_redirect) {
+      url_loader_modified_headers_.SetHeader(network::kAcceptHeader,
+                                             network::kFrameAcceptHeader);
+      resource_request_->headers.SetHeader(network::kAcceptHeader,
+                                           network::kFrameAcceptHeader);
+    }
+
     Restart();
   }
 
diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index 9150bffa..3d6f61c 100644
--- a/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -390,7 +390,7 @@
 // (crbug.com/723618).
 // http://crbug.com/801629 : Flaky on Linux and Windows, and Mac with
 // --enable-features=VizDisplayCompositor
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_LINUX)
 #define MAYBE_CoalescedMouseMovesCorrectlyTerminated \
   DISABLED_CoalescedMouseMovesCorrectlyTerminated
 #else
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
index 711ec50..4624422 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.cc
@@ -102,6 +102,7 @@
     bool request_video_input,
     bool request_audio_output,
     bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
     EnumerateDevicesCallback client_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -121,7 +122,8 @@
 
   media_stream_manager_->media_devices_manager()->EnumerateDevices(
       render_process_id_, render_frame_id_, devices_to_enumerate,
-      request_video_input_capabilities, std::move(client_callback));
+      request_video_input_capabilities, request_audio_input_capabilities,
+      std::move(client_callback));
 }
 
 void MediaDevicesDispatcherHost::GetVideoInputCapabilities(
@@ -355,9 +357,11 @@
   DCHECK_EQ(num_pending_audio_input_parameters_, 0U);
   for (const auto& device_info :
        enumeration[blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
+    auto parameters = media::AudioParameters::UnavailableDeviceParams();
     blink::mojom::AudioInputDeviceCapabilities capabilities(
-        device_info.device_id, device_info.group_id,
-        media::AudioParameters::UnavailableDeviceParams());
+        device_info.device_id, device_info.group_id, parameters,
+        parameters.IsValid(), parameters.channels(), parameters.sample_rate(),
+        parameters.GetBufferDuration());
     if (device_info.device_id == default_device_id)
       current_audio_input_capabilities_.insert(
           current_audio_input_capabilities_.begin(), std::move(capabilities));
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host.h b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
index c2525bef..d02bffb 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host.h
@@ -40,6 +40,7 @@
                         bool request_video_input,
                         bool request_audio_output,
                         bool request_video_input_capabilities,
+                        bool request_audio_input_capabilities,
                         EnumerateDevicesCallback client_callback) override;
   void GetVideoInputCapabilities(
       GetVideoInputCapabilitiesCallback client_callback) override;
diff --git a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
index 1699e96e0..fc37c89 100644
--- a/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_dispatcher_host_unittest.cc
@@ -241,7 +241,9 @@
       const base::Closure& closure,
       const std::vector<std::vector<blink::WebMediaDeviceInfo>>& devices,
       std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
-          video_input_capabilities) {
+          video_input_capabilities,
+      std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
+          audio_input_capabilities) {
     enumerated_devices_ = devices;
     closure.Run();
   }
@@ -256,7 +258,7 @@
     base::RunLoop run_loop;
     host_->EnumerateDevices(
         enumerate_audio_input, enumerate_video_input, enumerate_audio_output,
-        false,
+        false, false,
         base::BindOnce(&MediaDevicesDispatcherHostTest::DevicesEnumerated,
                        base::Unretained(this), run_loop.QuitClosure()));
     run_loop.Run();
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 5ec40d1..2136faa3 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -9,6 +9,7 @@
 
 #include <algorithm>
 #include <functional>
+#include <map>
 #include <string>
 
 #include "base/bind.h"
@@ -425,6 +426,7 @@
     int render_frame_id,
     const BoolDeviceTypes& requested_types,
     bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
     EnumerateDevicesCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -436,7 +438,8 @@
       base::BindOnce(&MediaDevicesManager::CheckPermissionsForEnumerateDevices,
                      weak_factory_.GetWeakPtr(), render_process_id,
                      render_frame_id, requested_types,
-                     request_video_input_capabilities, std::move(callback)));
+                     request_video_input_capabilities,
+                     request_audio_input_capabilities, std::move(callback)));
 }
 
 uint32_t MediaDevicesManager::SubscribeDeviceChangeNotifications(
@@ -636,6 +639,7 @@
     int render_frame_id,
     const BoolDeviceTypes& requested_types,
     bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
     EnumerateDevicesCallback callback,
     MediaDeviceSaltAndOrigin salt_and_origin) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -643,13 +647,15 @@
       requested_types, render_process_id, render_frame_id,
       base::BindOnce(&MediaDevicesManager::OnPermissionsCheckDone,
                      weak_factory_.GetWeakPtr(), requested_types,
-                     request_video_input_capabilities, std::move(callback),
+                     request_video_input_capabilities,
+                     request_audio_input_capabilities, std::move(callback),
                      std::move(salt_and_origin)));
 }
 
 void MediaDevicesManager::OnPermissionsCheckDone(
     const MediaDevicesManager::BoolDeviceTypes& requested_types,
     bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
     EnumerateDevicesCallback callback,
     MediaDeviceSaltAndOrigin salt_and_origin,
     const MediaDevicesManager::BoolDeviceTypes& has_permissions) {
@@ -673,21 +679,27 @@
       internal_requested_types,
       base::BindOnce(&MediaDevicesManager::OnDevicesEnumerated,
                      weak_factory_.GetWeakPtr(), requested_types,
-                     request_video_input_capabilities, std::move(callback),
+                     request_video_input_capabilities,
+                     request_audio_input_capabilities, std::move(callback),
                      std::move(salt_and_origin), has_permissions));
 }
 
 void MediaDevicesManager::OnDevicesEnumerated(
     const MediaDevicesManager::BoolDeviceTypes& requested_types,
     bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
     EnumerateDevicesCallback callback,
     const MediaDeviceSaltAndOrigin& salt_and_origin,
     const MediaDevicesManager::BoolDeviceTypes& has_permissions,
     const MediaDeviceEnumeration& enumeration) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
   const bool video_input_capabilities_requested =
       has_permissions[blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT] &&
       request_video_input_capabilities;
+  const bool audio_input_capabilities_requested =
+      has_permissions[blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT] &&
+      request_audio_input_capabilities;
 
   std::vector<blink::WebMediaDeviceInfoArray> result(
       blink::NUM_MEDIA_DEVICE_TYPES);
@@ -701,12 +713,108 @@
     }
   }
 
-  std::move(callback).Run(
-      result, video_input_capabilities_requested
-                  ? ComputeVideoInputCapabilities(
-                        enumeration[blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT],
-                        result[blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT])
-                  : std::vector<VideoInputDeviceCapabilitiesPtr>());
+  GetAudioInputCapabilities(video_input_capabilities_requested,
+                            audio_input_capabilities_requested,
+                            std::move(callback), enumeration, result);
+}
+
+void MediaDevicesManager::GetAudioInputCapabilities(
+    bool request_video_input_capabilities,
+    bool request_audio_input_capabilities,
+    EnumerateDevicesCallback callback,
+    const MediaDeviceEnumeration& enumeration,
+    const std::vector<blink::WebMediaDeviceInfoArray>& enumeration_results) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  EnumerationState state;
+  size_t state_id = next_enumeration_state_id_++;
+  state.video_input_capabilities_requested = request_video_input_capabilities;
+  state.audio_input_capabilities_requested = request_audio_input_capabilities;
+  state.completion_cb = std::move(callback);
+  state.enumeration = std::move(enumeration);
+  state.enumeration_results = std::move(enumeration_results);
+  state.num_pending_audio_input_capabilities =
+      enumeration_results[blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT].size();
+
+  if (!state.audio_input_capabilities_requested ||
+      state.num_pending_audio_input_capabilities == 0) {
+    FinalizeDevicesEnumerated(std::move(state));
+    return;
+  }
+
+  enumeration_states_[state_id] = std::move(state);
+  for (const auto& result :
+       enumeration_results[blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT]) {
+    AudioInputDeviceCapabilitiesPtr capabilities =
+        blink::mojom::AudioInputDeviceCapabilities::New();
+    capabilities->device_id = result.device_id;
+    capabilities->parameters =
+        media::AudioParameters::UnavailableDeviceParams();
+    enumeration_states_[state_id].audio_capabilities.push_back(
+        std::move(capabilities));
+    size_t capabilities_index =
+        enumeration_states_[state_id].audio_capabilities.size() - 1;
+    if (use_fake_devices_) {
+      base::PostTaskWithTraits(
+          FROM_HERE, {BrowserThread::IO},
+          base::BindOnce(&MediaDevicesManager::GotAudioInputCapabilities,
+                         weak_factory_.GetWeakPtr(), state_id,
+                         capabilities_index,
+                         media::AudioParameters::UnavailableDeviceParams()));
+    } else {
+      audio_system_->GetInputStreamParameters(
+          result.device_id,
+          base::BindOnce(&MediaDevicesManager::GotAudioInputCapabilities,
+                         weak_factory_.GetWeakPtr(), state_id,
+                         capabilities_index));
+    }
+  }
+}
+
+void MediaDevicesManager::GotAudioInputCapabilities(
+    size_t state_id,
+    size_t capabilities_index,
+    const base::Optional<media::AudioParameters>& parameters) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(base::ContainsKey(enumeration_states_, state_id));
+
+  auto& enumeration_state = enumeration_states_[state_id];
+  DCHECK_GT(enumeration_state.num_pending_audio_input_capabilities, 0);
+
+  AudioInputDeviceCapabilitiesPtr& capabilities =
+      enumeration_state.audio_capabilities[capabilities_index];
+  if (parameters) {
+    capabilities->parameters = *parameters;
+    // Data from the |parameters| field is duplicated in the |channels|,
+    // |sample_rate| and |latency| fields due to the lack of availability
+    // of the media::AudioParameters native mojo mapping in blink.
+    // TODO(crbug.com/787252): Remove redundant fields when |parameters|
+    // is accessible from Blink.
+    capabilities->is_valid = parameters->IsValid();
+    capabilities->channels = parameters->channels();
+    capabilities->sample_rate = parameters->sample_rate();
+    capabilities->latency = parameters->GetBufferDuration();
+  }
+  DCHECK(capabilities->parameters.IsValid());
+
+  if (--enumeration_state.num_pending_audio_input_capabilities == 0) {
+    FinalizeDevicesEnumerated(std::move(enumeration_state));
+    enumeration_states_.erase(state_id);
+  }
+}
+
+void MediaDevicesManager::FinalizeDevicesEnumerated(
+    EnumerationState enumeration_state) {
+  std::move(enumeration_state.completion_cb)
+      .Run(std::move(enumeration_state.enumeration_results),
+           enumeration_state.video_input_capabilities_requested
+               ? ComputeVideoInputCapabilities(
+                     enumeration_state
+                         .enumeration[blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT],
+                     enumeration_state.enumeration_results
+                         [blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT])
+               : std::vector<VideoInputDeviceCapabilitiesPtr>(),
+           std::move(enumeration_state.audio_capabilities));
 }
 
 std::vector<VideoInputDeviceCapabilitiesPtr>
@@ -1004,4 +1112,11 @@
                                           device_infos));
 }
 
+MediaDevicesManager::EnumerationState::EnumerationState() = default;
+MediaDevicesManager::EnumerationState::EnumerationState(
+    EnumerationState&& other) = default;
+MediaDevicesManager::EnumerationState::~EnumerationState() = default;
+MediaDevicesManager::EnumerationState& MediaDevicesManager::EnumerationState::
+operator=(EnumerationState&& other) = default;
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_devices_manager.h b/content/browser/renderer_host/media/media_devices_manager.h
index 1c0e8bd..979718d5 100644
--- a/content/browser/renderer_host/media/media_devices_manager.h
+++ b/content/browser/renderer_host/media/media_devices_manager.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_DEVICES_MANAGER_H_
 
 #include <array>
+#include <map>
 #include <memory>
 #include <string>
 #include <utility>
@@ -24,6 +25,7 @@
 #include "third_party/blink/public/common/mediastream/media_devices.h"
 #include "third_party/blink/public/mojom/mediastream/media_devices.mojom.h"
 
+using blink::mojom::AudioInputDeviceCapabilitiesPtr;
 using blink::mojom::VideoInputDeviceCapabilitiesPtr;
 
 namespace media {
@@ -62,7 +64,8 @@
       base::OnceCallback<void(const MediaDeviceEnumeration&)>;
   using EnumerateDevicesCallback = base::OnceCallback<void(
       const std::vector<blink::WebMediaDeviceInfoArray>&,
-      std::vector<VideoInputDeviceCapabilitiesPtr>)>;
+      std::vector<VideoInputDeviceCapabilitiesPtr>,
+      std::vector<AudioInputDeviceCapabilitiesPtr>)>;
   using StopRemovedInputDeviceCallback = base::RepeatingCallback<void(
       blink::MediaDeviceType type,
       const blink::WebMediaDeviceInfo& media_device_info)>;
@@ -99,6 +102,7 @@
                         int render_frame_id,
                         const BoolDeviceTypes& requested_types,
                         bool request_video_input_capabilities,
+                        bool request_audio_input_capabilities,
                         EnumerateDevicesCallback callback);
 
   uint32_t SubscribeDeviceChangeNotifications(
@@ -171,6 +175,27 @@
     blink::mojom::MediaDevicesListenerPtr listener;
   };
 
+  // Class containing the state of each spawned enumeration. This state is
+  // required since retrieving audio parameters is done asynchronously for each
+  // device and a new devices enumeration request can be started before all
+  // parameters have been collected.
+  class EnumerationState {
+   public:
+    EnumerationState();
+    EnumerationState(EnumerationState&& other);
+    ~EnumerationState();
+
+    EnumerationState& operator=(EnumerationState&& other);
+
+    bool video_input_capabilities_requested = false;
+    bool audio_input_capabilities_requested = false;
+    EnumerateDevicesCallback completion_cb;
+    std::vector<AudioInputDeviceCapabilitiesPtr> audio_capabilities;
+    int num_pending_audio_input_capabilities;
+    std::vector<blink::WebMediaDeviceInfoArray> enumeration_results;
+    MediaDeviceEnumeration enumeration;
+  };
+
   // The NO_CACHE policy is such that no previous results are used when
   // EnumerateDevices is called. The results of a new or in-progress low-level
   // device enumeration are used.
@@ -191,21 +216,35 @@
       int render_frame_id,
       const BoolDeviceTypes& requested_types,
       bool request_video_input_capabilities,
+      bool request_audio_input_capabilities,
       EnumerateDevicesCallback callback,
       MediaDeviceSaltAndOrigin salt_and_origin);
   void OnPermissionsCheckDone(
       const MediaDevicesManager::BoolDeviceTypes& requested_types,
       bool request_video_input_capabilities,
+      bool request_audio_input_capabilities,
       EnumerateDevicesCallback callback,
       MediaDeviceSaltAndOrigin salt_and_origin,
       const MediaDevicesManager::BoolDeviceTypes& has_permissions);
   void OnDevicesEnumerated(
       const MediaDevicesManager::BoolDeviceTypes& requested_types,
       bool request_video_input_capabilities,
+      bool request_audio_input_capabilities,
       EnumerateDevicesCallback callback,
       const MediaDeviceSaltAndOrigin& salt_and_origin,
       const MediaDevicesManager::BoolDeviceTypes& has_permissions,
       const MediaDeviceEnumeration& enumeration);
+  void GetAudioInputCapabilities(
+      bool request_video_input_capabilities,
+      bool request_audio_input_capabilities,
+      EnumerateDevicesCallback callback,
+      const MediaDeviceEnumeration& enumeration,
+      const std::vector<blink::WebMediaDeviceInfoArray>& devices_info);
+  void GotAudioInputCapabilities(
+      size_t state_index,
+      size_t capabilities_index,
+      const base::Optional<media::AudioParameters>& parameters);
+  void FinalizeDevicesEnumerated(EnumerationState enumeration_state);
 
   std::vector<VideoInputDeviceCapabilitiesPtr> ComputeVideoInputCapabilities(
       const blink::WebMediaDeviceInfoArray& raw_device_infos,
@@ -289,6 +328,9 @@
   class AudioServiceDeviceListener;
   std::unique_ptr<AudioServiceDeviceListener> audio_service_device_listener_;
 
+  std::map<uint32_t, EnumerationState> enumeration_states_;
+  uint32_t next_enumeration_state_id_ = 0;
+
   base::WeakPtrFactory<MediaDevicesManager> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaDevicesManager);
diff --git a/content/browser/renderer_host/media/media_devices_manager_unittest.cc b/content/browser/renderer_host/media/media_devices_manager_unittest.cc
index 29852c6d..4177cd99 100644
--- a/content/browser/renderer_host/media/media_devices_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_devices_manager_unittest.cc
@@ -45,6 +45,8 @@
 // is performed when cache is enabled, regardless of the number of client calls.
 const int kNumCalls = 3;
 
+const size_t kNumAudioInputDevices = 2;
+
 const auto kIgnoreLogMessageCB = base::BindRepeating([](const std::string&) {});
 
 MediaDeviceSaltAndOrigin GetSaltAndOrigin(int /* process_id */,
@@ -62,7 +64,7 @@
       : FakeAudioManager(std::make_unique<media::TestAudioThread>(),
                          &fake_audio_log_factory_),
         num_output_devices_(2),
-        num_input_devices_(2) {}
+        num_input_devices_(kNumAudioInputDevices) {}
   ~MockAudioManager() override {}
 
   MOCK_METHOD1(MockGetAudioInputDeviceNames, void(media::AudioDeviceNames*));
@@ -199,19 +201,30 @@
           expected_video_capture_device_settings,
       base::RunLoop* run_loop,
       const std::vector<blink::WebMediaDeviceInfoArray>& devices,
-      std::vector<VideoInputDeviceCapabilitiesPtr> capabilities) {
-    EXPECT_EQ(capabilities.size(),
+      std::vector<VideoInputDeviceCapabilitiesPtr> video_capabilities,
+      std::vector<AudioInputDeviceCapabilitiesPtr> audio_capabilities) {
+    EXPECT_EQ(video_capabilities.size(),
               expected_video_capture_device_settings.size());
-    for (size_t i = 0; i < capabilities.size(); ++i) {
+    for (size_t i = 0; i < video_capabilities.size(); ++i) {
       EXPECT_EQ(
-          capabilities[i]->formats.size(),
+          video_capabilities[i]->formats.size(),
           expected_video_capture_device_settings[i].supported_formats.size());
-      for (size_t j = 0; j < capabilities[i]->formats.size(); ++j) {
+      for (size_t j = 0; j < video_capabilities[i]->formats.size(); ++j) {
         EXPECT_EQ(
-            capabilities[i]->formats[j],
+            video_capabilities[i]->formats[j],
             expected_video_capture_device_settings[i].supported_formats[j]);
       }
     }
+    EXPECT_EQ(audio_capabilities.size(), kNumAudioInputDevices);
+    for (size_t i = 0; i < audio_capabilities.size(); ++i) {
+      EXPECT_TRUE(audio_capabilities[i]->parameters.IsValid());
+      EXPECT_EQ(audio_capabilities[i]->parameters.channel_layout(),
+                media::CHANNEL_LAYOUT_STEREO);
+      EXPECT_EQ(audio_capabilities[i]->parameters.sample_rate(),
+                media::AudioParameters::kAudioCDSampleRate);
+      EXPECT_EQ(audio_capabilities[i]->parameters.frames_per_buffer(),
+                media::AudioParameters::kAudioCDSampleRate / 100);
+    }
     run_loop->Quit();
   }
 
@@ -828,9 +841,10 @@
 
   MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
   devices_to_enumerate[blink::MEDIA_DEVICE_TYPE_VIDEO_INPUT] = true;
+  devices_to_enumerate[blink::MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
   base::RunLoop run_loop;
   media_devices_manager_->EnumerateDevices(
-      -1, -1, devices_to_enumerate, true,
+      -1, -1, devices_to_enumerate, true, true,
       base::BindOnce(
           &MediaDevicesManagerTest::EnumerateWithCapabilitiesCallback,
           base::Unretained(this), fake_capture_device_settings, &run_loop));
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index fe1e4e4..47a2c21 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -213,64 +213,36 @@
 ServiceWorkerProviderHost*
 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
   DCHECK(!IsAtEnd());
-  return provider_host_iterator_->GetCurrentValue();
+  return provider_host_iterator_->second.get();
 }
 
 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
   DCHECK(!IsAtEnd());
-  DCHECK(!provider_host_iterator_->IsAtEnd());
-  DCHECK(!process_iterator_->IsAtEnd());
-
-  // Advance the inner iterator. If an element is reached, we're done.
-  provider_host_iterator_->Advance();
-  if (ForwardUntilMatchingProviderHost())
-    return;
-
-  // Advance the outer iterator until an element is reached, or end is hit.
-  while (true) {
-    process_iterator_->Advance();
-    if (process_iterator_->IsAtEnd())
-      return;
-    ProviderMap* provider_map = process_iterator_->GetCurrentValue();
-    provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
-    if (ForwardUntilMatchingProviderHost())
-      return;
-  }
+  provider_host_iterator_++;
+  ForwardUntilMatchingProviderHost();
 }
 
 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
-  return process_iterator_->IsAtEnd() &&
-         (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
+  return provider_host_iterator_ == map_->end();
 }
 
 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
-    ProcessToProviderMap* map,
+    ProviderByIdMap* map,
     ProviderHostPredicate predicate)
-    : map_(map), predicate_(std::move(predicate)) {
-  DCHECK(map);
-  Initialize();
+    : map_(map),
+      predicate_(std::move(predicate)),
+      provider_host_iterator_(map_->begin()) {
+  ForwardUntilMatchingProviderHost();
 }
 
-void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
-  process_iterator_.reset(new ProcessToProviderMap::iterator(map_));
-  // Advance to the first element.
-  while (!process_iterator_->IsAtEnd()) {
-    ProviderMap* provider_map = process_iterator_->GetCurrentValue();
-    provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
-    if (ForwardUntilMatchingProviderHost())
-      return;
-    process_iterator_->Advance();
-  }
-}
-
-bool ServiceWorkerContextCore::ProviderHostIterator::
+void ServiceWorkerContextCore::ProviderHostIterator::
     ForwardUntilMatchingProviderHost() {
-  while (!provider_host_iterator_->IsAtEnd()) {
+  while (!IsAtEnd()) {
     if (predicate_.is_null() || predicate_.Run(GetProviderHost()))
-      return true;
-    provider_host_iterator_->Advance();
+      return;
+    provider_host_iterator_++;
   }
-  return false;
+  return;
 }
 
 ServiceWorkerContextCore::ServiceWorkerContextCore(
@@ -283,7 +255,7 @@
         observer_list,
     ServiceWorkerContextWrapper* wrapper)
     : wrapper_(wrapper),
-      providers_(std::make_unique<ProcessToProviderMap>()),
+      providers_(std::make_unique<ProviderByIdMap>()),
       provider_by_uuid_(std::make_unique<ProviderByClientUUIDMap>()),
       loader_factory_getter_(url_loader_factory_getter),
       force_update_on_page_load_(false),
@@ -329,52 +301,22 @@
 void ServiceWorkerContextCore::AddProviderHost(
     std::unique_ptr<ServiceWorkerProviderHost> host) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  int process_id = host->process_id();
   int provider_id = host->provider_id();
-  // Precreated hosts are stored in the same map regardless of process.
-  if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
-    process_id = ChildProcessHost::kInvalidUniqueID;
-  ProviderMap* map = GetProviderMapForProcess(process_id);
-  if (!map) {
-    providers_->AddWithID(std::make_unique<ProviderMap>(), process_id);
-    map = GetProviderMapForProcess(process_id);
-  }
-  map->AddWithID(std::move(host), provider_id);
+  providers_->emplace(provider_id, std::move(host));
 }
 
 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
-    int process_id,
     int provider_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  // Precreated hosts are stored in the same map regardless of process.
-  if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
-    process_id = ChildProcessHost::kInvalidUniqueID;
-  ProviderMap* map = GetProviderMapForProcess(process_id);
-  if (!map)
+  auto found = providers_->find(provider_id);
+  if (found == providers_->end())
     return nullptr;
-  return map->Lookup(provider_id);
+  return found->second.get();
 }
 
-void ServiceWorkerContextCore::RemoveProviderHost(
-    int process_id, int provider_id) {
+void ServiceWorkerContextCore::RemoveProviderHost(int provider_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  // Precreated hosts are stored in the same map regardless of process.
-  if (ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id))
-    process_id = ChildProcessHost::kInvalidUniqueID;
-  ProviderMap* map = GetProviderMapForProcess(process_id);
-  DCHECK(map);
-  map->Remove(provider_id);
-}
-
-void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
-    int process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  if (providers_->Lookup(process_id))
-    providers_->Remove(process_id);
-  // This function is used to prevent <process_id, provider_id> collisions when
-  // a render process host is reused with the same process id. Don't bother
-  // removing the providers in this process with browser-assigned ids, which
-  // live in a different map, since they have unique ids.
+  providers_->erase(provider_id);
 }
 
 std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator>
@@ -541,12 +483,6 @@
   return next_embedded_worker_id_++;
 }
 
-ServiceWorkerContextCore::ProviderMap*
-ServiceWorkerContextCore::GetProviderMapForProcess(int process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  return providers_->Lookup(process_id);
-}
-
 void ServiceWorkerContextCore::RegistrationComplete(
     const GURL& scope,
     ServiceWorkerContextCore::RegistrationCallback callback,
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index 1da46ff..c0cee8f 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -69,19 +69,18 @@
                               int64_t registration_id)>;
   using UnregistrationCallback =
       base::OnceCallback<void(blink::ServiceWorkerStatusCode status)>;
-  // TODO(falken): Change these to just use std::map.
-  using ProviderMap = base::IDMap<std::unique_ptr<ServiceWorkerProviderHost>>;
-  using ProcessToProviderMap = base::IDMap<std::unique_ptr<ProviderMap>>;
-
+  using ProviderByIdMap =
+      std::map<int, std::unique_ptr<ServiceWorkerProviderHost>>;
   using ProviderByClientUUIDMap =
       std::map<std::string, ServiceWorkerProviderHost*>;
 
   // Directory for ServiceWorkerStorage and ServiceWorkerCacheManager.
   static const base::FilePath::CharType kServiceWorkerDirectory[];
 
-  // Iterates over ServiceWorkerProviderHost objects in a ProcessToProviderMap.
-  // TODO(falken): This can just iterate over the simple map
-  // |providers_by_uuid_| for simplicity.
+  // Iterates over ServiceWorkerProviderHost objects in the ProviderByIdMap.
+  // Note: As ProviderHostIterator is operating on a member of
+  // ServiceWorkerContextCore, users must ensure the ServiceWorkerContextCore
+  // instance always outlives the ProviderHostIterator one.
   class CONTENT_EXPORT ProviderHostIterator {
    public:
     ~ProviderHostIterator();
@@ -93,15 +92,12 @@
     friend class ServiceWorkerContextCore;
     using ProviderHostPredicate =
         base::RepeatingCallback<bool(ServiceWorkerProviderHost*)>;
-    ProviderHostIterator(ProcessToProviderMap* map,
-                         ProviderHostPredicate predicate);
-    void Initialize();
-    bool ForwardUntilMatchingProviderHost();
+    ProviderHostIterator(ProviderByIdMap* map, ProviderHostPredicate predicate);
+    void ForwardUntilMatchingProviderHost();
 
-    ProcessToProviderMap* map_;
+    ProviderByIdMap* const map_;
     ProviderHostPredicate predicate_;
-    std::unique_ptr<ProcessToProviderMap::iterator> process_iterator_;
-    std::unique_ptr<ProviderMap::iterator> provider_host_iterator_;
+    ProviderByIdMap::iterator provider_host_iterator_;
 
     DISALLOW_COPY_AND_ASSIGN(ProviderHostIterator);
   };
@@ -161,14 +157,10 @@
   }
 
   // The context class owns the set of ProviderHosts.
-  //
-  // For browser-assigned provider ids, the |process_id| parameter is ignored,
-  // since they have unique ids.
   void AddProviderHost(
       std::unique_ptr<ServiceWorkerProviderHost> provider_host);
-  ServiceWorkerProviderHost* GetProviderHost(int process_id, int provider_id);
-  void RemoveProviderHost(int process_id, int provider_id);
-  void RemoveAllProviderHostsForProcess(int process_id);
+  ServiceWorkerProviderHost* GetProviderHost(int provider_id);
+  void RemoveProviderHost(int provider_id);
 
   // Returns a ProviderHost iterator for all service worker clients for the
   // |origin|. If |include_reserved_clients| is false, this only returns clients
@@ -304,8 +296,6 @@
     blink::ServiceWorkerStatusCode last_failure;
   };
 
-  ProviderMap* GetProviderMapForProcess(int process_id);
-
   void RegistrationComplete(const GURL& scope,
                             RegistrationCallback callback,
                             blink::ServiceWorkerStatusCode status,
@@ -345,9 +335,9 @@
   // Bind() to hold a reference to |wrapper_| until |this| is fully destroyed.
   ServiceWorkerContextWrapper* wrapper_;
 
-  // |providers_| owns the provider hosts. Hosts with browser-assigned provider
-  // ids (unique over all processes), are kept in the map for process id -1.
-  std::unique_ptr<ProcessToProviderMap> providers_;
+  // |providers_| owns the provider hosts.
+  std::unique_ptr<ProviderByIdMap> providers_;
+
   // |provider_by_uuid_| contains raw pointers to hosts owned by |providers_|.
   std::unique_ptr<ProviderByClientUUIDMap> provider_by_uuid_;
 
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index ae6b513..a758bd6 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -877,14 +877,10 @@
   ServiceWorkerProviderHost* host1_raw = host1.get();
   ServiceWorkerProviderHost* host2_raw = host2.get();
   ServiceWorkerProviderHost* host3_raw = host3.get();
-  ASSERT_TRUE(
-      context()->GetProviderHost(host1->process_id(), host1->provider_id()));
-  ASSERT_TRUE(
-      context()->GetProviderHost(host2->process_id(), host2->provider_id()));
-  ASSERT_TRUE(
-      context()->GetProviderHost(host3->process_id(), host3->provider_id()));
-  ASSERT_TRUE(
-      context()->GetProviderHost(host4->process_id(), host4->provider_id()));
+  ASSERT_TRUE(context()->GetProviderHost(host1->provider_id()));
+  ASSERT_TRUE(context()->GetProviderHost(host2->provider_id()));
+  ASSERT_TRUE(context()->GetProviderHost(host3->provider_id()));
+  ASSERT_TRUE(context()->GetProviderHost(host4->provider_id()));
 
   // Iterate over the client provider hosts that belong to kOrigin1.
   std::set<ServiceWorkerProviderHost*> results;
@@ -908,10 +904,10 @@
   EXPECT_EQ(1u, results.size());
   EXPECT_TRUE(ContainsKey(results, host2_raw));
 
-  context()->RemoveProviderHost(kRenderProcessId1, host1->provider_id());
-  context()->RemoveProviderHost(kRenderProcessId2, host2->provider_id());
-  context()->RemoveProviderHost(kRenderProcessId2, host3->provider_id());
-  context()->RemoveProviderHost(kRenderProcessId2, host4_provider_id);
+  context()->RemoveProviderHost(host1->provider_id());
+  context()->RemoveProviderHost(host2->provider_id());
+  context()->RemoveProviderHost(host3->provider_id());
+  context()->RemoveProviderHost(host4_provider_id);
 }
 
 class ServiceWorkerContextRecoveryTest
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 18ac03b3..1ac76b0 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -324,8 +324,7 @@
 
   // Shouldn't crash if the ProviderHost is deleted prior to completion of
   // the database lookup.
-  context()->RemoveProviderHost(helper_->mock_render_process_id(),
-                                provider_host_->provider_id());
+  context()->RemoveProviderHost(provider_host_->provider_id());
   EXPECT_FALSE(provider_host_.get());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
diff --git a/content/browser/service_worker/service_worker_navigation_handle.cc b/content/browser/service_worker/service_worker_navigation_handle.cc
index 16c0b2e..e86fb6f 100644
--- a/content/browser/service_worker/service_worker_navigation_handle.cc
+++ b/content/browser/service_worker/service_worker_navigation_handle.cc
@@ -32,8 +32,6 @@
 void ServiceWorkerNavigationHandle::OnCreatedProviderHost(
     blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
-      provider_info->provider_id));
   DCHECK(provider_info->host_ptr_info.is_valid() &&
          provider_info->client_request.is_pending());
 
diff --git a/content/browser/service_worker/service_worker_navigation_handle_core.cc b/content/browser/service_worker/service_worker_navigation_handle_core.cc
index f8024bd..26b0570 100644
--- a/content/browser/service_worker/service_worker_navigation_handle_core.cc
+++ b/content/browser/service_worker/service_worker_navigation_handle_core.cc
@@ -37,8 +37,6 @@
   DCHECK(provider_host);
   provider_host_ = std::move(provider_host);
 
-  DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
-      provider_info->provider_id));
   DCHECK(provider_info->host_ptr_info.is_valid() &&
          provider_info->client_request.is_pending());
   base::PostTaskWithTraits(
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 379830f5..c19abba 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -56,12 +56,11 @@
 
 namespace {
 
-// Used for provider hosts precreated by the browser process (navigations or
-// service worker execution contexts). This function provides the next
-// ServiceWorkerProviderHost ID for them, starts at -2 and keeps going down.
-int NextBrowserProvidedProviderId() {
-  static int g_next_browser_provided_provider_id = -2;
-  return g_next_browser_provided_provider_id--;
+// This function provides the next ServiceWorkerProviderHost ID, starts at -2
+// and keeps going down.
+int NextProviderId() {
+  static int g_next_provider_id = -2;
+  return g_next_provider_id--;
 }
 
 // A request handler derivative used to handle navigation requests when
@@ -114,19 +113,18 @@
 };
 
 void RemoveProviderHost(base::WeakPtr<ServiceWorkerContextCore> context,
-                        int process_id,
                         int provider_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerProviderHost::RemoveProviderHost");
-  if (!context || !context->GetProviderHost(process_id, provider_id)) {
+  if (!context || !context->GetProviderHost(provider_id)) {
     // In some cases, it is possible for the Mojo endpoint of a pre-created
     // host to be destroyed before being claimed by the renderer and
     // having the host become owned by ServiceWorkerContextCore. The owner of
     // the host is responsible for deleting the host, so just return here.
     return;
   }
-  context->RemoveProviderHost(process_id, provider_id);
+  context->RemoveProviderHost(provider_id);
 }
 
 void GetInterfaceImpl(const std::string& interface_name,
@@ -267,7 +265,7 @@
     blink::mojom::ServiceWorkerContainerHostAssociatedRequest host_request,
     blink::mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info,
     base::WeakPtr<ServiceWorkerContextCore> context)
-    : provider_id_(NextBrowserProvidedProviderId()),
+    : provider_id_(NextProviderId()),
       type_(type),
       client_uuid_(base::GenerateGUID()),
       create_time_(base::TimeTicks::Now()),
@@ -292,8 +290,8 @@
   DCHECK(client_ptr_info.is_valid() && host_request.is_pending());
   container_.Bind(std::move(client_ptr_info));
   binding_.Bind(std::move(host_request));
-  binding_.set_connection_error_handler(base::BindOnce(
-      &RemoveProviderHost, context_, render_process_id_, provider_id_));
+  binding_.set_connection_error_handler(
+      base::BindOnce(&RemoveProviderHost, context_, provider_id_));
 }
 
 ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index e775ad4..5352e94 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -421,15 +421,14 @@
   // Create a provider host connected with the renderer process.
   ServiceWorkerProviderHost* provider_host =
       CreateProviderHost(GURL("https://www.example.com/example1.html"));
-  int process_id = provider_host->process_id();
   int provider_id = provider_host->provider_id();
-  EXPECT_TRUE(context_->GetProviderHost(process_id, provider_id));
+  EXPECT_TRUE(context_->GetProviderHost(provider_id));
 
   // Disconnect the mojo pipe from the renderer side.
   ASSERT_TRUE(remote_endpoints_.back().host_ptr()->is_bound());
   remote_endpoints_.back().host_ptr()->reset();
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(context_->GetProviderHost(process_id, provider_id));
+  EXPECT_FALSE(context_->GetProviderHost(provider_id));
 }
 
 class MockServiceWorkerContainer : public blink::mojom::ServiceWorkerContainer {
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc
index ec6bbfb..b32c8f49 100644
--- a/content/browser/service_worker/service_worker_request_handler.cc
+++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -173,7 +173,7 @@
   }
 
   ServiceWorkerProviderHost* provider_host =
-      context_wrapper->context()->GetProviderHost(process_id, provider_id);
+      context_wrapper->context()->GetProviderHost(provider_id);
   if (!provider_host || !provider_host->IsContextAlive())
     return;
 
diff --git a/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
index 11fcba6..0e8e130 100644
--- a/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
+++ b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -151,8 +151,7 @@
 }
 
 TEST_F(ServiceWorkerScriptLoaderFactoryTest, NoProviderHost) {
-  helper_->context()->RemoveProviderHost(helper_->mock_render_process_id(),
-                                         provider_host_->provider_id());
+  helper_->context()->RemoveProviderHost(provider_host_->provider_id());
 
   network::TestURLLoaderClient client;
   network::mojom::URLLoaderPtr loader = CreateTestLoaderAndStart(&client);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 08e2c20..70b1ec6 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -5991,7 +5991,7 @@
       process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
   int frame_routing_id =
       node->render_manager()->speculative_frame_host()->GetRoutingID();
-  int proxy_routing_id =
+  int previous_routing_id =
       node->render_manager()->GetProxyToParent()->GetRoutingID();
 
   // Now go to c.com so the navigation to a.com is cancelled and send an IPC
@@ -6008,7 +6008,7 @@
         &params->interface_bundle->document_interface_broker_content);
     mojo::MakeRequest(
         &params->interface_bundle->document_interface_broker_blink);
-    params->proxy_routing_id = proxy_routing_id;
+    params->previous_routing_id = previous_routing_id;
     params->opener_routing_id = IPC::mojom::kRoutingIdNone;
     params->parent_routing_id =
         shell()->web_contents()->GetMainFrame()->GetRoutingID();
@@ -6079,7 +6079,7 @@
         &params->interface_bundle->document_interface_broker_content);
     mojo::MakeRequest(
         &params->interface_bundle->document_interface_broker_blink);
-    params->proxy_routing_id = IPC::mojom::kRoutingIdNone;
+    params->previous_routing_id = IPC::mojom::kRoutingIdNone;
     params->opener_routing_id = IPC::mojom::kRoutingIdNone;
     params->parent_routing_id = parent_routing_id;
     params->previous_sibling_routing_id = IPC::mojom::kRoutingIdNone;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index d80128a..0c5634c 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -6429,7 +6429,7 @@
 
 bool WebContentsImpl::CreateRenderFrameForRenderManager(
     RenderFrameHost* render_frame_host,
-    int proxy_routing_id,
+    int previous_routing_id,
     int opener_routing_id,
     int parent_routing_id,
     int previous_sibling_routing_id) {
@@ -6438,7 +6438,7 @@
 
   RenderFrameHostImpl* rfh =
       static_cast<RenderFrameHostImpl*>(render_frame_host);
-  if (!rfh->CreateRenderFrame(proxy_routing_id, opener_routing_id,
+  if (!rfh->CreateRenderFrame(previous_routing_id, opener_routing_id,
                               parent_routing_id, previous_sibling_routing_id))
     return false;
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 25fcc96d..c81ed2e2 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -796,7 +796,7 @@
       RenderViewHost* render_view_host) override;
   bool CreateRenderFrameForRenderManager(
       RenderFrameHost* render_frame_host,
-      int proxy_routing_id,
+      int previous_routing_id,
       int opener_routing_id,
       int parent_routing_id,
       int previous_sibling_routing_id) override;
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.cc b/content/browser/web_package/signed_exchange_cert_fetcher.cc
index d72a0ed8..84457b8 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -151,6 +151,8 @@
 void SignedExchangeCertFetcher::Abort() {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
                "SignedExchangeCertFetcher::Abort");
+  MaybeNotifyCompletionToDevtools(
+      network::URLLoaderCompletionStatus(net::ERR_ABORTED));
   DCHECK(callback_);
   url_loader_ = nullptr;
   body_.reset();
@@ -193,6 +195,10 @@
   body_.reset();
   handle_watcher_ = nullptr;
 
+  // Notify the completion to the devtools here because |this| may be deleted
+  // before OnComplete() is called.
+  MaybeNotifyCompletionToDevtools(network::URLLoaderCompletionStatus(net::OK));
+
   std::unique_ptr<SignedExchangeCertificateChain> cert_chain =
       SignedExchangeCertificateChain::Parse(
           base::as_bytes(base::make_span(body_string_)), devtools_proxy_);
@@ -308,14 +314,20 @@
     const network::URLLoaderCompletionStatus& status) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
                "SignedExchangeCertFetcher::OnComplete");
-  if (devtools_proxy_) {
-    DCHECK(cert_request_id_);
-    devtools_proxy_->CertificateRequestCompleted(*cert_request_id_, status);
-  }
+  MaybeNotifyCompletionToDevtools(status);
   if (!handle_watcher_)
     Abort();
 }
 
+void SignedExchangeCertFetcher::MaybeNotifyCompletionToDevtools(
+    const network::URLLoaderCompletionStatus& status) {
+  if (!devtools_proxy_ || has_notified_completion_to_devtools_)
+    return;
+  DCHECK(cert_request_id_);
+  devtools_proxy_->CertificateRequestCompleted(*cert_request_id_, status);
+  has_notified_completion_to_devtools_ = true;
+}
+
 // static
 base::ScopedClosureRunner SignedExchangeCertFetcher::SetMaxCertSizeForTest(
     size_t max_cert_size) {
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.h b/content/browser/web_package/signed_exchange_cert_fetcher.h
index 283e81e7..7e3f3a3 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher.h
+++ b/content/browser/web_package/signed_exchange_cert_fetcher.h
@@ -84,6 +84,9 @@
   void OnHandleReady(MojoResult result);
   void OnDataComplete();
 
+  void MaybeNotifyCompletionToDevtools(
+      const network::URLLoaderCompletionStatus& status);
+
   // network::mojom::URLLoaderClient
   void OnReceiveResponse(const network::ResourceResponseHead& head) override;
   void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
@@ -109,6 +112,7 @@
 
   // This is owned by SignedExchangeHandler which is the owner of |this|.
   SignedExchangeDevToolsProxy* devtools_proxy_;
+  bool has_notified_completion_to_devtools_ = false;
   // This is owned by SignedExchangeLoader which owns SignedExchangeHandler
   // that is the owner of |this|.
   SignedExchangeReporter* reporter_;
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc
index 86d0026e9..b27c2e0a 100644
--- a/content/browser/web_package/signed_exchange_loader.cc
+++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -45,7 +45,8 @@
 net::RedirectInfo CreateRedirectInfo(
     const GURL& new_url,
     const network::ResourceRequest& outer_request,
-    const network::ResourceResponseHead& outer_response) {
+    const network::ResourceResponseHead& outer_response,
+    bool is_fallback_redirect) {
   // https://wicg.github.io/webpackage/loading.html#mp-http-fetch
   // Step 3. Set actualResponse's status to 303. [spec text]
   return net::RedirectInfo::ComputeRedirectInfo(
@@ -58,7 +59,8 @@
       outer_request.referrer_policy, outer_request.referrer.spec(), 303,
       new_url,
       net::RedirectUtil::GetReferrerPolicyHeader(outer_response.headers.get()),
-      false /* insecure_scheme_was_upgraded */);
+      false /* insecure_scheme_was_upgraded */, true /* copy_fragment */,
+      is_fallback_redirect);
 }
 
 bool HasNoSniffHeader(const network::ResourceResponseHead& response) {
@@ -302,7 +304,8 @@
     fallback_url_ = request_url;
     DCHECK(outer_response_timing_info_);
     forwarding_client_->OnReceiveRedirect(
-        CreateRedirectInfo(request_url, outer_request_, outer_response_),
+        CreateRedirectInfo(request_url, outer_request_, outer_response_,
+                           true /* is_fallback_redirect */),
         std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
     forwarding_client_.reset();
     return;
@@ -312,7 +315,8 @@
 
   DCHECK(outer_response_timing_info_);
   forwarding_client_->OnReceiveRedirect(
-      CreateRedirectInfo(request_url, outer_request_, outer_response_),
+      CreateRedirectInfo(request_url, outer_request_, outer_response_,
+                         false /* is_fallback_redirect */),
       std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
   forwarding_client_.reset();
 
diff --git a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index 59a9a894..d0eac74 100644
--- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -771,6 +771,8 @@
     https_server_.ServeFilesFromSourceDirectory("content/test/data");
     https_server_.RegisterRequestHandler(
         base::BindRepeating(&self::RedirectResponseHandler));
+    https_server_.RegisterRequestHandler(
+        base::BindRepeating(&self::FallbackSxgResponseHandler));
     https_server_.RegisterRequestMonitor(
         base::BindRepeating(&self::MonitorRequest, base::Unretained(this)));
     ASSERT_TRUE(https_server_.Start());
@@ -785,16 +787,16 @@
     EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
   }
 
-  bool ShouldHaveSXGAcceptHeaderInEnabledOrigin() const { return GetParam(); }
+  bool IsSignedExchangeEnabled() const { return GetParam(); }
 
-  bool ShouldHaveSXGAcceptHeader() const { return GetParam(); }
-
-  void CheckAcceptHeader(const GURL& url, bool is_navigation) {
+  void CheckAcceptHeader(const GURL& url,
+                         bool is_navigation,
+                         bool is_fallback) {
     const auto accept_header = GetInterceptedAcceptHeader(url);
     ASSERT_TRUE(accept_header);
     EXPECT_EQ(
         *accept_header,
-        ShouldHaveSXGAcceptHeader()
+        IsSignedExchangeEnabled() && !is_fallback
             ? (is_navigation
                    ? std::string(network::kFrameAcceptHeader) +
                          std::string(kAcceptHeaderSignedExchangeSuffix)
@@ -806,14 +808,22 @@
   void CheckNavigationAcceptHeader(const std::vector<GURL>& urls) {
     for (const auto& url : urls) {
       SCOPED_TRACE(url);
-      CheckAcceptHeader(url, true /* is_navigation */);
+      CheckAcceptHeader(url, true /* is_navigation */, false /* is_fallback */);
     }
   }
 
   void CheckPrefetchAcceptHeader(const std::vector<GURL>& urls) {
     for (const auto& url : urls) {
       SCOPED_TRACE(url);
-      CheckAcceptHeader(url, false /* is_navigation */);
+      CheckAcceptHeader(url, false /* is_navigation */,
+                        false /* is_fallback */);
+    }
+  }
+
+  void CheckFallbackAcceptHeader(const std::vector<GURL>& urls) {
+    for (const auto& url : urls) {
+      SCOPED_TRACE(url);
+      CheckAcceptHeader(url, true /* is_navigation */, true /* is_fallback */);
     }
   }
 
@@ -844,6 +854,33 @@
     return std::move(http_response);
   }
 
+  // Responds with a prologue-only signed exchange that triggers a fallback
+  // redirect.
+  static std::unique_ptr<net::test_server::HttpResponse>
+  FallbackSxgResponseHandler(const net::test_server::HttpRequest& request) {
+    const std::string prefix = "/fallback_sxg?";
+    if (!base::StartsWith(request.relative_url, prefix,
+                          base::CompareCase::SENSITIVE)) {
+      return std::unique_ptr<net::test_server::HttpResponse>();
+    }
+    std::string fallback_url(request.relative_url.substr(prefix.length()));
+
+    std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
+        new net::test_server::BasicHttpResponse);
+    http_response->set_code(net::HTTP_OK);
+    http_response->set_content_type("application/signed-exchange;v=b3");
+
+    std::string sxg("sxg1-b3", 8);
+    sxg.push_back(fallback_url.length() >> 8);
+    sxg.push_back(fallback_url.length() & 0xff);
+    sxg += fallback_url;
+    // FallbackUrlAndAfter() requires 6 more bytes for sizes of next fields.
+    sxg.resize(sxg.length() + 6);
+
+    http_response->set_content(sxg);
+    return std::move(http_response);
+  }
+
   void MonitorRequest(const net::test_server::HttpRequest& request) {
     const auto it = request.headers.find(std::string(network::kAcceptHeader));
     if (it == request.headers.end())
@@ -860,7 +897,7 @@
 
 IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest, Simple) {
   const GURL test_url = https_server_.GetURL("/sxg/test.html");
-  EXPECT_EQ(ShouldHaveSXGAcceptHeaderInEnabledOrigin(),
+  EXPECT_EQ(IsSignedExchangeEnabled(),
             signed_exchange_utils::IsSignedExchangeHandlingEnabled());
   NavigateAndWaitForTitle(test_url, test_url.spec());
   CheckNavigationAcceptHeader({test_url});
@@ -877,6 +914,20 @@
 }
 
 IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
+                       FallbackRedirect) {
+  if (!IsSignedExchangeEnabled())
+    return;
+
+  const GURL fallback_url = https_server_.GetURL("/sxg/test.html");
+  const GURL test_url =
+      https_server_.GetURL("/fallback_sxg?" + fallback_url.spec());
+  NavigateAndWaitForTitle(test_url, fallback_url.spec());
+
+  CheckNavigationAcceptHeader({test_url});
+  CheckFallbackAcceptHeader({fallback_url});
+}
+
+IN_PROC_BROWSER_TEST_P(SignedExchangeAcceptHeaderBrowserTest,
                        PrefetchEnabledPageEnabledTarget) {
   const GURL target = https_server_.GetURL("/sxg/hello.txt");
   const GURL page_url =
@@ -922,13 +973,12 @@
 
     const std::string expected_title =
         is_generated_scope
-            ? (ShouldHaveSXGAcceptHeader() ? frame_accept_with_sxg
-                                           : frame_accept)
+            ? (IsSignedExchangeEnabled() ? frame_accept_with_sxg : frame_accept)
             : "Done";
     const base::Optional<std::string> expected_target_accept_header =
         is_generated_scope
             ? base::nullopt
-            : base::Optional<std::string>(ShouldHaveSXGAcceptHeader()
+            : base::Optional<std::string>(IsSignedExchangeEnabled()
                                               ? frame_accept_with_sxg
                                               : frame_accept);
 
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index e2c91ea0..7a9177d 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -876,6 +876,22 @@
   ExecuteJavascriptAndWaitForOk("verifyAfterAudioServiceCrash()");
 }
 
+// Test crashes on MSAN. See https://crbug.com/941934
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_GetUserMediaCloneAndApplyConstraints \
+  DISABLED_GetUserMediaCloneAndApplyConstraints
+#else
+#define MAYBE_GetUserMediaCloneAndApplyConstraints \
+  GetUserMediaCloneAndApplyConstraints
+#endif
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+                       MAYBE_GetUserMediaCloneAndApplyConstraints) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+  NavigateToURL(shell(), url);
+  ExecuteJavascriptAndWaitForOk("getUserMediaCloneAndApplyConstraints()");
+}
+
 // We run these tests with the audio service both in and out of the the browser
 // process to have waterfall coverage while the feature rolls out. It should be
 // removed after launch.
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom
index fb914afb..8bb126ba 100644
--- a/content/common/renderer.mojom
+++ b/content/common/renderer.mojom
@@ -102,9 +102,10 @@
   // Specifies the routing ID of the new RenderFrame object.
   int32 routing_id;
 
-  // If a valid |proxy_routing_id| is provided, the new frame will be
-  // configured to replace the proxy on commit.
-  int32 proxy_routing_id;
+  // If a valid |previous_routing_id| is provided, the new frame will be
+  // configured to replace either the previous frame or the previous proxy on
+  // commit.
+  int32 previous_routing_id;
 
   // Specifies the new frame's opener.  The opener will be null if this is
   // MSG_ROUTING_NONE.
diff --git a/content/common/service_worker/service_worker_utils.h b/content/common/service_worker/service_worker_utils.h
index 7a9a0c1..71d4ab5 100644
--- a/content/common/service_worker/service_worker_utils.h
+++ b/content/common/service_worker/service_worker_utils.h
@@ -58,11 +58,6 @@
   CONTENT_EXPORT static bool AllOriginsMatchAndCanAccessServiceWorkers(
       const std::vector<GURL>& urls);
 
-  // Returns true if the |provider_id| was assigned by the browser process.
-  static bool IsBrowserAssignedProviderId(int provider_id) {
-    return provider_id < kInvalidServiceWorkerProviderId;
-  }
-
   template <typename T>
   static std::string MojoEnumToString(T mojo_enum) {
     std::ostringstream oss;
diff --git a/content/public/browser/background_sync_context.h b/content/public/browser/background_sync_context.h
index fd7c4064..f4ec66a3 100644
--- a/content/public/browser/background_sync_context.h
+++ b/content/public/browser/background_sync_context.h
@@ -7,16 +7,9 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#endif
 
 namespace content {
 
-class BrowserContext;
 class StoragePartition;
 
 // One instance of this exists per StoragePartition, and services multiple child
@@ -27,30 +20,13 @@
  public:
   BackgroundSyncContext() = default;
 
-  // Process any pending Background Sync registrations.
+  // Process any pending Background Sync registrations for |storage_partition|.
   // This involves firing any sync events ready to be fired, and optionally
   // scheduling a job to wake up the browser when the next event needs to be
   // fired.
-  virtual void FireBackgroundSyncEvents(base::OnceClosure done_closure) = 0;
-
-#if defined(OS_ANDROID)
-  // Processes pending Background Sync registrations for all storage partitions
-  // in |browser_context|, and then runs  the |j_runnable| when done.
-  virtual void FireBackgroundSyncEventsAcrossPartitions(
-      BrowserContext* browser_context,
-      const base::android::JavaParamRef<jobject>& j_runnable) = 0;
-#endif
-
-  // Gets the soonest time delta from now, when the browser should be woken up
-  // to fire any Background Sync events.
-  virtual base::TimeDelta GetSoonestWakeupDelta() = 0;
-
-  // Gets the soonest time delta from now, when the browser should be woken up
-  // to fire any Background Sync events, across all storage partitions in
-  // |browser_context|, and invokes |callback| with it.
-  virtual void GetSoonestWakeupDeltaAcrossPartitions(
-      BrowserContext* browser_context,
-      base::OnceCallback<void(base::TimeDelta)> callback) = 0;
+  virtual void FireBackgroundSyncEventsForStoragePartition(
+      StoragePartition* storage_partition,
+      base::OnceClosure done_closure) = 0;
 
  protected:
   virtual ~BackgroundSyncContext() = default;
diff --git a/content/public/browser/background_sync_controller.h b/content/public/browser/background_sync_controller.h
index 50e6c4064..33ad82d 100644
--- a/content/public/browser/background_sync_controller.h
+++ b/content/public/browser/background_sync_controller.h
@@ -33,9 +33,16 @@
   // registered a background sync event.
   virtual void NotifyBackgroundSyncRegistered(const url::Origin& origin) {}
 
-  // Calculates the soonest wakeup delta across all storage partitions and
-  // schedules a background task to wake up the browser.
-  virtual void RunInBackground() {}
+  // If |enabled|, ensures that the browser is running when the device next goes
+  // online after |min_ms| has passed. The behavior is platform dependent:
+  // * Android: Registers a GCM task which verifies that the browser is running
+  // the next time the device goes online after |min_ms| has passed. If it's
+  // not, it starts it.
+  //
+  // * Other Platforms: (UNIMPLEMENTED) Keeps the browser alive via
+  // BackgroundModeManager until called with |enabled| = false. |min_ms| is
+  // ignored.
+  virtual void RunInBackground(bool enabled, int64_t min_ms) {}
 };
 
 }  // namespace content
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 0eb603ec..99e1f619 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -1258,7 +1258,7 @@
     version = WebURLResponse::kHTTPVersion_2_0;
   response->SetHTTPVersion(version);
   response->SetHttpStatusCode(headers->response_code());
-  response->SetHTTPStatusText(WebString::FromLatin1(headers->GetStatusText()));
+  response->SetHttpStatusText(WebString::FromLatin1(headers->GetStatusText()));
 
   // Build up the header map.
   size_t iter = 0;
diff --git a/content/renderer/media/stream/local_video_capturer_source.cc b/content/renderer/media/stream/local_video_capturer_source.cc
index 93cd648..d8a1005 100644
--- a/content/renderer/media/stream/local_video_capturer_source.cc
+++ b/content/renderer/media/stream/local_video_capturer_source.cc
@@ -4,6 +4,8 @@
 
 #include "content/renderer/media/stream/local_video_capturer_source.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "content/renderer/media/video_capture_impl_manager.h"
@@ -12,10 +14,13 @@
 
 namespace content {
 
-LocalVideoCapturerSource::LocalVideoCapturerSource(int session_id)
+LocalVideoCapturerSource::LocalVideoCapturerSource(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    int session_id)
     : session_id_(session_id),
       manager_(RenderThreadImpl::current()->video_capture_impl_manager()),
       release_device_cb_(manager_->UseDevice(session_id_)),
+      task_runner_(std::move(task_runner)),
       weak_factory_(this) {
   DCHECK(RenderThreadImpl::current());
 }
@@ -38,12 +43,13 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   running_callback_ = running_callback;
 
-  stop_capture_cb_ =
-      manager_->StartCapture(session_id_, params,
-                             media::BindToCurrentLoop(base::Bind(
-                                 &LocalVideoCapturerSource::OnStateUpdate,
-                                 weak_factory_.GetWeakPtr())),
-                             new_frame_callback);
+  stop_capture_cb_ = manager_->StartCapture(
+      session_id_, params,
+      media::BindToLoop(
+          task_runner_,
+          base::BindRepeating(&LocalVideoCapturerSource::OnStateUpdate,
+                              weak_factory_.GetWeakPtr())),
+      new_frame_callback);
 }
 
 void LocalVideoCapturerSource::RequestRefreshFrame() {
@@ -117,8 +123,10 @@
 
 // static
 std::unique_ptr<media::VideoCapturerSource> LocalVideoCapturerSource::Create(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     int session_id) {
-  return std::make_unique<LocalVideoCapturerSource>(session_id);
+  return std::make_unique<LocalVideoCapturerSource>(std::move(task_runner),
+                                                    session_id);
 }
 
 }  // namespace content
diff --git a/content/renderer/media/stream/local_video_capturer_source.h b/content/renderer/media/stream/local_video_capturer_source.h
index 02021c39..e04926d3 100644
--- a/content/renderer/media/stream/local_video_capturer_source.h
+++ b/content/renderer/media/stream/local_video_capturer_source.h
@@ -16,6 +16,10 @@
 #include "media/capture/video_capturer_source.h"
 #include "third_party/blink/public/common/media/video_capture.h"
 
+namespace base {
+class SingleThreadTaskRunner;
+}
+
 namespace content {
 
 class VideoCaptureImplManager;
@@ -26,8 +30,12 @@
 // implementation. This is a main Render thread only object.
 class LocalVideoCapturerSource : public media::VideoCapturerSource {
  public:
-  static std::unique_ptr<media::VideoCapturerSource> Create(int session_id);
-  explicit LocalVideoCapturerSource(int session_id);
+  static std::unique_ptr<media::VideoCapturerSource> Create(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      int session_id);
+  LocalVideoCapturerSource(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      int session_id);
   ~LocalVideoCapturerSource() override;
 
   // VideoCaptureSource Implementation.
@@ -58,6 +66,8 @@
   RunningCallback running_callback_;
   base::Closure stop_capture_cb_;
 
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
   // Bound to the main render thread.
   THREAD_CHECKER(thread_checker_);
 
diff --git a/content/renderer/media/stream/media_stream_center.cc b/content/renderer/media/stream/media_stream_center.cc
index bbcaf705..18bd3994 100644
--- a/content/renderer/media/stream/media_stream_center.cc
+++ b/content/renderer/media/stream/media_stream_center.cc
@@ -65,6 +65,14 @@
         media::SampleFormatToBitsPerChannel(media::kSampleFormatS16),  // min
         media::SampleFormatToBitsPerChannel(media::kSampleFormatS16)   // max
     };
+    auto parameters = media_stream_source->GetAudioParameters();
+    if (parameters.IsValid()) {
+      capabilities.channel_count = {1, parameters.channels()};
+      capabilities.sample_rate = {parameters.sample_rate(),
+                                  parameters.sample_rate()};
+      capabilities.latency = {parameters.GetBufferDuration().InSecondsF(),
+                              parameters.GetBufferDuration().InSecondsF()};
+    }
     source.SetCapabilities(capabilities);
   }
 
diff --git a/content/renderer/media/stream/remote_media_stream_track_adapter.cc b/content/renderer/media/stream/remote_media_stream_track_adapter.cc
index 9e579d0..ecb75e8 100644
--- a/content/renderer/media/stream/remote_media_stream_track_adapter.cc
+++ b/content/renderer/media/stream/remote_media_stream_track_adapter.cc
@@ -7,6 +7,7 @@
 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
 #include "content/renderer/media/webrtc/peer_connection_remote_audio_source.h"
 #include "content/renderer/media/webrtc/track_observer.h"
+#include "media/base/limits.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
 
diff --git a/content/renderer/media/stream/user_media_client_impl_unittest.cc b/content/renderer/media/stream/user_media_client_impl_unittest.cc
index b3f2374..864e154 100644
--- a/content/renderer/media/stream/user_media_client_impl_unittest.cc
+++ b/content/renderer/media/stream/user_media_client_impl_unittest.cc
@@ -180,6 +180,7 @@
                         bool request_video_input,
                         bool request_audio_output,
                         bool request_video_input_capabilities,
+                        bool request_audio_input_capabilities,
                         EnumerateDevicesCallback callback) override {
     NOTREACHED();
   }
diff --git a/content/renderer/media/stream/user_media_processor.cc b/content/renderer/media/stream/user_media_processor.cc
index 09f79b9..5fc0c78f 100644
--- a/content/renderer/media/stream/user_media_processor.cc
+++ b/content/renderer/media/stream/user_media_processor.cc
@@ -1004,6 +1004,21 @@
       media::SampleFormatToBitsPerChannel(media::kSampleFormatS16),  // min
       media::SampleFormatToBitsPerChannel(media::kSampleFormatS16)   // max
   };
+  auto device_parameters = audio_source->device().input;
+  if (device_parameters.IsValid()) {
+    capabilities.channel_count = {1, device_parameters.channels()};
+    capabilities.sample_rate = {std::min(blink::kAudioProcessingSampleRate,
+                                         device_parameters.sample_rate()),
+                                std::max(blink::kAudioProcessingSampleRate,
+                                         device_parameters.sample_rate())};
+    double fallback_latency = blink::kFallbackAudioLatencyMs / 1000;
+    capabilities.latency = {
+        std::min(fallback_latency,
+                 device_parameters.GetBufferDuration().InSecondsF()),
+        std::max(fallback_latency,
+                 device_parameters.GetBufferDuration().InSecondsF())};
+  }
+
   capabilities.device_id = blink::WebString::FromUTF8(device.id);
   if (device.group_id)
     capabilities.group_id = blink::WebString::FromUTF8(*device.group_id);
@@ -1056,7 +1071,9 @@
   return std::make_unique<MediaStreamVideoCapturerSource>(
       render_frame_->GetRoutingID(), stop_callback, device,
       current_request_info_->video_capture_settings().capture_params(),
-      base::BindRepeating(&LocalVideoCapturerSource::Create));
+      base::BindRepeating(
+          &LocalVideoCapturerSource::Create,
+          render_frame_->GetTaskRunner(blink::TaskType::kInternalMedia)));
 }
 
 void UserMediaProcessor::StartTracks(const std::string& label) {
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc
index d23f0f05..72f55ccd 100644
--- a/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -111,6 +111,7 @@
   GetMediaDevicesDispatcher()->EnumerateDevices(
       request_audio_input, request_video_input, request_audio_output,
       false /* request_video_input_capabilities */,
+      false /* request_audio_input_capabilities */,
       base::BindOnce(&PepperMediaDeviceManager::DevicesEnumerated, AsWeakPtr(),
                      callback, ToMediaDeviceType(type)));
 }
@@ -256,7 +257,9 @@
     blink::MediaDeviceType type,
     const std::vector<blink::WebMediaDeviceInfoArray>& enumeration,
     std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
-        video_input_capabilities) {
+        video_input_capabilities,
+    std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
+        audio_input_capabilities) {
   client_callback.Run(FromMediaDeviceInfoArray(type, enumeration[type]));
 }
 
diff --git a/content/renderer/pepper/pepper_media_device_manager.h b/content/renderer/pepper/pepper_media_device_manager.h
index 0d8f2f3..dd6f3e6 100644
--- a/content/renderer/pepper/pepper_media_device_manager.h
+++ b/content/renderer/pepper/pepper_media_device_manager.h
@@ -92,7 +92,9 @@
       blink::MediaDeviceType type,
       const std::vector<blink::WebMediaDeviceInfoArray>& enumeration,
       std::vector<blink::mojom::VideoInputDeviceCapabilitiesPtr>
-          video_input_capabilities);
+          video_input_capabilities,
+      std::vector<blink::mojom::AudioInputDeviceCapabilitiesPtr>
+          audio_input_capabilities);
 
   const blink::mojom::MediaStreamDispatcherHostPtr&
   GetMediaStreamDispatcherHost();
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index cae65621..1741f151 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1379,7 +1379,7 @@
     service_manager::mojom::InterfaceProviderPtr interface_provider,
     blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content,
     blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_blink,
-    int proxy_routing_id,
+    int previous_routing_id,
     int opener_routing_id,
     int parent_routing_id,
     int previous_sibling_routing_id,
@@ -1395,11 +1395,11 @@
   RenderViewImpl* render_view = nullptr;
   RenderFrameImpl* render_frame = nullptr;
   blink::WebLocalFrame* web_frame = nullptr;
-  if (proxy_routing_id == MSG_ROUTING_NONE) {
+  if (previous_routing_id == MSG_ROUTING_NONE) {
     // TODO(alexmos): This path is currently used only:
     // 1) When recreating a RenderFrame after a crash.
     // 2) In tests that issue this IPC directly.
-    // These two cases should be cleaned up to also pass a proxy_routing_id,
+    // These two cases should be cleaned up to also pass a previous_routing_id,
     // which would allow removing this branch altogether.  See
     // https://crbug.com/756790.
 
@@ -1441,7 +1441,7 @@
     render_frame->in_frame_tree_ = true;
   } else {
     RenderFrameProxy* proxy =
-        RenderFrameProxy::FromRoutingID(proxy_routing_id);
+        RenderFrameProxy::FromRoutingID(previous_routing_id);
     // The remote frame could've been detached while the remote-to-local
     // navigation was being initiated in the browser process. Drop the
     // navigation and don't create the frame in that case.  See
@@ -1461,7 +1461,7 @@
         render_view, routing_id, std::move(interface_provider),
         std::move(document_interface_broker_content), devtools_frame_token);
     render_frame->InitializeBlameContext(nullptr);
-    render_frame->proxy_routing_id_ = proxy_routing_id;
+    render_frame->previous_routing_id_ = previous_routing_id;
     proxy->set_provisional_frame_routing_id(routing_id);
     web_frame = blink::WebLocalFrame::CreateProvisional(
         render_frame, render_frame->blink_interface_registry_.get(),
@@ -1479,8 +1479,8 @@
   const bool is_main_frame = !web_frame->Parent();
 
   // Child frames require there to be a |parent_routing_id| present, for the
-  // remote parent frame. Though it is only used if the |proxy_routing_id| is
-  // not given, which happens in some corner cases.
+  // remote parent frame. Though it is only used if the |previous_routing_id|
+  // is not given, which happens in some corner cases.
   if (!is_main_frame)
     DCHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
 
@@ -1702,7 +1702,7 @@
       in_frame_tree_(false),
       render_view_(params.render_view),
       routing_id_(params.routing_id),
-      proxy_routing_id_(MSG_ROUTING_NONE),
+      previous_routing_id_(MSG_ROUTING_NONE),
 #if BUILDFLAG(ENABLE_PLUGINS)
       plugin_power_saver_helper_(nullptr),
 #endif
@@ -4300,9 +4300,9 @@
 
   // If this was a provisional frame with an associated proxy, tell the proxy
   // that it's no longer associated with this frame.
-  if (proxy_routing_id_ != MSG_ROUTING_NONE) {
+  if (previous_routing_id_ != MSG_ROUTING_NONE) {
     RenderFrameProxy* proxy =
-        RenderFrameProxy::FromRoutingID(proxy_routing_id_);
+        RenderFrameProxy::FromRoutingID(previous_routing_id_);
 
     // |proxy| should always exist.  Detaching the proxy would've also detached
     // this provisional frame.  The proxy should also not be associated with
@@ -4582,7 +4582,7 @@
             internal_data->effective_connection_type());
   }
 
-  if (proxy_routing_id_ != MSG_ROUTING_NONE) {
+  if (previous_routing_id_ != MSG_ROUTING_NONE) {
     // If this is a provisional frame associated with a proxy (i.e., a frame
     // created for a remote-to-local navigation), swap it into the frame tree
     // now.
@@ -6170,14 +6170,15 @@
 }
 
 bool RenderFrameImpl::SwapIn() {
-  CHECK_NE(proxy_routing_id_, MSG_ROUTING_NONE);
+  CHECK_NE(previous_routing_id_, MSG_ROUTING_NONE);
   CHECK(!in_frame_tree_);
 
   // The proxy should always exist.  If it was detached while the provisional
   // LocalFrame was being navigated, the provisional frame would've been
   // cleaned up by RenderFrameProxy::FrameDetached.  See
   // https://crbug.com/526304 and https://crbug.com/568676 for context.
-  RenderFrameProxy* proxy = RenderFrameProxy::FromRoutingID(proxy_routing_id_);
+  RenderFrameProxy* proxy =
+      RenderFrameProxy::FromRoutingID(previous_routing_id_);
   CHECK(proxy);
 
   unique_name_helper_.set_propagated_name(proxy->unique_name());
@@ -6187,7 +6188,7 @@
   if (!proxy->web_frame()->Swap(frame_))
     return false;
 
-  proxy_routing_id_ = MSG_ROUTING_NONE;
+  previous_routing_id_ = MSG_ROUTING_NONE;
   in_frame_tree_ = true;
 
   // If this is the main frame going from a remote frame to a local frame,
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 479181d..fe02f31 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -212,19 +212,19 @@
       const FrameReplicationState& replicated_state,
       bool has_committed_real_load);
 
-  // Creates a new RenderFrame with |routing_id|.  If |proxy_routing_id| is
+  // Creates a new RenderFrame with |routing_id|. If |previous_routing_id| is
   // MSG_ROUTING_NONE, it creates the Blink WebLocalFrame and inserts it into
-  // the frame tree after the frame identified by
-  // |previous_sibling_routing_id|, or as the first child if
-  // |previous_sibling_routing_id| is MSG_ROUTING_NONE. Otherwise, the frame is
-  // semi-orphaned until it commits, at which point it replaces the proxy
-  // identified by |proxy_routing_id|.
+  // the frame tree after the frame identified by |previous_sibling_routing_id|,
+  // or as the first child if |previous_sibling_routing_id| is MSG_ROUTING_NONE.
+  // Otherwise, the frame is semi-orphaned until it commits, at which point it
+  // replaces the previous object identified by |previous_routing_id|. The
+  // previous object can either be a RenderFrame or a RenderFrameProxy.
   // The frame's opener is set to the frame identified by |opener_routing_id|.
   // The frame is created as a child of the RenderFrame identified by
   // |parent_routing_id| or as the top-level frame if
   // the latter is MSG_ROUTING_NONE.
   // |devtools_frame_token| is passed from the browser and corresponds to the
-  // owner FrameTreeNode.  It can only be used for tagging requests and calls
+  // owner FrameTreeNode. It can only be used for tagging requests and calls
   // for context frame attribution. It should never be passed back to the
   // browser as a frame identifier in the control flows calls.
   //
@@ -237,7 +237,7 @@
       blink::mojom::DocumentInterfaceBrokerPtr
           document_interface_broker_content,
       blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_blink,
-      int proxy_routing_id,
+      int previous_routing_id,
       int opener_routing_id,
       int parent_routing_id,
       int previous_sibling_routing_id,
@@ -1080,7 +1080,7 @@
   // RenderFrameProxy it is associated with.  Return value indicates whether
   // the swap operation succeeded.  This should only be used for provisional
   // frames associated with a proxy, while the proxy is still in the frame
-  // tree.  If the associated proxy has been detached before this is called,
+  // tree. If the associated proxy has been detached before this is called,
   // this returns false and aborts the swap.
   bool SwapIn();
 
@@ -1481,11 +1481,12 @@
   RenderViewImpl* render_view_;
   int routing_id_;
 
-  // If this frame was created to replace a proxy, this will store the routing
-  // id of the proxy to replace at commit-time, at which time it will be
-  // cleared.
-  // TODO(creis): Remove this after switching to PlzNavigate.
-  int proxy_routing_id_;
+  // If this RenderFrame was created to replace a previous object, this will
+  // store its routing id. The previous object can be:
+  // - A RenderFrame. This requires RenderDocument to be enabled.
+  // - A RenderFrameProxy.
+  // At commit time, the two objects will be swapped and the old one cleared.
+  int previous_routing_id_;
 
   // Non-null when the RenderFrame is a local root for compositing, input,
   // layout, etc. A local frame is also a local root iff it does not have a
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 3fa6942..c33da733 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -2138,7 +2138,7 @@
   RenderFrameImpl::CreateFrame(
       params->routing_id, std::move(interface_provider),
       std::move(document_interface_broker_content),
-      std::move(document_interface_broker_blink), params->proxy_routing_id,
+      std::move(document_interface_broker_blink), params->previous_routing_id,
       params->opener_routing_id, params->parent_routing_id,
       params->previous_sibling_routing_id, params->devtools_frame_token,
       params->replication_state, compositor_deps, *params->widget_params,
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
index 3ff1a11..e87511f 100644
--- a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
+++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
@@ -62,8 +62,6 @@
     blink::mojom::ControllerServiceWorkerInfoPtr controller_info,
     scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) {
   DCHECK(provider_info);
-  DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
-      provider_info->provider_id));
 
   auto provider =
       base::WrapUnique(new ServiceWorkerNetworkProviderForFrame(frame));
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc
index a6b94d36..8f4209cd 100644
--- a/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -8,7 +8,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/atomic_sequence_num.h"
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -56,12 +55,6 @@
 
 }  // namespace
 
-// static
-int ServiceWorkerProviderContext::GetNextId() {
-  static base::AtomicSequenceNumber sequence;
-  return sequence.GetNext();  // We start at zero.
-}
-
 // For service worker clients.
 ServiceWorkerProviderContext::ServiceWorkerProviderContext(
     int provider_id,
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h
index 7bb9f599..73f68c1 100644
--- a/content/renderer/service_worker/service_worker_provider_context.h
+++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -64,9 +64,6 @@
       public blink::mojom::ServiceWorkerContainer,
       public blink::mojom::ServiceWorkerWorkerClientRegistry {
  public:
-  // Returns a unique id within this process.
-  static int GetNextId();
-
   // |provider_id| is used to identify this provider in IPC messages to the
   // browser process. |request| is an endpoint which is connected to
   // the content::ServiceWorkerProviderHost that notifies of changes to the
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc
index 18a200b..e5912b3 100644
--- a/content/renderer/worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -215,7 +215,7 @@
   delete this;
 }
 
-void EmbeddedSharedWorkerStub::SelectAppCacheID(long long app_cache_id) {
+void EmbeddedSharedWorkerStub::SelectAppCacheID(int64_t app_cache_id) {
   if (app_cache_host_) {
     // app_cache_host_ could become stale as it's owned by blink's
     // DocumentLoader. This method is assumed to be called while it's valid.
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h
index 5fb382c..f46c360 100644
--- a/content/renderer/worker/embedded_shared_worker_stub.h
+++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -85,7 +85,7 @@
   void WorkerScriptLoaded() override;
   void WorkerScriptLoadFailed() override;
   void WorkerScriptEvaluated(bool success) override;
-  void SelectAppCacheID(long long) override;
+  void SelectAppCacheID(int64_t) override;
   std::unique_ptr<blink::WebApplicationCacheHost> CreateApplicationCacheHost(
       blink::WebApplicationCacheHostClient*) override;
   std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 157fd13..df5475e8 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -14,6 +14,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/nullable_string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -1446,7 +1447,7 @@
 }
 
 void TestRunner::WorkQueue::ProcessWorkSoon() {
-  if (controller_->top_loading_frame_)
+  if (!controller_->loading_frames_.empty())
     return;
 
   if (!queue_.empty()) {
@@ -1488,8 +1489,9 @@
   }
 
   if (!controller_->web_test_runtime_flags_.wait_until_done() &&
-      !controller_->top_loading_frame_)
+      controller_->loading_frames_.empty()) {
     controller_->delegate_->TestFinished();
+  }
 }
 
 TestRunner::TestRunner(TestInterfaces* interfaces)
@@ -1538,7 +1540,7 @@
 
 void TestRunner::Reset() {
   is_web_platform_tests_mode_ = false;
-  top_loading_frame_ = nullptr;
+  loading_frames_.clear();
   web_test_runtime_flags_.Reset();
   mock_screen_orientation_client_->ResetData();
   drag_image_.reset();
@@ -1833,28 +1835,36 @@
   return test_is_running_ && frame->Top()->View() == main_view_;
 }
 
-void TestRunner::tryToSetTopLoadingFrame(blink::WebFrame* frame) {
+void TestRunner::AddLoadingFrame(blink::WebFrame* frame) {
   if (!IsFramePartOfMainTestWindow(frame))
     return;
 
-  if (top_loading_frame_ || web_test_runtime_flags_.have_top_loading_frame())
-    return;
+  if (loading_frames_.empty()) {
+    // Don't do anything if another renderer process is already tracking the
+    // loading frames.
+    if (web_test_runtime_flags_.have_loading_frame())
+      return;
+    web_test_runtime_flags_.set_have_loading_frame(true);
+    OnWebTestRuntimeFlagsChanged();
+  }
 
-  top_loading_frame_ = frame;
-  web_test_runtime_flags_.set_have_top_loading_frame(true);
-  OnWebTestRuntimeFlagsChanged();
+  loading_frames_.push_back(frame);
 }
 
-void TestRunner::tryToClearTopLoadingFrame(blink::WebFrame* frame) {
+void TestRunner::RemoveLoadingFrame(blink::WebFrame* frame) {
   if (!IsFramePartOfMainTestWindow(frame))
     return;
 
-  if (frame != top_loading_frame_)
+  if (!base::ContainsValue(loading_frames_, frame))
     return;
 
-  top_loading_frame_ = nullptr;
-  DCHECK(web_test_runtime_flags_.have_top_loading_frame());
-  web_test_runtime_flags_.set_have_top_loading_frame(false);
+  DCHECK(web_test_runtime_flags_.have_loading_frame());
+
+  base::Erase(loading_frames_, frame);
+  if (!loading_frames_.empty())
+    return;
+
+  web_test_runtime_flags_.set_have_loading_frame(false);
   OnWebTestRuntimeFlagsChanged();
 
   LocationChangeDone();
@@ -2593,7 +2603,7 @@
 }
 
 void TestRunner::NotifyDone() {
-  if (web_test_runtime_flags_.wait_until_done() && !top_loading_frame_ &&
+  if (web_test_runtime_flags_.wait_until_done() && loading_frames_.empty() &&
       work_queue_.is_empty())
     delegate_->TestFinished();
   web_test_runtime_flags_.set_wait_until_done(false);
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index db9140e2..dab6e4e 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -136,17 +136,19 @@
   bool animation_requires_raster() const { return animation_requires_raster_; }
   void SetAnimationRequiresRaster(bool do_raster);
 
-  // To be called when |frame| starts loading - TestRunner will check if there
-  // is currently no top-loading-frame being tracked and if so, then it will
-  // start tracking |frame| as the top-loading-frame.
-  void tryToSetTopLoadingFrame(blink::WebFrame* frame);
+  // Add |frame| to the set of loading frames.
+  //
+  // Note: Only one renderer process is really tracking the loading frames. This
+  //       is the first to observe one. Both local and remote frames are tracked
+  //       by this process.
+  void AddLoadingFrame(blink::WebFrame* frame);
 
-  // To be called when |frame| finishes loading - TestRunner will check if
-  // |frame| is currently tracked as the top-loading-frame, if yes, stop
-  // top-loading-frame tracking, and potentially finish the test (unless
-  // testRunner.waitUntilDone() was called and/or there are pending load
-  // requests in WorkQueue).
-  void tryToClearTopLoadingFrame(blink::WebFrame*);
+  // Remove |frame| from the set of loading frames.
+  //
+  // When there are no more loading frames, this potentially finishes the test,
+  // unless testRunner.waitUntilDone() was called and/or there are pending load
+  // requests in WorkQueue.
+  void RemoveLoadingFrame(blink::WebFrame* frame);
 
   blink::WebFrame* mainFrame() const;
   void policyDelegateDone();
@@ -556,8 +558,8 @@
   WebTestDelegate* delegate_;
   blink::WebView* main_view_;
 
-  // This is non-0 IFF a load is in progress.
-  blink::WebFrame* top_loading_frame_;
+  // This is non empty when a load is in progress.
+  std::vector<blink::WebFrame*> loading_frames_;
 
   // WebContentSettingsClient mock object.
   std::unique_ptr<MockContentSettingsClient> mock_content_settings_client_;
diff --git a/content/shell/test_runner/web_frame_test_client.cc b/content/shell/test_runner/web_frame_test_client.cc
index ccf1365..f10f8d5 100644
--- a/content/shell/test_runner/web_frame_test_client.cc
+++ b/content/shell/test_runner/web_frame_test_client.cc
@@ -404,12 +404,11 @@
 }
 
 void WebFrameTestClient::DidStartLoading() {
-  test_runner()->tryToSetTopLoadingFrame(web_frame_test_proxy_->GetWebFrame());
+  test_runner()->AddLoadingFrame(web_frame_test_proxy_->GetWebFrame());
 }
 
 void WebFrameTestClient::DidStopLoading() {
-  test_runner()->tryToClearTopLoadingFrame(
-      web_frame_test_proxy_->GetWebFrame());
+  test_runner()->RemoveLoadingFrame(web_frame_test_proxy_->GetWebFrame());
 }
 
 void WebFrameTestClient::DidDispatchPingLoader(const blink::WebURL& url) {
diff --git a/content/shell/test_runner/web_test_runtime_flags.cc b/content/shell/test_runner/web_test_runtime_flags.cc
index e21cfbd..b864bb1 100644
--- a/content/shell/test_runner/web_test_runtime_flags.cc
+++ b/content/shell/test_runner/web_test_runtime_flags.cc
@@ -54,7 +54,7 @@
 
   set_stay_on_page_after_handling_before_unload(false);
 
-  set_have_top_loading_frame(false);
+  set_have_loading_frame(false);
 
   set_can_open_windows(false);
 
diff --git a/content/shell/test_runner/web_test_runtime_flags.h b/content/shell/test_runner/web_test_runtime_flags.h
index 8175afd..046044f 100644
--- a/content/shell/test_runner/web_test_runtime_flags.h
+++ b/content/shell/test_runner/web_test_runtime_flags.h
@@ -153,11 +153,9 @@
   // Desired return value of WebLocalFrameClient::runModalBeforeUnloadDialog.
   DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(stay_on_page_after_handling_before_unload)
 
-  // Indicates if the test already tracks a top loading frame (in any of the
-  // renderer processes).  This flag is trying to prevent different renderer
-  // processes from tracking different top loading frames (i.e. main frame in
-  // one renderer and an OOPIF in another renderer).
-  DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(have_top_loading_frame)
+  // Indicates if one renderer process is in charge of tracking the loading
+  // frames. Only one can do it at a time.
+  DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(have_loading_frame)
 
   // If true, new windows can be opened via javascript or by plugins. By
   // default, set to false and can be toggled to true using
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 26687449..28a2ffa 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1385,7 +1385,6 @@
     "../browser/background_fetch/background_fetch_service_unittest.cc",
     "../browser/background_fetch/storage/database_helpers_unittest.cc",
     "../browser/background_fetch/storage/image_helpers_unittest.cc",
-    "../browser/background_sync/background_sync_launcher_unittest.cc",
     "../browser/background_sync/background_sync_manager_unittest.cc",
     "../browser/background_sync/background_sync_network_observer_unittest.cc",
     "../browser/background_sync/background_sync_service_impl_unittest.cc",
diff --git a/content/test/data/accessibility/event/checkbox-validity-expected-auralinux.txt b/content/test/data/accessibility/event/checkbox-validity-expected-auralinux.txt
new file mode 100644
index 0000000..df0cb66
--- /dev/null
+++ b/content/test/data/accessibility/event/checkbox-validity-expected-auralinux.txt
@@ -0,0 +1,4 @@
+STATE-CHANGE:CHECKED:FALSE role=ROLE_CHECK_BOX name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE,REQUIRED,INVALID-ENTRY
+STATE-CHANGE:CHECKED:TRUE role=ROLE_CHECK_BOX name='(null)' CHECKED,ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE,REQUIRED
+STATE-CHANGE:INVALID-ENTRY:FALSE role=ROLE_CHECK_BOX name='(null)' CHECKED,ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE,REQUIRED
+STATE-CHANGE:INVALID-ENTRY:TRUE role=ROLE_CHECK_BOX name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE,REQUIRED,INVALID-ENTRY
diff --git a/content/test/data/accessibility/event/checkbox-validity.html b/content/test/data/accessibility/event/checkbox-validity.html
new file mode 100644
index 0000000..7195a1d
--- /dev/null
+++ b/content/test/data/accessibility/event/checkbox-validity.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<form>
+    <input id="in1" type="checkbox" required>
+    <input id="in2" type="checkbox" required checked="true">
+</form>
+<script>
+    function go() {
+        document.getElementById('in1').checked = true;
+        document.getElementById('in2').checked = false;
+    }
+</script>
\ No newline at end of file
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html
index 23e2568..ecedfb0 100644
--- a/content/test/data/media/getusermedia.html
+++ b/content/test/data/media/getusermedia.html
@@ -916,6 +916,38 @@
     }
   }
 
+  function playStreamAndGetElement(stream) {
+    v = document.createElement("video");
+    document.body.append(v);
+    v.srcObject = stream;
+    v.play();
+    return v;
+  }
+
+  async function getUserMediaCloneAndApplyConstraints() {
+    const stream = await navigator.mediaDevices.getUserMedia({video: { width: 640, height: 480 }});
+    const video = playStreamAndGetElement(stream);
+
+    const clone1 = stream.clone();
+    await clone1.getVideoTracks()[0].applyConstraints({width: 500, height: 500});
+    const video1 = playStreamAndGetElement(clone1);
+
+    const clone2 = stream.clone();
+    await clone2.getVideoTracks()[0].applyConstraints({width: 100, height: 100});
+    const video2 = playStreamAndGetElement(clone2);
+
+    var numFrames = 0;
+    var numOnProgress = 0;
+    video2.onprogress = () => {
+      numFrames += video2.webkitDecodedFrameCount;
+      ++numOnProgress;
+      if (numFrames >= 1)
+        reportTestSuccess();
+      if (numOnProgress > 20)
+        failTest("track from cloned stream is not producing any frames");
+    }
+  }
+
   </script>
 </head>
 <body>
diff --git a/content/test/mock_background_sync_controller.cc b/content/test/mock_background_sync_controller.cc
index b671965..13b94930 100644
--- a/content/test/mock_background_sync_controller.cc
+++ b/content/test/mock_background_sync_controller.cc
@@ -12,8 +12,11 @@
   registration_origin_ = origin;
 }
 
-void MockBackgroundSyncController::RunInBackground() {
+void MockBackgroundSyncController::RunInBackground(bool enabled,
+                                                   int64_t min_ms) {
   run_in_background_count_ += 1;
+  run_in_background_enabled_ = enabled;
+  run_in_background_min_ms_ = min_ms;
 }
 
 void MockBackgroundSyncController::GetParameterOverrides(
diff --git a/content/test/mock_background_sync_controller.h b/content/test/mock_background_sync_controller.h
index 3f97681..0a854ea 100644
--- a/content/test/mock_background_sync_controller.h
+++ b/content/test/mock_background_sync_controller.h
@@ -9,7 +9,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/time/time.h"
 #include "content/public/browser/background_sync_controller.h"
 #include "content/public/browser/background_sync_parameters.h"
 #include "url/gurl.h"
@@ -25,7 +24,7 @@
 
   // BackgroundSyncController:
   void NotifyBackgroundSyncRegistered(const url::Origin& origin) override;
-  void RunInBackground() override;
+  void RunInBackground(bool enabled, int64_t min_ms) override;
   void GetParameterOverrides(
       BackgroundSyncParameters* parameters) const override;
 
@@ -34,6 +33,8 @@
     return registration_origin_;
   }
   int run_in_background_count() const { return run_in_background_count_; }
+  bool run_in_background_enabled() const { return run_in_background_enabled_; }
+  int64_t run_in_background_min_ms() const { return run_in_background_min_ms_; }
   BackgroundSyncParameters* background_sync_parameters() {
     return &background_sync_parameters_;
   }
@@ -43,6 +44,8 @@
   url::Origin registration_origin_;
 
   int run_in_background_count_ = 0;
+  bool run_in_background_enabled_ = true;
+  int64_t run_in_background_min_ms_ = 0;
   BackgroundSyncParameters background_sync_parameters_;
 
   DISALLOW_COPY_AND_ASSIGN(MockBackgroundSyncController);
diff --git a/content/test/test_background_sync_manager.cc b/content/test/test_background_sync_manager.cc
index 0635711..3e95d08 100644
--- a/content/test/test_background_sync_manager.cc
+++ b/content/test/test_background_sync_manager.cc
@@ -118,9 +118,4 @@
   BackgroundSyncManager::GetDataFromBackend(key, std::move(callback));
 }
 
-base::TimeDelta TestBackgroundSyncManager::GetSoonestWakeupDelta() {
-  soonest_wakeup_delta_ = BackgroundSyncManager::GetSoonestWakeupDelta();
-  return soonest_wakeup_delta_;
-}
-
 }  // namespace content
diff --git a/content/test/test_background_sync_manager.h b/content/test/test_background_sync_manager.h
index 4fd6508c..a4566e0c 100644
--- a/content/test/test_background_sync_manager.h
+++ b/content/test/test_background_sync_manager.h
@@ -86,13 +86,6 @@
     return parameters_.get();
   }
 
-  bool IsBrowserWakeupScheduled() const {
-    return !soonest_wakeup_delta_.is_max();
-  }
-  bool EqualsSoonestWakeupDelta(base::TimeDelta compare_to) const {
-    return soonest_wakeup_delta_ == compare_to;
-  }
-
  protected:
   // Override to allow delays to be injected by tests.
   void StoreDataInBackend(
@@ -126,8 +119,6 @@
   void HasMainFrameProviderHost(const url::Origin& origin,
                                 BoolCallback callback) override;
 
-  base::TimeDelta GetSoonestWakeupDelta() override;
-
  private:
   // Callback to resume the StoreDataInBackend operation, after explicit
   // delays injected by tests.
@@ -152,7 +143,6 @@
   DispatchSyncCallback dispatch_sync_callback_;
   base::OnceClosure delayed_task_;
   base::TimeDelta delayed_task_delta_;
-  base::TimeDelta soonest_wakeup_delta_;
 
   DISALLOW_COPY_AND_ASSIGN(TestBackgroundSyncManager);
 };
diff --git a/device/usb/mojo/type_converters.cc b/device/usb/mojo/type_converters.cc
index 65e3a791..73e973a 100644
--- a/device/usb/mojo/type_converters.cc
+++ b/device/usb/mojo/type_converters.cc
@@ -25,6 +25,11 @@
   info->direction = endpoint.direction;
   info->type = endpoint.transfer_type;
   info->packet_size = static_cast<uint32_t>(endpoint.maximum_packet_size);
+  info->synchronization_type = endpoint.synchronization_type;
+  info->usage_type = endpoint.usage_type;
+  info->polling_interval = endpoint.polling_interval;
+  info->extra_data.assign(endpoint.extra_data.begin(),
+                          endpoint.extra_data.end());
   return info;
 }
 
@@ -38,6 +43,8 @@
   info->class_code = interface.interface_class;
   info->subclass_code = interface.interface_subclass;
   info->protocol_code = interface.interface_protocol;
+  info->extra_data.assign(interface.extra_data.begin(),
+                          interface.extra_data.end());
 
   // Filter out control endpoints for the public interface.
   info->endpoints.reserve(interface.endpoints.size());
@@ -87,9 +94,13 @@
                                               config) {
   auto info = device::mojom::UsbConfigurationInfo::New();
   info->configuration_value = config.configuration_value;
+  info->self_powered = config.self_powered;
+  info->remote_wakeup = config.remote_wakeup;
+  info->maximum_power = config.maximum_power;
   info->interfaces =
       mojo::ConvertTo<std::vector<device::mojom::UsbInterfaceInfoPtr>>(
           config.interfaces);
+  info->extra_data.assign(config.extra_data.begin(), config.extra_data.end());
   return info;
 }
 
diff --git a/device/usb/public/mojom/device.mojom b/device/usb/public/mojom/device.mojom
index 0d51a45..595a77d3 100644
--- a/device/usb/public/mojom/device.mojom
+++ b/device/usb/public/mojom/device.mojom
@@ -46,11 +46,34 @@
   INTERRUPT,
 };
 
+enum UsbSynchronizationType {
+  NONE = 0,
+  ASYNCHRONOUS,
+  ADAPTIVE,
+  SYNCHRONOUS,
+};
+
+enum UsbUsageType {
+  // Isochronous endpoint usages.
+  DATA = 0,
+  FEEDBACK,
+  EXPLICIT_FEEDBACK,
+  // Interrupt endpoint usages.
+  PERIODIC,
+  NOTIFICATION,
+  // Not currently defined by any spec.
+  RESERVED,
+};
+
 struct UsbEndpointInfo {
   uint8 endpoint_number;
   UsbTransferDirection direction;
   UsbTransferType type;
   uint32 packet_size;
+  UsbSynchronizationType synchronization_type;
+  UsbUsageType usage_type;
+  uint8 polling_interval;
+  array<uint8> extra_data;
 };
 
 struct UsbAlternateInterfaceInfo {
@@ -60,6 +83,7 @@
   uint8 protocol_code;
   mojo_base.mojom.String16? interface_name;
   array<UsbEndpointInfo> endpoints;
+  array<uint8> extra_data;
 };
 
 struct UsbInterfaceInfo {
@@ -70,7 +94,11 @@
 struct UsbConfigurationInfo {
   uint8 configuration_value;
   mojo_base.mojom.String16? configuration_name;
+  bool self_powered;
+  bool remote_wakeup;
+  uint8 maximum_power;
   array<UsbInterfaceInfo> interfaces;
+  array<uint8> extra_data;
 };
 
 struct UsbDeviceInfo {
diff --git a/device/usb/usb_descriptors.cc b/device/usb/usb_descriptors.cc
index 3b6502b..8a385d8 100644
--- a/device/usb/usb_descriptors.cc
+++ b/device/usb/usb_descriptors.cc
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -275,37 +276,37 @@
   switch (attributes & 0x0F) {
     // Isochronous endpoints only.
     case 0x05:
-      synchronization_type = USB_SYNCHRONIZATION_ASYNCHRONOUS;
+      synchronization_type = UsbSynchronizationType::ASYNCHRONOUS;
       break;
     case 0x09:
-      synchronization_type = USB_SYNCHRONIZATION_ADAPTIVE;
+      synchronization_type = UsbSynchronizationType::ADAPTIVE;
       break;
     case 0x0D:
-      synchronization_type = USB_SYNCHRONIZATION_SYNCHRONOUS;
+      synchronization_type = UsbSynchronizationType::SYNCHRONOUS;
       break;
     default:
-      synchronization_type = USB_SYNCHRONIZATION_NONE;
+      synchronization_type = UsbSynchronizationType::NONE;
   }
   switch (attributes & 0x33) {
     // Isochronous endpoint usages.
     case 0x01:
-      usage_type = USB_USAGE_DATA;
+      usage_type = UsbUsageType::DATA;
       break;
     case 0x11:
-      usage_type = USB_USAGE_FEEDBACK;
+      usage_type = UsbUsageType::FEEDBACK;
       break;
     case 0x21:
-      usage_type = USB_USAGE_EXPLICIT_FEEDBACK;
+      usage_type = UsbUsageType::EXPLICIT_FEEDBACK;
       break;
     // Interrupt endpoint usages.
     case 0x03:
-      usage_type = USB_USAGE_PERIODIC;
+      usage_type = UsbUsageType::PERIODIC;
       break;
     case 0x13:
-      usage_type = USB_USAGE_NOTIFICATION;
+      usage_type = UsbUsageType::NOTIFICATION;
       break;
     default:
-      usage_type = USB_USAGE_RESERVED;
+      usage_type = UsbUsageType::RESERVED;
   }
 }
 
diff --git a/device/usb/usb_descriptors.h b/device/usb/usb_descriptors.h
index 6704ba4..6f28f65 100644
--- a/device/usb/usb_descriptors.h
+++ b/device/usb/usb_descriptors.h
@@ -22,28 +22,11 @@
 
 using UsbTransferType = mojom::UsbTransferType;
 using UsbTransferDirection = mojom::UsbTransferDirection;
-
-enum UsbSynchronizationType {
-  USB_SYNCHRONIZATION_NONE = 0,
-  USB_SYNCHRONIZATION_ASYNCHRONOUS,
-  USB_SYNCHRONIZATION_ADAPTIVE,
-  USB_SYNCHRONIZATION_SYNCHRONOUS,
-};
-
-enum UsbUsageType {
-  // Isochronous endpoint usages.
-  USB_USAGE_DATA = 0,
-  USB_USAGE_FEEDBACK,
-  USB_USAGE_EXPLICIT_FEEDBACK,
-  // Interrupt endpoint usages.
-  USB_USAGE_PERIODIC,
-  USB_USAGE_NOTIFICATION,
-  // Not currently defined by any spec.
-  USB_USAGE_RESERVED,
-};
+using UsbSynchronizationType = mojom::UsbSynchronizationType;
+using UsbUsageType = mojom::UsbUsageType;
 
 struct UsbEndpointDescriptor {
-  UsbEndpointDescriptor(const uint8_t* data);
+  explicit UsbEndpointDescriptor(const uint8_t* data);
   UsbEndpointDescriptor(uint8_t address,
                         uint8_t attributes,
                         uint16_t maximum_packet_size,
@@ -63,7 +46,7 @@
 };
 
 struct UsbInterfaceDescriptor {
-  UsbInterfaceDescriptor(const uint8_t* data);
+  explicit UsbInterfaceDescriptor(const uint8_t* data);
   UsbInterfaceDescriptor(uint8_t interface_number,
                          uint8_t alternate_setting,
                          uint8_t interface_class,
@@ -85,7 +68,7 @@
 };
 
 struct UsbConfigDescriptor {
-  UsbConfigDescriptor(const uint8_t* data);
+  explicit UsbConfigDescriptor(const uint8_t* data);
   UsbConfigDescriptor(uint8_t configuration_value,
                       bool self_powered,
                       bool remote_wakeup,
diff --git a/device/usb/usb_descriptors_unittest.cc b/device/usb/usb_descriptors_unittest.cc
index b566a1e..6334f60 100644
--- a/device/usb/usb_descriptors_unittest.cc
+++ b/device/usb/usb_descriptors_unittest.cc
@@ -6,7 +6,10 @@
 
 #include <stdint.h>
 
+#include <algorithm>
 #include <memory>
+#include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
@@ -89,11 +92,12 @@
   EXPECT_EQ(UsbTransferDirection::INBOUND,
             config.interfaces[0].endpoints[0].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[0].maximum_packet_size);
-  EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
+  EXPECT_EQ(UsbSynchronizationType::NONE,
             config.interfaces[0].endpoints[0].synchronization_type);
   EXPECT_EQ(UsbTransferType::BULK,
             config.interfaces[0].endpoints[0].transfer_type);
-  EXPECT_EQ(USB_USAGE_RESERVED, config.interfaces[0].endpoints[0].usage_type);
+  EXPECT_EQ(UsbUsageType::RESERVED,
+            config.interfaces[0].endpoints[0].usage_type);
   EXPECT_EQ(0, config.interfaces[0].endpoints[0].polling_interval);
   EXPECT_EQ(0u, config.interfaces[0].endpoints[0].extra_data.size());
   // Endpoint 2 IN
@@ -101,11 +105,12 @@
   EXPECT_EQ(UsbTransferDirection::INBOUND,
             config.interfaces[0].endpoints[1].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[1].maximum_packet_size);
-  EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
+  EXPECT_EQ(UsbSynchronizationType::NONE,
             config.interfaces[0].endpoints[1].synchronization_type);
   EXPECT_EQ(UsbTransferType::INTERRUPT,
             config.interfaces[0].endpoints[1].transfer_type);
-  EXPECT_EQ(USB_USAGE_PERIODIC, config.interfaces[0].endpoints[1].usage_type);
+  EXPECT_EQ(UsbUsageType::PERIODIC,
+            config.interfaces[0].endpoints[1].usage_type);
   EXPECT_EQ(4, config.interfaces[0].endpoints[1].polling_interval);
   EXPECT_EQ(0u, config.interfaces[0].endpoints[1].extra_data.size());
   // Endpoint 3 OUT
@@ -113,11 +118,11 @@
   EXPECT_EQ(UsbTransferDirection::OUTBOUND,
             config.interfaces[0].endpoints[2].direction);
   EXPECT_EQ(512, config.interfaces[0].endpoints[2].maximum_packet_size);
-  EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
+  EXPECT_EQ(UsbSynchronizationType::NONE,
             config.interfaces[0].endpoints[2].synchronization_type);
   EXPECT_EQ(UsbTransferType::INTERRUPT,
             config.interfaces[0].endpoints[2].transfer_type);
-  EXPECT_EQ(USB_USAGE_NOTIFICATION,
+  EXPECT_EQ(UsbUsageType::NOTIFICATION,
             config.interfaces[0].endpoints[2].usage_type);
   EXPECT_EQ(4, config.interfaces[0].endpoints[2].polling_interval);
   EXPECT_EQ(0u, config.interfaces[0].endpoints[2].extra_data.size());
@@ -163,11 +168,11 @@
   EXPECT_EQ(UsbTransferDirection::INBOUND,
             config.interfaces[1].endpoints[0].direction);
   EXPECT_EQ(1024, config.interfaces[1].endpoints[0].maximum_packet_size);
-  EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
+  EXPECT_EQ(UsbSynchronizationType::NONE,
             config.interfaces[1].endpoints[0].synchronization_type);
   EXPECT_EQ(UsbTransferType::ISOCHRONOUS,
             config.interfaces[1].endpoints[0].transfer_type);
-  EXPECT_EQ(USB_USAGE_DATA, config.interfaces[1].endpoints[0].usage_type);
+  EXPECT_EQ(UsbUsageType::DATA, config.interfaces[1].endpoints[0].usage_type);
   EXPECT_EQ(8, config.interfaces[1].endpoints[0].polling_interval);
   EXPECT_EQ(0u, config.interfaces[1].endpoints[0].extra_data.size());
   // Endpoint 2 OUT
@@ -175,11 +180,12 @@
   EXPECT_EQ(UsbTransferDirection::OUTBOUND,
             config.interfaces[1].endpoints[1].direction);
   EXPECT_EQ(1024, config.interfaces[1].endpoints[1].maximum_packet_size);
-  EXPECT_EQ(USB_SYNCHRONIZATION_NONE,
+  EXPECT_EQ(UsbSynchronizationType::NONE,
             config.interfaces[1].endpoints[1].synchronization_type);
   EXPECT_EQ(UsbTransferType::ISOCHRONOUS,
             config.interfaces[1].endpoints[1].transfer_type);
-  EXPECT_EQ(USB_USAGE_FEEDBACK, config.interfaces[1].endpoints[1].usage_type);
+  EXPECT_EQ(UsbUsageType::FEEDBACK,
+            config.interfaces[1].endpoints[1].usage_type);
   EXPECT_EQ(8, config.interfaces[1].endpoints[1].polling_interval);
   EXPECT_EQ(0u, config.interfaces[1].endpoints[1].extra_data.size());
 }
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index e70e7cd..a1d2ea3 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -297,13 +297,13 @@
 SynchronizationType ConvertSynchronizationTypeToApi(
     const UsbSynchronizationType& input) {
   switch (input) {
-    case device::USB_SYNCHRONIZATION_NONE:
+    case UsbSynchronizationType::NONE:
       return usb::SYNCHRONIZATION_TYPE_NONE;
-    case device::USB_SYNCHRONIZATION_ASYNCHRONOUS:
+    case UsbSynchronizationType::ASYNCHRONOUS:
       return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
-    case device::USB_SYNCHRONIZATION_ADAPTIVE:
+    case UsbSynchronizationType::ADAPTIVE:
       return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
-    case device::USB_SYNCHRONIZATION_SYNCHRONOUS:
+    case UsbSynchronizationType::SYNCHRONOUS:
       return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
     default:
       NOTREACHED();
@@ -313,17 +313,17 @@
 
 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
   switch (input) {
-    case device::USB_USAGE_DATA:
+    case UsbUsageType::DATA:
       return usb::USAGE_TYPE_DATA;
-    case device::USB_USAGE_FEEDBACK:
+    case UsbUsageType::FEEDBACK:
       return usb::USAGE_TYPE_FEEDBACK;
-    case device::USB_USAGE_EXPLICIT_FEEDBACK:
+    case UsbUsageType::EXPLICIT_FEEDBACK:
       return usb::USAGE_TYPE_EXPLICITFEEDBACK;
-    case device::USB_USAGE_PERIODIC:
+    case UsbUsageType::PERIODIC:
       return usb::USAGE_TYPE_PERIODIC;
-    case device::USB_USAGE_NOTIFICATION:
+    case UsbUsageType::NOTIFICATION:
       return usb::USAGE_TYPE_NOTIFICATION;
-    case device::USB_USAGE_RESERVED:
+    case UsbUsageType::RESERVED:
       return usb::USAGE_TYPE_NONE;
     default:
       NOTREACHED();
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 3d986b6..8913381 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1386,6 +1386,8 @@
   AUTOTESTPRIVATE_SETTABLETMODEENABLED = 1323,
   AUTOTESTPRIVATE_GETSHELFAUTOHIDEBEHAVIOR = 1324,
   AUTOTESTPRIVATE_SETSHELFAUTOHIDEBEHAVIOR = 1325,
+  AUTOTESTPRIVATE_EXPORTCROSTINI = 1326,
+  AUTOTESTPRIVATE_IMPORTCROSTINI = 1327,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/common/permissions/usb_device_permission_unittest.cc b/extensions/common/permissions/usb_device_permission_unittest.cc
index 1eaea4c..dd8e347 100644
--- a/extensions/common/permissions/usb_device_permission_unittest.cc
+++ b/extensions/common/permissions/usb_device_permission_unittest.cc
@@ -43,15 +43,15 @@
   configs.push_back(std::move(config_2));
 
   for (size_t i = 0; i < interface_classes.size(); ++i) {
+    auto alternate = device::mojom::UsbAlternateInterfaceInfo::New();
+    alternate->alternate_setting = 0;
+    alternate->class_code = interface_classes[i];
+    alternate->subclass_code = 255;
+    alternate->protocol_code = 255;
+
     auto interface = device::mojom::UsbInterfaceInfo::New();
     interface->interface_number = i;
-    interface->alternates.push_back(
-        device::mojom::UsbAlternateInterfaceInfo::New(
-            /*alternate_setting=*/0, interface_classes[i],
-            /*subclass_code=*/255,
-            /*protocol_code=*/255,
-            /*interface_name=*/base::nullopt,
-            std::vector<device::mojom::UsbEndpointInfoPtr>()));
+    interface->alternates.push_back(std::move(std::move(alternate)));
 
     configs[0]->interfaces.push_back(std::move(interface));
   }
diff --git a/fuchsia/engine/context_provider_impl_unittest.cc b/fuchsia/engine/context_provider_impl_unittest.cc
index 9b3d3a4..961e1af 100644
--- a/fuchsia/engine/context_provider_impl_unittest.cc
+++ b/fuchsia/engine/context_provider_impl_unittest.cc
@@ -273,10 +273,7 @@
 
   // Pass a handle data dir to the context.
   create_params.set_data_directory(
-      fidl::InterfaceHandle<fuchsia::io::Directory>(
-          zx::channel(base::fuchsia::GetHandleFromFile(
-              base::File(profile_temp_dir.GetPath(),
-                         base::File::FLAG_OPEN | base::File::FLAG_READ)))));
+      base::fuchsia::OpenDirectory(profile_temp_dir.GetPath()));
 
   provider_ptr_->Create(std::move(create_params), context.NewRequest());
 
@@ -305,10 +302,7 @@
 
   // Pass a handle data dir to the context.
   create_params.set_data_directory(
-      fidl::InterfaceHandle<fuchsia::io::Directory>(
-          zx::channel(base::fuchsia::GetHandleFromFile(
-              base::File(profile_temp_dir.GetPath(),
-                         base::File::FLAG_OPEN | base::File::FLAG_READ)))));
+      base::fuchsia::OpenDirectory(profile_temp_dir.GetPath()));
 
   provider_ptr_->Create2(std::move(create_params), context.NewRequest());
 
@@ -329,10 +323,7 @@
   // Pass in a handle to a file instead of a directory.
   CHECK(base::CreateTemporaryFile(&temp_file_path));
   create_params.set_data_directory(
-      fidl::InterfaceHandle<fuchsia::io::Directory>(
-          zx::channel(base::fuchsia::GetHandleFromFile(
-              base::File(temp_file_path,
-                         base::File::FLAG_OPEN | base::File::FLAG_READ)))));
+      base::fuchsia::OpenDirectory(temp_file_path));
 
   provider_ptr_->Create(std::move(create_params), context.NewRequest());
 
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc
index ba7f504..961d50f 100644
--- a/fuchsia/runners/common/web_content_runner.cc
+++ b/fuchsia/runners/common/web_content_runner.cc
@@ -24,11 +24,9 @@
 
 namespace {
 
-fidl::InterfaceHandle<fuchsia::io::Directory> OpenDirectory(
+fidl::InterfaceHandle<fuchsia::io::Directory> OpenDirectoryOrFail(
     const base::FilePath& path) {
-  fidl::InterfaceHandle<fuchsia::io::Directory> directory(
-      zx::channel(base::fuchsia::GetHandleFromFile(
-          base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ))));
+  auto directory = base::fuchsia::OpenDirectory(path);
   CHECK(directory) << "Failed to open " << path;
   return directory;
 }
@@ -42,8 +40,8 @@
   chromium::web::CreateContextParams2 create_params;
 
   // Pass /svc and /data to the context.
-  create_params.set_service_directory(
-      OpenDirectory(base::FilePath(base::fuchsia::kServiceDirectoryPath)));
+  create_params.set_service_directory(OpenDirectoryOrFail(
+      base::FilePath(base::fuchsia::kServiceDirectoryPath)));
   if (data_directory)
     create_params.set_data_directory(std::move(data_directory));
 
@@ -63,8 +61,8 @@
 
 // static
 chromium::web::ContextPtr WebContentRunner::CreateDefaultWebContext() {
-  return CreateWebContextWithDataDirectory(
-      OpenDirectory(base::FilePath("/data")));
+  return CreateWebContextWithDataDirectory(OpenDirectoryOrFail(
+      base::FilePath(base::fuchsia::kPersistedDataDirectoryPath)));
 }
 
 // static
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index fea08b2..fc78b4d4 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3229,6 +3229,22 @@
       "features": [
         "exit_on_context_lost"
       ]
+    },
+    {
+      "id": 298,
+      "cr_bugs": [941716],
+      "description": "AImageReader is very crashy on this driver version",
+      "os": {
+        "type" : "android"
+      },
+      "gl_vendor": "Qualcomm.*",
+      "driver_version": {
+        "op": "=",
+        "value": "269.0"
+      },
+      "features": [
+        "disable_aimagereader"
+      ]
     }
   ]
 }
diff --git a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm
index 5f890535..e8299e6 100644
--- a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm
+++ b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm
@@ -432,8 +432,13 @@
                                                           delete_end);
 
       if (base::FeatureList::IsEnabled(
-              autofill::features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
+              autofill::features::kAutofillSaveCreditCardUsesStrikeSystemV2) ||
+          base::FeatureList::IsEnabled(
+              autofill::features::
+                  kAutofillLocalCardMigrationUsesStrikeSystemV2)) {
         // Clear out the Autofill StrikeDatabase in its entirety.
+        // Both StrikeDatabase and LegacyStrikeDatabase use data from the same
+        // ProtoDatabase, so only one of them needs to call ClearAllStrikes(~).
         autofill::StrikeDatabase* strike_database =
             autofill::StrikeDatabaseFactory::GetForBrowserState(browser_state_);
         if (strike_database)
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
index 4e91940..50e66c3 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
@@ -309,9 +309,16 @@
   [_parentController
       dismissViewControllerAnimated:animated
                          completion:^{
+                           // TODO(crbug.com/940856): Make sure navigaton
+                           // controller doesn't keep any controllers. Without
+                           // this there's a memory leak of (almost) every BHVC
+                           // the user visits.
+                           [self.bookmarkNavigationController
+                               setViewControllers:@[]
+                                         animated:NO];
+
                            self.bookmarkBrowser.homeDelegate = nil;
                            self.bookmarkBrowser = nil;
-                           self.bookmarkNavigationController = nil;
                            self.bookmarkTransitioningDelegate = nil;
                            self.bookmarkNavigationController = nil;
                            self.bookmarkNavigationControllerDelegate = nil;
diff --git a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.h b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.h
index 23ebcbc..bf70cd2 100644
--- a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.h
+++ b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.h
@@ -21,7 +21,7 @@
 - (instancetype)init NS_UNAVAILABLE;
 
 // The ChromeTableViewController owned by this ViewController.
-@property(nonatomic, readonly, strong)
+@property(nonatomic, readonly, weak)
     ChromeTableViewController* tableViewController;
 
 @end
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 83e4e8b..6c97832 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -2616,7 +2616,12 @@
     return;
   }
 
-  self.webStateImpl->SetIsLoading(false);
+  if (![_navigationStates lastNavigationWithPendingItemInNavigationContext] ||
+      !web::features::StorePendingItemInContext()) {
+    self.webStateImpl->SetIsLoading(false);
+  } else {
+    // There is another pending navigation, so the state is still loading.
+  }
   self.webStateImpl->OnPageLoaded(currentURL, YES);
 }
 
diff --git a/media/blink/resource_multibuffer_data_provider_unittest.cc b/media/blink/resource_multibuffer_data_provider_unittest.cc
index f1d95a78..917174b 100644
--- a/media/blink/resource_multibuffer_data_provider_unittest.cc
+++ b/media/blink/resource_multibuffer_data_provider_unittest.cc
@@ -245,7 +245,7 @@
 
   WebURLResponse response(gurl_);
   response.SetHttpStatusCode(404);
-  response.SetHTTPStatusText("Not Found\n");
+  response.SetHttpStatusText("Not Found\n");
   loader_->DidReceiveResponse(response);
 }
 
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc
index 74395cf..1ee9ee5 100644
--- a/net/url_request/redirect_info.cc
+++ b/net/url_request/redirect_info.cc
@@ -106,6 +106,7 @@
 RedirectInfo::RedirectInfo()
     : status_code(-1),
       insecure_scheme_was_upgraded(false),
+      is_signed_exchange_fallback_redirect(false),
       new_referrer_policy(
           URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE) {}
 
@@ -125,7 +126,8 @@
     const GURL& new_location,
     const base::Optional<std::string>& referrer_policy_header,
     bool insecure_scheme_was_upgraded,
-    bool copy_fragment) {
+    bool copy_fragment,
+    bool is_signed_exchange_fallback_redirect) {
   RedirectInfo redirect_info;
 
   redirect_info.status_code = http_status_code;
@@ -149,6 +151,8 @@
   }
 
   redirect_info.insecure_scheme_was_upgraded = insecure_scheme_was_upgraded;
+  redirect_info.is_signed_exchange_fallback_redirect =
+      is_signed_exchange_fallback_redirect;
 
   // Update the first-party URL if appropriate.
   if (original_first_party_url_policy ==
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h
index 7236455..524adf95 100644
--- a/net/url_request/redirect_info.h
+++ b/net/url_request/redirect_info.h
@@ -44,7 +44,9 @@
       // by default. Set false only when the network delegate has set the
       // desired redirect URL (with or without fragment), so it must not be
       // changed any more.
-      bool copy_fragment = true);
+      bool copy_fragment = true,
+      // Whether the redirect is caused by a failure of signed exchange loading.
+      bool is_signed_exchange_fallback_redirect = false);
 
   // The status code for the redirect response. This is almost redundant with
   // the response headers, but some URLRequestJobs emit redirects without
@@ -70,6 +72,9 @@
   // upgrade-insecure-requests policy.
   bool insecure_scheme_was_upgraded;
 
+  // True if this is a redirect from Signed Exchange to its fallback URL.
+  bool is_signed_exchange_fallback_redirect;
+
   // The new referrer policy that should be obeyed if there are
   // subsequent redirects.
   URLRequest::ReferrerPolicy new_referrer_policy;
diff --git a/remoting/host/win/get_clsids.py b/remoting/host/win/get_clsids.py
index b77b9735..92bcf02 100644
--- a/remoting/host/win/get_clsids.py
+++ b/remoting/host/win/get_clsids.py
@@ -9,18 +9,20 @@
 # The IDs are not random to avoid rebuilding host when it's not
 # necessary.
 
+from __future__ import print_function
+
 import uuid
 import sys
 
 if len(sys.argv) != 3:
-  print """Expecting 2 args:
-<rdp_desktop_session_guid> <version>"""
+  print("""Expecting 2 args:
+<rdp_desktop_session_guid> <version>""")
   sys.exit(1)
 
 rdp_desktop_session_guid = sys.argv[1]
 version_full = sys.argv[2]
 
 # Output a GN list of 1 strings.
-print '["' + \
-    str(uuid.uuid5(uuid.UUID(rdp_desktop_session_guid), version_full)) + '"]'
+print('["' + \
+    str(uuid.uuid5(uuid.UUID(rdp_desktop_session_guid), version_full)) + '"]')
 
diff --git a/services/network/DEPS b/services/network/DEPS
index 4d8cc1ac..d140caf 100644
--- a/services/network/DEPS
+++ b/services/network/DEPS
@@ -19,4 +19,5 @@
   "+services/service_manager/public",
   "+services/service_manager/sandbox",
   "+third_party/boringssl/src/include",
+  "+url",
 ]
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index f025c30..02b87cb 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -4752,9 +4752,8 @@
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=" +
                                 ConvertToProxyServer(invalid_server).ToURI());
-
-  config->alternate_proxy_list.AddProxyServer(
-      ConvertToProxyServer(proxy_test_server));
+  config->alternate_rules.ParseFromString(
+      "http=" + ConvertToProxyServer(proxy_test_server).ToURI());
   proxy_config_client->OnCustomProxyConfigUpdated(std::move(config));
   scoped_task_environment_.RunUntilIdle();
 
diff --git a/services/network/network_service_proxy_delegate.cc b/services/network/network_service_proxy_delegate.cc
index 5207d9b5..9bb15f7 100644
--- a/services/network/network_service_proxy_delegate.cc
+++ b/services/network/network_service_proxy_delegate.cc
@@ -9,6 +9,7 @@
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "services/network/url_loader.h"
+#include "url/url_constants.h"
 
 namespace network {
 namespace {
@@ -67,9 +68,42 @@
   return false;
 }
 
-// Whether the custom proxy can proxy |url|.
-bool IsURLValidForProxy(const GURL& url) {
-  return url.SchemeIs(url::kHttpScheme) && !net::IsLocalhost(url);
+// Returns true if there is a possibility that |proxy_rules->Apply()| can
+// choose |target_proxy|. This does not consider the bypass rules; it only
+// scans the possible set of proxy server.
+bool RulesContainsProxy(const net::ProxyConfig::ProxyRules& proxy_rules,
+                        const net::ProxyServer& target_proxy) {
+  switch (proxy_rules.type) {
+    case net::ProxyConfig::ProxyRules::Type::EMPTY:
+      return false;
+
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
+      return CheckProxyList(proxy_rules.single_proxies, target_proxy);
+
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
+      return CheckProxyList(proxy_rules.proxies_for_http, target_proxy) ||
+             CheckProxyList(proxy_rules.proxies_for_https, target_proxy);
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+bool IsValidCustomProxyConfig(const mojom::CustomProxyConfig& config) {
+  switch (config.rules.type) {
+    case net::ProxyConfig::ProxyRules::Type::EMPTY:
+      return true;
+
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
+      return !config.rules.single_proxies.IsEmpty();
+
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
+      return !config.rules.proxies_for_http.IsEmpty() ||
+             !config.rules.proxies_for_https.IsEmpty();
+  }
+
+  NOTREACHED();
+  return false;
 }
 
 // Merges headers from |in| to |out|. If the header already exists in |out| they
@@ -106,14 +140,21 @@
   if (!MayProxyURL(request->url()))
     return;
 
-  MergeRequestHeaders(headers, proxy_config_->pre_cache_headers);
+  // For other schemes, the headers can be added to the CONNECT request when
+  // establishing the secure tunnel instead, see OnBeforeHttp1TunnelRequest().
+  const bool scheme_is_http = request->url().SchemeIs(url::kHttpScheme);
+  if (scheme_is_http)
+    MergeRequestHeaders(headers, proxy_config_->pre_cache_headers);
 
   auto* url_loader = URLLoader::ForRequest(*request);
   if (url_loader) {
     if (url_loader->custom_proxy_use_alternate_proxy_list()) {
       should_use_alternate_proxy_list_cache_.Put(request->url().spec(), true);
     }
-    MergeRequestHeaders(headers, url_loader->custom_proxy_pre_cache_headers());
+    if (scheme_is_http) {
+      MergeRequestHeaders(headers,
+                          url_loader->custom_proxy_pre_cache_headers());
+    }
   }
 }
 
@@ -121,7 +162,13 @@
     net::URLRequest* request,
     const net::ProxyInfo& proxy_info,
     net::HttpRequestHeaders* headers) {
+  // For other schemes, the headers can be added to the CONNECT request when
+  // establishing the secure tunnel instead, see OnBeforeHttp1TunnelRequest().
+  if (!request->url().SchemeIs(url::kHttpScheme))
+    return;
+
   auto* url_loader = URLLoader::ForRequest(*request);
+
   if (IsInProxyConfig(proxy_info.proxy_server())) {
     MergeRequestHeaders(headers, proxy_config_->post_cache_headers);
 
@@ -150,7 +197,7 @@
     const std::string& method,
     const net::ProxyRetryInfoMap& proxy_retry_info,
     net::ProxyInfo* result) {
-  if (!EligibleForProxy(*result, url, method))
+  if (!EligibleForProxy(*result, method))
     return;
 
   net::ProxyInfo proxy_info;
@@ -167,7 +214,10 @@
 
 void NetworkServiceProxyDelegate::OnBeforeHttp1TunnelRequest(
     const net::ProxyServer& proxy_server,
-    net::HttpRequestHeaders* extra_headers) {}
+    net::HttpRequestHeaders* extra_headers) {
+  if (IsInProxyConfig(proxy_server))
+    MergeRequestHeaders(extra_headers, proxy_config_->connect_tunnel_headers);
+}
 
 net::Error NetworkServiceProxyDelegate::OnHttp1TunnelHeadersReceived(
     const net::ProxyServer& proxy_server,
@@ -177,8 +227,7 @@
 
 void NetworkServiceProxyDelegate::OnCustomProxyConfigUpdated(
     mojom::CustomProxyConfigPtr proxy_config) {
-  DCHECK(proxy_config->rules.empty() ||
-         !proxy_config->rules.proxies_for_http.IsEmpty());
+  DCHECK(IsValidCustomProxyConfig(*proxy_config));
   if (proxy_config_) {
     previous_proxy_configs_.push_front(std::move(proxy_config_));
     if (previous_proxy_configs_.size() > kMaxPreviousConfigs)
@@ -220,11 +269,11 @@
   if (!proxy_server.is_valid() || proxy_server.is_direct())
     return false;
 
-  if (CheckProxyList(proxy_config_->rules.proxies_for_http, proxy_server))
+  if (RulesContainsProxy(proxy_config_->rules, proxy_server))
     return true;
 
   for (const auto& config : previous_proxy_configs_) {
-    if (CheckProxyList(config->rules.proxies_for_http, proxy_server))
+    if (RulesContainsProxy(config->rules, proxy_server))
       return true;
   }
 
@@ -232,13 +281,10 @@
 }
 
 bool NetworkServiceProxyDelegate::MayProxyURL(const GURL& url) const {
-  return IsURLValidForProxy(url) && !proxy_config_->rules.empty();
+  return !proxy_config_->rules.empty();
 }
 
 bool NetworkServiceProxyDelegate::MayHaveProxiedURL(const GURL& url) const {
-  if (!IsURLValidForProxy(url))
-    return false;
-
   if (!proxy_config_->rules.empty())
     return true;
 
@@ -252,23 +298,26 @@
 
 bool NetworkServiceProxyDelegate::EligibleForProxy(
     const net::ProxyInfo& proxy_info,
-    const GURL& url,
     const std::string& method) const {
-  return proxy_info.is_direct() && proxy_info.proxy_list().size() == 1 &&
-         MayProxyURL(url) &&
-         (proxy_config_->allow_non_idempotent_methods ||
-          net::HttpUtil::IsMethodIdempotent(method));
+  bool has_existing_config =
+      !proxy_info.is_direct() || proxy_info.proxy_list().size() > 1u;
+  if (!proxy_config_->should_override_existing_config && has_existing_config)
+    return false;
+
+  if (!proxy_config_->allow_non_idempotent_methods &&
+      !net::HttpUtil::IsMethodIdempotent(method)) {
+    return false;
+  }
+
+  return true;
 }
 
 net::ProxyConfig::ProxyRules NetworkServiceProxyDelegate::GetProxyRulesForURL(
     const GURL& url) const {
-  net::ProxyConfig::ProxyRules rules = proxy_config_->rules;
   const auto iter = should_use_alternate_proxy_list_cache_.Peek(url.spec());
-  if (iter == should_use_alternate_proxy_list_cache_.end())
-    return rules;
-
-  rules.proxies_for_http = proxy_config_->alternate_proxy_list;
-  return rules;
+  return iter != should_use_alternate_proxy_list_cache_.end()
+             ? proxy_config_->alternate_rules
+             : proxy_config_->rules;
 }
 
 }  // namespace network
diff --git a/services/network/network_service_proxy_delegate.h b/services/network/network_service_proxy_delegate.h
index 66ae8a3e..a14abdc0 100644
--- a/services/network/network_service_proxy_delegate.h
+++ b/services/network/network_service_proxy_delegate.h
@@ -70,9 +70,9 @@
   // or a previous config.
   bool MayHaveProxiedURL(const GURL& url) const;
 
-  // Whether the |url| with current |proxy_info| is eligible to be proxied.
+  // Whether the HTTP |method| with current |proxy_info| is eligible to be
+  // proxied.
   bool EligibleForProxy(const net::ProxyInfo& proxy_info,
-                        const GURL& url,
                         const std::string& method) const;
 
   // Get the proxy rules that apply to |url|.
diff --git a/services/network/network_service_proxy_delegate_unittest.cc b/services/network/network_service_proxy_delegate_unittest.cc
index 81ba2459..404028f0 100644
--- a/services/network/network_service_proxy_delegate_unittest.cc
+++ b/services/network/network_service_proxy_delegate_unittest.cc
@@ -3,8 +3,12 @@
 // found in the LICENSE file.
 
 #include "services/network/network_service_proxy_delegate.h"
+
+#include <string>
+
 #include "base/test/scoped_task_environment.h"
 #include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace network {
@@ -14,9 +18,19 @@
 constexpr char kLocalhost[] = "http://localhost";
 constexpr char kHttpsUrl[] = "https://example.com";
 constexpr char kWebsocketUrl[] = "ws://example.com";
+constexpr char kBypassUrl[] = "http://bypass.com";
 
 }  // namespace
 
+MATCHER_P2(Contain,
+           expected_name,
+           expected_value,
+           std::string("headers ") + (negation ? "don't " : "") + "contain '" +
+               expected_name + ": " + expected_value + "'") {
+  std::string value;
+  return arg.GetHeader(expected_name, &value) && value == expected_value;
+}
+
 class NetworkServiceProxyDelegateTest : public testing::Test {
  public:
   NetworkServiceProxyDelegateTest() {}
@@ -70,23 +84,7 @@
   auto request = CreateRequest(GURL(kHttpUrl));
   delegate->OnBeforeStartTransaction(request.get(), &headers);
 
-  std::string value;
-  EXPECT_TRUE(headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "bar");
-}
-
-TEST_F(NetworkServiceProxyDelegateTest,
-       DoesNotAddHeadersBeforeCacheForLocalhost) {
-  auto config = mojom::CustomProxyConfig::New();
-  config->rules.ParseFromString("http=proxy");
-  config->pre_cache_headers.SetHeader("foo", "bar");
-  auto delegate = CreateDelegate(std::move(config));
-
-  net::HttpRequestHeaders headers;
-  auto request = CreateRequest(GURL(kLocalhost));
-  delegate->OnBeforeStartTransaction(request.get(), &headers);
-
-  EXPECT_TRUE(headers.IsEmpty());
+  EXPECT_THAT(headers, Contain("foo", "bar"));
 }
 
 TEST_F(NetworkServiceProxyDelegateTest,
@@ -115,6 +113,20 @@
   EXPECT_TRUE(headers.IsEmpty());
 }
 
+TEST_F(NetworkServiceProxyDelegateTest,
+       DoesNotAddHeadersBeforeCacheForWebSocket) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("http=proxy");
+  config->pre_cache_headers.SetHeader("foo", "bar");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::HttpRequestHeaders headers;
+  auto request = CreateRequest(GURL(kWebsocketUrl));
+  delegate->OnBeforeStartTransaction(request.get(), &headers);
+
+  EXPECT_TRUE(headers.IsEmpty());
+}
+
 TEST_F(NetworkServiceProxyDelegateTest, AddsHeadersAfterCache) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=proxy");
@@ -127,9 +139,7 @@
   info.UsePacString("PROXY proxy");
   delegate->OnBeforeSendHeaders(request.get(), info, &headers);
 
-  std::string value;
-  EXPECT_TRUE(headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "bar");
+  EXPECT_THAT(headers, Contain("foo", "bar"));
 }
 
 TEST_F(NetworkServiceProxyDelegateTest,
@@ -163,6 +173,40 @@
   EXPECT_TRUE(headers.IsEmpty());
 }
 
+TEST_F(NetworkServiceProxyDelegateTest, DoesNotAddHeadersAfterCacheForHttps) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("http=proxy");
+  config->post_cache_headers.SetHeader("foo", "bar");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::HttpRequestHeaders headers;
+  auto request = CreateRequest(GURL(kHttpsUrl));
+  net::ProxyInfo info;
+  info.UsePacString("PROXY proxy");
+  delegate->OnBeforeSendHeaders(request.get(), info, &headers);
+
+  EXPECT_TRUE(headers.IsEmpty());
+}
+
+TEST_F(NetworkServiceProxyDelegateTest, DoesNotAddHeadersIfProxyIsBypassed) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("http=proxy");
+  config->rules.bypass_rules.AddRuleFromString(GURL(kBypassUrl).host());
+  config->pre_cache_headers.SetHeader("pre", "cache");
+  config->post_cache_headers.SetHeader("post", "cache");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::HttpRequestHeaders headers;
+  auto request = CreateRequest(GURL(kBypassUrl));
+  delegate->OnBeforeStartTransaction(request.get(), &headers);
+
+  net::ProxyInfo info;
+  info.UseDirect();
+  delegate->OnBeforeSendHeaders(request.get(), info, &headers);
+
+  EXPECT_TRUE(headers.IsEmpty());
+}
+
 TEST_F(NetworkServiceProxyDelegateTest,
        RemovesPreCacheHeadersWhenProxyNotInConfig) {
   auto config = mojom::CustomProxyConfig::New();
@@ -194,9 +238,7 @@
   info.UseDirect();
   delegate->OnBeforeSendHeaders(request.get(), info, &headers);
 
-  std::string value;
-  EXPECT_TRUE(headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "value");
+  EXPECT_THAT(headers, Contain("foo", "value"));
 }
 
 TEST_F(NetworkServiceProxyDelegateTest, KeepsPreCacheHeadersWhenProxyInConfig) {
@@ -212,9 +254,7 @@
   info.UsePacString("PROXY proxy");
   delegate->OnBeforeSendHeaders(request.get(), info, &headers);
 
-  std::string value;
-  EXPECT_TRUE(headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "bar");
+  EXPECT_THAT(headers, Contain("foo", "bar"));
 }
 
 TEST_F(NetworkServiceProxyDelegateTest, KeepsHeadersWhenConfigUpdated) {
@@ -234,9 +274,7 @@
   info.UsePacString("PROXY proxy");
   delegate->OnBeforeSendHeaders(request.get(), info, &headers);
 
-  std::string value;
-  EXPECT_TRUE(headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "bar");
+  EXPECT_THAT(headers, Contain("foo", "bar"));
 }
 
 TEST_F(NetworkServiceProxyDelegateTest,
@@ -260,6 +298,23 @@
   EXPECT_TRUE(headers.IsEmpty());
 }
 
+TEST_F(NetworkServiceProxyDelegateTest, AddsHeadersToTunnelRequest) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("https://proxy");
+  config->pre_cache_headers.SetHeader("pre_cache", "foo");
+  config->post_cache_headers.SetHeader("post_cache", "bar");
+  config->connect_tunnel_headers.SetHeader("connect", "baz");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::HttpRequestHeaders headers;
+  auto proxy_server = net::ProxyServer::FromPacString("HTTPS proxy");
+  delegate->OnBeforeHttp1TunnelRequest(proxy_server, &headers);
+
+  EXPECT_FALSE(headers.HasHeader("pre_cache"));
+  EXPECT_FALSE(headers.HasHeader("post_cache"));
+  EXPECT_THAT(headers, Contain("connect", "baz"));
+}
+
 TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpProxy) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=foo");
@@ -296,6 +351,52 @@
             net::ProxyServer::FromPacString("QUIC foo"));
 }
 
+TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpsUrl) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("https://foo");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::ProxyInfo result;
+  result.UseDirect();
+  delegate->OnResolveProxy(GURL(kHttpsUrl), "GET", net::ProxyRetryInfoMap(),
+                           &result);
+
+  net::ProxyList expected_proxy_list;
+  expected_proxy_list.AddProxyServer(
+      net::ProxyServer::FromPacString("HTTPS foo"));
+  EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
+}
+
+TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessWebSocketUrl) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("https://foo");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::ProxyInfo result;
+  result.UseDirect();
+  delegate->OnResolveProxy(GURL(kWebsocketUrl), "GET", net::ProxyRetryInfoMap(),
+                           &result);
+
+  net::ProxyList expected_proxy_list;
+  expected_proxy_list.AddProxyServer(
+      net::ProxyServer::FromPacString("HTTPS foo"));
+  EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
+}
+
+TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyNoRuleForHttpsUrl) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("http=foo");
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::ProxyInfo result;
+  result.UseDirect();
+  delegate->OnResolveProxy(GURL(kHttpsUrl), "GET", net::ProxyRetryInfoMap(),
+                           &result);
+
+  EXPECT_TRUE(result.is_direct());
+  EXPECT_FALSE(result.alternative_proxy().is_valid());
+}
+
 TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyLocalhost) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=foo");
@@ -354,9 +455,12 @@
   EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
 }
 
-TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyWebsocketScheme) {
+TEST_F(NetworkServiceProxyDelegateTest,
+       OnResolveProxyBypassForWebSocketScheme) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=foo");
+  config->rules.bypass_rules.AddRuleFromString(GURL(kWebsocketUrl).scheme() +
+                                               "://*");
   auto delegate = CreateDelegate(std::move(config));
 
   net::ProxyInfo result;
@@ -371,6 +475,7 @@
 TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyDoesNotOverrideExisting) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=foo");
+  config->should_override_existing_config = false;
   auto delegate = CreateDelegate(std::move(config));
 
   net::ProxyInfo result;
@@ -385,6 +490,24 @@
   EXPECT_FALSE(result.alternative_proxy().is_valid());
 }
 
+TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyOverridesExisting) {
+  auto config = mojom::CustomProxyConfig::New();
+  config->rules.ParseFromString("http=foo");
+  config->should_override_existing_config = true;
+  auto delegate = CreateDelegate(std::move(config));
+
+  net::ProxyInfo result;
+  result.UsePacString("PROXY bar");
+  delegate->OnResolveProxy(GURL(kHttpUrl), "GET", net::ProxyRetryInfoMap(),
+                           &result);
+
+  net::ProxyList expected_proxy_list;
+  expected_proxy_list.AddProxyServer(
+      net::ProxyServer::FromPacString("PROXY foo"));
+  EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
+  EXPECT_FALSE(result.alternative_proxy().is_valid());
+}
+
 TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyDeprioritizesBadProxies) {
   auto config = mojom::CustomProxyConfig::New();
   config->rules.ParseFromString("http=foo,bar");
diff --git a/services/network/public/cpp/net_ipc_param_traits.h b/services/network/public/cpp/net_ipc_param_traits.h
index 8db5f62c..3cff701 100644
--- a/services/network/public/cpp/net_ipc_param_traits.h
+++ b/services/network/public/cpp/net_ipc_param_traits.h
@@ -278,6 +278,7 @@
   IPC_STRUCT_TRAITS_MEMBER(new_top_frame_origin)
   IPC_STRUCT_TRAITS_MEMBER(new_referrer)
   IPC_STRUCT_TRAITS_MEMBER(insecure_scheme_was_upgraded)
+  IPC_STRUCT_TRAITS_MEMBER(is_signed_exchange_fallback_redirect)
   IPC_STRUCT_TRAITS_MEMBER(new_referrer_policy)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 7e0994c..8ad776b 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -42,18 +42,25 @@
 [EnableIf=is_trial_comparison_cert_verifier_supported]
 import "services/network/public/mojom/trial_comparison_cert_verifier.mojom";
 
-// Config for setting a custom proxy config that will be used if a request
-// matches the proxy rules and would otherwise be direct. This config allows
-// headers to be set on requests to the proxies from the config before and/or
-// after the caching layer. Currently only supports proxying http requests.
+// The browser can provide a CustomProxyConfig to a CustomProxyConfigClient
+// running in the network service. The network service will use the given proxy
+// configuration if a request matches the proxy rules and all the other
+// criteria contained within it. This configuration allows the browser to
+// direct the network service to set headers on requests to the given proxies
+// before and/or after the caching layer.
 struct CustomProxyConfig {
-  // The custom proxy rules to use. Right now this is limited to proxies for
-  // http requests.
+  // The custom proxy rules to use. Note that ftp:// requests are not
+  // supported.
   ProxyRules rules;
 
-  // List of proxies that will be used if
+  // The proxy rules that will be used if
   // ResourceRequest::custom_proxy_use_alternate_proxy_list is set.
-  ProxyList alternate_proxy_list;
+  ProxyRules alternate_rules;
+
+  // Whether the custom proxy config should override other sources of proxy
+  // configuration. If false, the custom config is ignored if a proxy is set in
+  // the operating system, for example.
+  bool should_override_existing_config = false;
 
   // Whether the custom proxy config should apply to requests using
   // non-idempotent methods. Can be true if the proxy is known to handle this
@@ -67,17 +74,22 @@
   // |custom_proxy_pre_cache_headers| and |custom_proxy_post_cache_headers|
   // fields in ResourceRequest.
   //
-  // Headers that will be set before the cache for http requests. If the request
-  // does not use a custom proxy, these headers will be removed before sending
-  // to the network. If a request already has one of these headers set, it may
-  // be overwritten if a custom proxy is used, or removed if a custom proxy is
-  // not used.
+  // Headers that will be set before the cache for http:// requests. If the
+  // request does not use a custom proxy, these headers will be removed before
+  // sending to the network. If a request already has one of these headers set,
+  // it may be overwritten if a custom proxy is used, or removed if a custom
+  // proxy is not used.
   HttpRequestHeaders pre_cache_headers;
 
-  // Headers that will be set after the cache for requests that are issued
-  // through a custom proxy. Headers here will overwrite matching headers on the
-  // request if a custom proxy is used.
+  // Headers that will be set after the cache for http:// requests that are
+  // issued through a custom proxy. Headers here will overwrite matching
+  // headers on the request if a custom proxy is used.
   HttpRequestHeaders post_cache_headers;
+
+  // For tunneled requests (https://, ws://, wss://), these headers are added
+  // to the CONNECT request. Headers here will overwrite matching headers on
+  // the CONNECT request if a custom proxy is used.
+  HttpRequestHeaders connect_tunnel_headers;
 };
 
 // Client to update the custom proxy config.
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 049da805..39d6ca6 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -283,9 +283,10 @@
   // The profile ID of network conditions to throttle the network request.
   mojo_base.mojom.UnguessableToken? throttling_profile_id;
 
-  // Headers that will be added pre and post cache if the network context uses
-  // the custom proxy for this request. The custom proxy is used for requests
-  // that match the custom proxy config, and would otherwise be made direct.
+  // Headers that will be added pre and post cache for http:// requests if the
+  // network context uses the custom proxy for this request. The custom proxy
+  // is used for requests that match the custom proxy config, and would
+  // otherwise be made direct.
   HttpRequestHeaders custom_proxy_pre_cache_headers;
   HttpRequestHeaders custom_proxy_post_cache_headers;
 
@@ -340,8 +341,8 @@
   // For kRawFile
   mojo_base.mojom.File? file;
   // For kBlob
-  // TODO(Richard): Deprecate this once NetworkService is fully shipped.
-  string blob_uuid;
+  // TODO(richard.li): Deprecate this once NetworkService is fully shipped.
+  string? blob_uuid;
   // For kDataPipe
   network.mojom.DataPipeGetter? data_pipe_getter;
   // For kChunkedDataPipe
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index f222147..41e14d4 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -149,18 +149,6 @@
 #define SK_SUPPORT_LEGACY_DRAWLOOPER
 #endif
 
-// Skia is enabling this feature soon. Chrome probably does
-// not want it for M64
-#ifndef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
-#define SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
-#endif
-
-// Switching to explicit allocation causes some image diffs in
-// Chrome's layout tests. This define allows us to stage the change.
-#ifndef SK_OLD_STYLE_RESOURCE_ALLOCATION
-#define SK_OLD_STYLE_RESOURCE_ALLOCATION
-#endif
-
 // Chrome should only sort opLists within DDLs
 #ifndef SK_DISABLE_OPLIST_SORTING
 #define SK_DISABLE_OPLIST_SORTING
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc
index 82948ed..168168ae 100644
--- a/storage/browser/quota/quota_manager.cc
+++ b/storage/browser/quota/quota_manager.cc
@@ -20,6 +20,7 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -196,6 +197,8 @@
 }  // namespace
 
 // Helper to asynchronously gather usage and quota information.
+// This class is not thread-safe. Each instance can only be used on the sequence
+// where it was constructed. Instances of this class own and delete themselves.
 class QuotaManager::UsageAndQuotaInfoGatherer : public QuotaTask {
  public:
   UsageAndQuotaInfoGatherer(QuotaManager* manager,
@@ -216,6 +219,7 @@
 
  protected:
   void Run() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     // Start the async process of gathering the info we need.
     // Gather 4 pieces of info before computing an answer:
     // settings, device_storage_capacity, host_usage, and host_quota.
@@ -254,6 +258,7 @@
   }
 
   void Aborted() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     weak_factory_.InvalidateWeakPtrs();
     std::move(callback_).Run(
         blink::mojom::QuotaStatusCode::kErrorAbort, /*status*/
@@ -264,6 +269,7 @@
   }
 
   void Completed() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     weak_factory_.InvalidateWeakPtrs();
 
     // Constrain the desired |host_quota| to something that fits.
@@ -289,11 +295,13 @@
 
  private:
   QuotaManager* manager() const {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return static_cast<QuotaManager*>(observer());
   }
 
   void OnGotSettings(const base::Closure& barrier_closure,
                      const QuotaSettings& settings) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     settings_ = settings;
     barrier_closure.Run();
     if (type_ == StorageType::kTemporary && !is_unlimited_) {
@@ -308,6 +316,7 @@
   void OnGotCapacity(const base::Closure& barrier_closure,
                      int64_t total_space,
                      int64_t available_space) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     total_space_ = total_space;
     available_space_ = available_space;
     barrier_closure.Run();
@@ -316,6 +325,7 @@
   void OnGotHostUsage(const base::Closure& barrier_closure,
                       int64_t usage,
                       blink::mojom::UsageBreakdownPtr usage_breakdown) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     host_usage_ = usage;
     host_usage_breakdown_ = std::move(usage_breakdown);
     barrier_closure.Run();
@@ -324,6 +334,7 @@
   void SetDesiredHostQuota(const base::Closure& barrier_closure,
                            blink::mojom::QuotaStatusCode status,
                            int64_t quota) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     desired_host_quota_ = quota;
     barrier_closure.Run();
   }
@@ -342,6 +353,9 @@
   int64_t host_usage_ = 0;
   blink::mojom::UsageBreakdownPtr host_usage_breakdown_;
   QuotaSettings settings_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  // Weak pointers are used to support cancelling work.
   base::WeakPtrFactory<UsageAndQuotaInfoGatherer> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(UsageAndQuotaInfoGatherer);
 };
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index e6503d3..69f369d 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -2463,6 +2463,19 @@
       },
       {
         "args": [
+          "--xvfb",
+          "--jobs=1"
+        ],
+        "isolate_name": "telemetry_perf_unittests",
+        "name": "telemetry_perf_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "idempotent": false,
+          "shards": 12
+        }
+      },
+      {
+        "args": [
           "--jobs=1",
           "--extra-browser-args=--disable-gpu"
         ],
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 833472e..61ab4319 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -660,7 +660,7 @@
       {
         "args": [
           "-v",
-          "--browser=android-chromium",
+          "--browser=android-chrome",
           "--upload-results",
           "--run-ref-build",
           "--test-shard-map-filename=android-go-perf_map.json"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index e09af88..cc5ef61 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1203,6 +1203,12 @@
           '--jobs=1',
         ],
       },
+      'Linux Tests (dbg)(1)': {
+        'args': [
+          '--xvfb',
+          '--jobs=1',
+        ],
+      },
       'linux-xenial-rel': {
         'args': [
           '--xvfb',
@@ -1244,8 +1250,6 @@
       },
     },
     'remove_from': [
-      # crbug.com/934885
-      'Linux Tests (dbg)(1)',
       'Linux Tests (dbg)(1)(32)',
       # crbug.com/936540
       'Mac10.10 Tests',
diff --git a/third_party/blink/public/mojom/mediastream/media_devices.mojom b/third_party/blink/public/mojom/mediastream/media_devices.mojom
index 85e82eb..05030e8 100644
--- a/third_party/blink/public/mojom/mediastream/media_devices.mojom
+++ b/third_party/blink/public/mojom/mediastream/media_devices.mojom
@@ -6,6 +6,7 @@
 
 import "media/capture/mojom/video_capture_types.mojom";
 import "media/mojo/interfaces/audio_parameters.mojom";
+import "mojo/public/mojom/base/time.mojom";
 
 enum MediaDeviceType {
   MEDIA_AUDIO_INPUT,
@@ -37,6 +38,13 @@
   string device_id;
   string group_id;
   media.mojom.AudioParameters parameters;
+  // Values copied from the device parameters (Blink-use only).
+  // TODO(crbug.com/787252): remove the copies below in favour of |parameters|
+  // when it becomes visible in Blink.
+  bool is_valid;
+  int32 channels;
+  int32 sample_rate;
+  mojo_base.mojom.TimeDelta latency;
 };
 
 // This object lives in the browser and is responsible for processing device
@@ -44,19 +52,23 @@
 // notifications.
 interface MediaDevicesDispatcherHost {
   // Enumerates media devices and capabilities. The reply contains the
-  // |enumeration| and |video_input_device_capabilities| arrays. The
-  // |enumeration| array always has NUM_MEDIA_DEVICE_TYPES elements indexed by
-  // device type as defined in MediaDeviceType. Each element of |enumeration| is
-  // an array with as many elements as devices of the corresponding type exist
-  // in the system, or zero if the device types was not requested. Similarly,
-  // the number of elements in |video_input_device_capabilities| is equal to the
-  // number of video input devices in the system, or zero if not requested.
+  // |enumeration|, |video_input_device_capabilities|, and
+  // |audio_input_device_capabilities| arrays. The |enumeration| array always
+  // has NUM_MEDIA_DEVICE_TYPES elements indexed by device type as defined in
+  // MediaDeviceType. Each element of |enumeration| is an array with as many
+  // elements as devices of the corresponding type exist in the system, or zero
+  // if the device types was not requested. Similarly, the number of elements in
+  // |audio_input_device_capabilities| and |video_input_device_capabilities| is
+  // equal to respectively the number of video and audio input devices in the
+  // system, or zero if not requested.
   EnumerateDevices(bool request_audio_input,
                    bool request_video_input,
                    bool request_audio_output,
-                   bool request_video_input_capabilities)
+                   bool request_video_input_capabilities,
+                   bool request_audio_input_capabilities)
       => (array<array<MediaDeviceInfo>> enumeration,
-          array<VideoInputDeviceCapabilities> video_input_device_capabilities);
+          array<VideoInputDeviceCapabilities> video_input_device_capabilities,
+          array<AudioInputDeviceCapabilities> audio_input_device_capabilities);
 
   // Returns a list of video devices and their capabilities.
   // If there is a user-preferred device, it is the first in the result.
diff --git a/third_party/blink/public/platform/web_media_stream_source.h b/third_party/blink/public/platform/web_media_stream_source.h
index 9ebf4aa7..31ddba11 100644
--- a/third_party/blink/public/platform/web_media_stream_source.h
+++ b/third_party/blink/public/platform/web_media_stream_source.h
@@ -74,6 +74,9 @@
     WebVector<bool> auto_gain_control;
     WebVector<bool> noise_suppression;
     WebVector<int32_t> sample_size;
+    WebVector<int32_t> channel_count;
+    WebVector<int32_t> sample_rate;
+    WebVector<double> latency;
 
     WebMediaStreamTrack::FacingMode facing_mode =
         WebMediaStreamTrack::FacingMode::kNone;
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h
index fcc734f..55b4cea 100644
--- a/third_party/blink/public/platform/web_url_response.h
+++ b/third_party/blink/public/platform/web_url_response.h
@@ -177,8 +177,8 @@
   BLINK_PLATFORM_EXPORT WebString MimeType() const;
   BLINK_PLATFORM_EXPORT void SetMimeType(const WebString&);
 
-  BLINK_PLATFORM_EXPORT long long ExpectedContentLength() const;
-  BLINK_PLATFORM_EXPORT void SetExpectedContentLength(long long);
+  BLINK_PLATFORM_EXPORT int64_t ExpectedContentLength() const;
+  BLINK_PLATFORM_EXPORT void SetExpectedContentLength(int64_t);
 
   BLINK_PLATFORM_EXPORT void SetTextEncodingName(const WebString&);
 
@@ -192,7 +192,7 @@
   BLINK_PLATFORM_EXPORT void SetHttpStatusCode(int);
 
   BLINK_PLATFORM_EXPORT WebString HttpStatusText() const;
-  BLINK_PLATFORM_EXPORT void SetHTTPStatusText(const WebString&);
+  BLINK_PLATFORM_EXPORT void SetHttpStatusText(const WebString&);
 
   BLINK_PLATFORM_EXPORT WebString HttpHeaderField(const WebString& name) const;
   BLINK_PLATFORM_EXPORT void SetHTTPHeaderField(const WebString& name,
@@ -202,8 +202,8 @@
   BLINK_PLATFORM_EXPORT void ClearHTTPHeaderField(const WebString& name);
   BLINK_PLATFORM_EXPORT void VisitHTTPHeaderFields(WebHTTPHeaderVisitor*) const;
 
-  BLINK_PLATFORM_EXPORT long long AppCacheID() const;
-  BLINK_PLATFORM_EXPORT void SetAppCacheID(long long);
+  BLINK_PLATFORM_EXPORT int64_t AppCacheID() const;
+  BLINK_PLATFORM_EXPORT void SetAppCacheID(int64_t);
 
   BLINK_PLATFORM_EXPORT WebURL AppCacheManifestURL() const;
   BLINK_PLATFORM_EXPORT void SetAppCacheManifestURL(const WebURL&);
@@ -287,7 +287,7 @@
       net::HttpResponseInfo::ConnectionInfo);
 
   // Original size of the response before decompression.
-  BLINK_PLATFORM_EXPORT void SetEncodedDataLength(long long);
+  BLINK_PLATFORM_EXPORT void SetEncodedDataLength(int64_t);
 
   BLINK_PLATFORM_EXPORT void SetIsSignedExchangeInnerResponse(bool);
 
diff --git a/third_party/blink/public/web/web_shared_worker_client.h b/third_party/blink/public/web/web_shared_worker_client.h
index 1010a68..b0f2aaa 100644
--- a/third_party/blink/public/web/web_shared_worker_client.h
+++ b/third_party/blink/public/web/web_shared_worker_client.h
@@ -56,7 +56,7 @@
   virtual void WorkerScriptLoaded() = 0;
   virtual void WorkerScriptLoadFailed() = 0;
   virtual void WorkerScriptEvaluated(bool success) = 0;
-  virtual void SelectAppCacheID(long long) = 0;
+  virtual void SelectAppCacheID(int64_t) = 0;
 
   // Called on the main webkit thread in the worker process during
   // initialization.
diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni
index ee2e9a5..9eb65cc 100644
--- a/third_party/blink/renderer/bindings/bindings.gni
+++ b/third_party/blink/renderer/bindings/bindings.gni
@@ -19,7 +19,6 @@
                     "core/v8/custom/v8_custom_xpath_ns_resolver.h",
                     "core/v8/custom/v8_dev_tools_host_custom.cc",
                     "core/v8/custom/v8_element_custom.cc",
-                    "core/v8/custom/v8_error_event_custom.cc",
                     "core/v8/custom/v8_event_target_custom.cc",
                     "core/v8/custom/v8_html_all_collection_custom.cc",
                     "core/v8/custom/v8_html_plugin_element_custom.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_error_event_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_error_event_custom.cc
deleted file mode 100644
index ca801c7..0000000
--- a/third_party/blink/renderer/bindings/core/v8/custom/v8_error_event_custom.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_error_event.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-
-namespace blink {
-
-void V8ErrorEvent::ErrorAttributeGetterCustom(
-    const v8::FunctionCallbackInfo<v8::Value>& info) {
-  v8::Isolate* isolate = info.GetIsolate();
-  ErrorEvent* event = V8ErrorEvent::ToImpl(info.Holder());
-  ScriptState* script_state = ScriptState::From(isolate->GetCurrentContext());
-
-  ScriptValue error = event->error(script_state);
-  v8::Local<v8::Value> error_value =
-      error.IsEmpty() ? v8::Local<v8::Value>(v8::Null(isolate))
-                      : error.V8Value();
-  V8SetReturnValue(info, error_value);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 6836cf1..fa21f0f4 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -382,7 +382,7 @@
       }
 
       std::unique_ptr<TextResourceDecoder> decoder(
-          TextResourceDecoder::Create(TextResourceDecoderOptions(
+          std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
               TextResourceDecoderOptions::kPlainTextContent,
               WTF::TextEncoding(script_resource_->Encoding()))));
       decoder->CheckForBOM(maybe_bom, kMaximumLengthOfBOM);
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py
similarity index 82%
rename from third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
rename to third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py
index d21cd6c9..dc570b7 100755
--- a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_instances.py
@@ -22,10 +22,17 @@
         self._outputs = {
             'css_property_instances.h': self.generate_property_instances_header,
             'css_property_instances.cc':
-                self.generate_property_instances_implementation,
-            'css_property.h': self.generate_resolved_property_header,
-            'css_property.cc': self.generate_resolved_property_implementation,
+                self.generate_property_instances_implementation
         }
+        # These files are no longer generated. If the files are present from
+        # a previous build, we remove them. This avoids accidentally #including
+        # a stale generated header.
+        self._cleanup = set([
+            'css_property.cc',
+            'css_property.h',
+            'css_unresolved_property.cc',
+            'css_unresolved_property.h'
+        ])
 
         self._css_properties = css_properties.CSSProperties(json5_file_paths)
 
@@ -99,22 +106,5 @@
             'last_property_id': self._css_properties.last_property_id
         }
 
-    @template_expander.use_jinja(
-        'core/css/properties/templates/css_property.cc.tmpl')
-    def generate_resolved_property_implementation(self):
-        return {
-            'input_files': self._input_files,
-            'property_classes_by_property_id': self._property_classes_by_id,
-            'last_property_id': self._css_properties.last_property_id
-        }
-
-    @template_expander.use_jinja(
-        'core/css/properties/templates/css_property.h.tmpl')
-    def generate_resolved_property_header(self):
-        return {
-            'input_files': self._input_files,
-            'property_classes_by_property_id': self._property_classes_by_id,
-        }
-
 if __name__ == '__main__':
     json5_generator.Maker(CSSPropertyBaseWriter).main()
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
index 3899bd6..6f84b47 100755
--- a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
@@ -9,7 +9,7 @@
 import template_expander
 
 from collections import namedtuple
-from make_css_property_base import CSSPropertyBaseWriter
+from make_css_property_instances import CSSPropertyBaseWriter
 
 
 class PropertyMethod(namedtuple('PropertyMethod', 'name,return_type,parameters')):
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.cc.tmpl
deleted file mode 100644
index ccee755..0000000
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.cc.tmpl
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-{% from 'templates/macros.tmpl' import source_files_for_generated_file %}
-{{source_files_for_generated_file(template_file, input_files)}}
-// clang-format off
-
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
-
-namespace blink {
-
-const CSSProperty& GetCSSPropertyVariable() {
-  return To<CSSProperty>(GetCSSPropertyVariableInternal());
-}
-{% for property_class_data in property_classes_by_property_id %}
-const CSSProperty& Get{{property_class_data.property_id}}() {
-  return To<CSSProperty>(Get{{property_class_data.property_id}}Internal());
-}
-{% endfor %}
-
-const CSSProperty& CSSProperty::Get(CSSPropertyID id) {
-  DCHECK_NE(id, CSSPropertyInvalid);
-  DCHECK_LE(id, {{last_property_id}}); // last property id
-  return To<CSSProperty>(CSSUnresolvedProperty::GetNonAliasProperty(id));
-}
-
-}  // namespace blink
-
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
deleted file mode 100644
index 57ab241..0000000
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-{% from 'templates/macros.tmpl' import source_files_for_generated_file %}
-{{source_files_for_generated_file(template_file, input_files)}}
-// clang-format off
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_H_
-
-#include "third_party/blink/renderer/core/css/css_property_name.h"
-#include "third_party/blink/renderer/core/css/css_value.h"
-#include "third_party/blink/renderer/core/css/properties/css_unresolved_property.h"
-#include "third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h"
-#include "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h"
-#include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h"
-#include "third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h"
-#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
-#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
-#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
-#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
-#include "third_party/blink/renderer/platform/text/text_direction.h"
-#include "third_party/blink/renderer/platform/text/writing_mode.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ComputedStyle;
-class CSSParserContext;
-class CSSParserLocalContext;
-class CSSParserTokenRange;
-class LayoutObject;
-class Longhand;
-class Shorthand;
-class SVGComputedStyle;
-class StylePropertyShorthand;
-
-enum PhysicalBoxSide { kTopSide, kRightSide, kBottomSide, kLeftSide };
-
-class CSSProperty : public CSSUnresolvedProperty {
- public:
-  CORE_EXPORT static const CSSProperty& Get(CSSPropertyID);
-
-  // For backwards compatibility when passing around CSSUnresolvedProperty
-  // references. In case we need to call a function that hasn't been converted
-  // to using property classes yet.
-  virtual CSSPropertyID PropertyID() const {
-    NOTREACHED();
-    return CSSPropertyInvalid;
-  }
-  virtual CSSPropertyName GetCSSPropertyName() const {
-    return CSSPropertyName(PropertyID());
-  }
-  bool IDEquals(CSSPropertyID id) const { return PropertyID() == id; }
-  bool IsResolvedProperty() const override { return true; }
-  virtual bool IsInterpolable() const { return false; }
-  virtual bool IsInherited() const { return false; }
-  virtual bool IsCompositableProperty() const { return false; }
-  virtual bool IsRepeated() const { return false; }
-  virtual char RepetitionSeparator() const {
-    NOTREACHED();
-    return 0;
-  }
-  virtual bool IsDescriptor() const { return false; }
-  virtual bool SupportsPercentage() const { return false; }
-  virtual bool IsProperty() const { return true; }
-  virtual bool IsAffectedByAll() const { return IsEnabled() && IsProperty(); }
-  virtual bool IsLayoutDependentProperty() const { return false; }
-  virtual bool IsLayoutDependent(const ComputedStyle* style, LayoutObject* layout_object) const { return false; }
-  virtual bool IsValidForVisitedLink() const { return false; }
-
-  // Properties that do not override this method:
-  // CSSPropertyWebkitFontSizeDelta
-  // CSSPropertyWebkitTextEmphasis
-  // CSSPropertyFontDisplay
-  // CSSPropertySrc
-  // CSSPropertyUnicodeRange
-  // CSSPropertyPage
-  // CSSPropertySize
-  // CSSPropertyWebkitMarginCollapse
-  // CSSPropertyWebkitMask
-  // CSSPropertyWebkitMaskRepeatX
-  // CSSPropertyWebkitMaskRepeatY
-  // CSSPropertyWebkitPerspectiveOriginX
-  // CSSPropertyWebkitPerspectiveOriginY
-  // CSSPropertyWebkitTextStroke
-  // CSSPropertyWebkitTransformOriginX
-  // CSSPropertyWebkitTransformOriginY
-  // CSSPropertyWebkitTransformOriginZ
-  // CSSPropertyMaxZoom
-  // CSSPropertyMinZoom
-  // CSSPropertyOrientation
-  // CSSPropertyUserZoom
-  // CSSPropertyMarker
-  // CSSPropertyAll
-  // CSSPropertyVariable (Variables are retrieved via Get(AtomicString))
-  virtual const CSSValue* CSSValueFromComputedStyleInternal(const ComputedStyle&,
-                                                            const SVGComputedStyle&,
-                                                            const LayoutObject*,
-                                                            Node*,
-                                                            bool allow_visited_style) const { return nullptr; }
-  // FIXME: Resolve computed auto alignment in applyProperty/ComputedStyle and
-  // remove this non-const Node parameter.
-  CORE_EXPORT const CSSValue* CSSValueFromComputedStyle(const ComputedStyle&,
-                                                        const LayoutObject*,
-                                                        Node*,
-                                                        bool allow_visited_style) const;
-  CORE_EXPORT virtual std::unique_ptr<CrossThreadStyleValue>
-    CrossThreadStyleValueFromComputedStyle(const ComputedStyle& computed_style,
-                                            const LayoutObject* layout_object,
-                                            Node* node,
-                                            bool allow_visited_style) const {
-    const CSSValue* css_value = CSSValueFromComputedStyle(
-      computed_style, layout_object, node, allow_visited_style);
-    if (!css_value)
-      return std::make_unique<CrossThreadUnsupportedValue>("");
-    CSSStyleValue* style_value = StyleValueFactory::CssValueToStyleValue(
-      GetCSSPropertyName(), *css_value);
-    if (!style_value)
-      return std::make_unique<CrossThreadUnsupportedValue>("");
-    switch (style_value->GetType()) {
-      case CSSStyleValue::StyleValueType::kKeywordType:
-        return std::make_unique<CrossThreadKeywordValue>(
-            To<CSSKeywordValue>(style_value)->value().IsolatedCopy());
-      case CSSStyleValue::StyleValueType::kUnitType:
-        return std::make_unique<CrossThreadUnitValue>(
-            To<CSSUnitValue>(style_value)->value(),
-            To<CSSUnitValue>(style_value)->GetInternalUnit());
-      default:
-        // Make an isolated copy to ensure that it is safe to pass cross thread.
-        return std::make_unique<CrossThreadUnsupportedValue>(
-            css_value->CssText().IsolatedCopy());
-    }
-  }
-  virtual const CSSProperty& ResolveDirectionAwareProperty(
-      TextDirection,
-      WritingMode) const {
-    return *this;
-  }
-  virtual bool IsShorthand() const { return false; }
-  virtual bool IsLonghand() const { return false; }
-  static void FilterEnabledCSSPropertiesIntoVector(const CSSPropertyID*,
-                                                   size_t length,
-                                                   Vector<const CSSProperty*>&);
-
- protected:
-  constexpr CSSProperty() : CSSUnresolvedProperty() {}
-
-  static const StylePropertyShorthand& BorderDirections();
-  static const CSSProperty& ResolveAfterToPhysicalProperty(
-      TextDirection,
-      WritingMode,
-      const StylePropertyShorthand&);
-  static const CSSProperty& ResolveBeforeToPhysicalProperty(
-      TextDirection,
-      WritingMode,
-      const StylePropertyShorthand&);
-  static const CSSProperty& ResolveEndToPhysicalProperty(
-      TextDirection,
-      WritingMode,
-      const StylePropertyShorthand&);
-  static const CSSProperty& ResolveStartToPhysicalProperty(
-      TextDirection,
-      WritingMode,
-      const StylePropertyShorthand&);
-};
-
-template <>
-struct DowncastTraits<CSSProperty> {
-  static bool AllowFrom(const CSSUnresolvedProperty& unresolved) {
-    return unresolved.IsResolvedProperty();
-  }
-};
-
-CORE_EXPORT const CSSProperty& GetCSSPropertyVariable();
-{% for property_class_data in property_classes_by_property_id %}
-CORE_EXPORT const CSSProperty& Get{{property_class_data.property_id}}();
-{% endfor %}
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTY_H_
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl
index 9b501e104..32e13519 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl
@@ -31,7 +31,7 @@
 } // namespace
 
 {% for property_class_data in property_classes_by_property_id %}
-const CSSUnresolvedProperty& Get{{property_class_data.property_id}}Internal() {
+const CSSProperty& Get{{property_class_data.property_id}}() {
   return property_{{property_class_data.property_id.lower()}};
 }
 {% endfor %}
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.h.tmpl
index af8a707..d9a6c572 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_instances.h.tmpl
@@ -12,12 +12,13 @@
 namespace blink {
 
 class CSSUnresolvedProperty;
+class CSSProperty;
 
 const CSSUnresolvedProperty* GetAliasPropertyInternal(CSSPropertyID);
 const CSSUnresolvedProperty& GetNonAliasPropertyInternal(CSSPropertyID);
 
 {% for property_class_data in property_classes_by_property_id %}
-const CSSUnresolvedProperty& Get{{property_class_data.property_id}}Internal();
+CORE_EXPORT const CSSProperty& Get{{property_class_data.property_id}}();
 {% endfor %}
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/build/scripts/json5_generator.py b/third_party/blink/renderer/build/scripts/json5_generator.py
index 7adff45..5aa6b64 100644
--- a/third_party/blink/renderer/build/scripts/json5_generator.py
+++ b/third_party/blink/renderer/build/scripts/json5_generator.py
@@ -226,6 +226,10 @@
     def __init__(self, json5_files, output_dir):
         self._input_files = copy.copy(json5_files)
         self._outputs = {}  # file_name -> generator
+        # A set of filenames that were formerly generated, but aren't anymore.
+        # Files present in this set will be deleted to prevent erroneous
+        # inclusion of stale generated headers for incremental builds.
+        self._cleanup = set()
         self.gperf_path = None
         if json5_files:
             self.json5_file = Json5File.load_from_files(json5_files,
@@ -258,6 +262,12 @@
         for file_name, generator in self._outputs.items():
             self._write_file_if_changed(output_dir, generator(), file_name)
 
+    def cleanup_files(self, output_dir):
+        for file_name in self._cleanup:
+            path = os.path.join(output_dir, file_name)
+            if os.path.exists(path):
+                os.remove(path)
+
     def set_gperf_path(self, gperf_path):
         self.gperf_path = gperf_path
 
@@ -288,3 +298,4 @@
         writer = self._writer_class(args.files, args.output_dir)
         writer.set_gperf_path(args.gperf)
         writer.write_files(args.output_dir)
+        writer.cleanup_files(args.output_dir)
diff --git a/third_party/blink/renderer/build/scripts/json5_generator_unittest.py b/third_party/blink/renderer/build/scripts/json5_generator_unittest.py
index 888ce91..04f01b9 100644
--- a/third_party/blink/renderer/build/scripts/json5_generator_unittest.py
+++ b/third_party/blink/renderer/build/scripts/json5_generator_unittest.py
@@ -2,12 +2,29 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import contextlib
 import os
+import shutil
+import tempfile
 import unittest
 
-from json5_generator import Json5File
+from json5_generator import Json5File, Writer
 
 
+@contextlib.contextmanager
+def tmp_dir():
+    tmp = tempfile.mkdtemp(prefix='json5_generator_')
+    try:
+        yield tmp
+    finally:
+        shutil.rmtree(tmp)
+
+
+class CleanupWriter(Writer):
+    def __init__(self, output_dir, cleanup):
+        super(CleanupWriter, self).__init__([], output_dir)
+        self._cleanup = cleanup
+
 class Json5FileTest(unittest.TestCase):
     def path_of_test_file(self, file_name):
         return os.path.join(
@@ -36,5 +53,47 @@
         with self.assertRaises(Exception):
             Json5File.load_from_files([self.path_of_test_file('json5_generator_invalid_key.json5')])
 
+    def test_cleanup_multiple_files(self):
+        with tmp_dir() as tmp:
+            path1 = os.path.join(tmp, 'file1.h')
+            path2 = os.path.join(tmp, 'file2.h')
+
+            with open(path1, 'wb') as f:
+                f.write('File1')
+            with open(path2, 'wb') as f:
+                f.write('File2')
+
+            self.assertTrue(os.path.exists(path1))
+            self.assertTrue(os.path.exists(path2))
+            CleanupWriter(tmp, set(['file1.h', 'file2.h'])).cleanup_files(tmp)
+            self.assertFalse(os.path.exists(path1))
+            self.assertFalse(os.path.exists(path2))
+
+    def test_cleanup_partial_files(self):
+        with tmp_dir() as tmp:
+            path1 = os.path.join(tmp, 'file1.h')
+            path2 = os.path.join(tmp, 'file2.h')
+
+            with open(path1, 'wb') as f:
+                f.write('File1')
+            with open(path2, 'wb') as f:
+                f.write('File2')
+
+            self.assertTrue(os.path.exists(path1))
+            self.assertTrue(os.path.exists(path2))
+            CleanupWriter(tmp, set(['file2.h'])).cleanup_files(tmp)
+            self.assertTrue(os.path.exists(path1))
+            self.assertFalse(os.path.exists(path2))
+
+    def test_cleanup_nonexisting(self):
+        with tmp_dir() as tmp:
+            path1 = os.path.join(tmp, 'file1.h')
+            with open(path1, 'wb') as f:
+                f.write('File1')
+            self.assertTrue(os.path.exists(path1))
+            # Don't throw when trying to clean up something that doesn't exist.
+            CleanupWriter(tmp, set(['file1.h', 'file2.h'])).cleanup_files(tmp)
+            self.assertFalse(os.path.exists(path1))
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 723ed200..06b1c1d0 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -505,17 +505,13 @@
   ]
 }
 
-css_properties("make_core_generated_css_property_baseclass") {
-  script = "../build/scripts/core/css/properties/make_css_property_base.py"
+css_properties("make_core_generated_css_property_instances") {
+  script = "../build/scripts/core/css/properties/make_css_property_instances.py"
   other_inputs = [
-    "../build/scripts/core/css/properties/templates/css_property.cc.tmpl",
-    "../build/scripts/core/css/properties/templates/css_property.h.tmpl",
     "../build/scripts/core/css/properties/templates/css_property_instances.cc.tmpl",
     "../build/scripts/core/css/properties/templates/css_property_instances.h.tmpl",
   ]
   outputs = [
-    "$blink_core_output_dir/css/properties/css_property.cc",
-    "$blink_core_output_dir/css/properties/css_property.h",
     "$blink_core_output_dir/css/properties/css_property_instances.cc",
     "$blink_core_output_dir/css/properties/css_property_instances.h",
   ]
@@ -1587,8 +1583,8 @@
   ":make_core_generated_computed_style_initial_values",
   ":make_core_generated_computed_style_base",
   ":make_core_generated_css_longhand_property_classes",
-  ":make_core_generated_css_property_baseclass",
   ":make_core_generated_css_property_names",
+  ":make_core_generated_css_property_instances",
   ":make_core_generated_css_shorthand_property_classes",
   ":make_core_generated_css_value_id_mappings",
   ":make_core_generated_cssom_types",
diff --git a/third_party/blink/renderer/core/animation/path_interpolation_functions.cc b/third_party/blink/renderer/core/animation/path_interpolation_functions.cc
index 5912ad1..339a0d90 100644
--- a/third_party/blink/renderer/core/animation/path_interpolation_functions.cc
+++ b/third_party/blink/renderer/core/animation/path_interpolation_functions.cc
@@ -90,7 +90,8 @@
   if (style_path)
     return ConvertValue(style_path->ByteStream(), coordinateConversion);
 
-  std::unique_ptr<SVGPathByteStream> empty_path = SVGPathByteStream::Create();
+  std::unique_ptr<SVGPathByteStream> empty_path =
+      std::make_unique<SVGPathByteStream>();
   return ConvertValue(*empty_path, ForceAbsolute);
 }
 
@@ -197,7 +198,7 @@
     const InterpolableValue& interpolable_value,
     const NonInterpolableValue* non_interpolable_value) {
   std::unique_ptr<SVGPathByteStream> path_byte_stream =
-      SVGPathByteStream::Create();
+      std::make_unique<SVGPathByteStream>();
   InterpolatedSVGPathSource source(
       ToInterpolableList(
           *ToInterpolableList(interpolable_value).Get(kPathArgsIndex)),
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn
index ed1c405..a99c53d 100644
--- a/third_party/blink/renderer/core/css/BUILD.gn
+++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -418,6 +418,8 @@
     "properties/computed_style_utils.h",
     "properties/css_parsing_utils.cc",
     "properties/css_parsing_utils.h",
+    "properties/css_property.cc",
+    "properties/css_property.h",
     "properties/css_property_base_custom.cc",
     "properties/css_property_ref.cc",
     "properties/css_property_ref.h",
diff --git a/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.cc b/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.cc
index 7816f8e..2e44633 100644
--- a/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.cc
+++ b/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
+namespace cssvalue {
 
 String CSSGridAutoRepeatValue::CustomCSSText() const {
   StringBuilder result;
@@ -18,4 +19,5 @@
   return result.ToString();
 }
 
+}  // namespace cssvalue
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h b/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h
index d839c64..979b2b01 100644
--- a/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h
+++ b/third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
+namespace cssvalue {
 
 // CSSGridAutoRepeatValue stores the track sizes and line numbers when the
 // auto-repeat syntax is used
@@ -47,8 +48,10 @@
   const CSSValueID auto_repeat_id_;
 };
 
+}  // namespace cssvalue
+
 template <>
-struct DowncastTraits<CSSGridAutoRepeatValue> {
+struct DowncastTraits<cssvalue::CSSGridAutoRepeatValue> {
   static bool AllowFrom(const CSSValue& value) {
     return value.IsGridAutoRepeatValue();
   }
diff --git a/third_party/blink/renderer/core/css/css_grid_line_names_value.cc b/third_party/blink/renderer/core/css/css_grid_line_names_value.cc
index a0eea30..d19ab13 100644
--- a/third_party/blink/renderer/core/css/css_grid_line_names_value.cc
+++ b/third_party/blink/renderer/core/css/css_grid_line_names_value.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
+namespace cssvalue {
 
 String CSSGridLineNamesValue::CustomCSSText() const {
   return "[" + CSSValueList::CustomCSSText() + "]";
@@ -41,4 +42,5 @@
 CSSGridLineNamesValue::CSSGridLineNamesValue()
     : CSSValueList(kGridLineNamesClass, kSpaceSeparator) {}
 
+}  // namespace cssvalue
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_grid_line_names_value.h b/third_party/blink/renderer/core/css/css_grid_line_names_value.h
index cf5efe13..1ab203c 100644
--- a/third_party/blink/renderer/core/css/css_grid_line_names_value.h
+++ b/third_party/blink/renderer/core/css/css_grid_line_names_value.h
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
+namespace cssvalue {
 
 class CSSGridLineNamesValue : public CSSValueList {
  public:
@@ -51,8 +52,10 @@
   }
 };
 
+}  // namespace cssvalue
+
 template <>
-struct DowncastTraits<CSSGridLineNamesValue> {
+struct DowncastTraits<cssvalue::CSSGridLineNamesValue> {
   static bool AllowFrom(const CSSValue& value) {
     return value.IsGridLineNamesValue();
   }
diff --git a/third_party/blink/renderer/core/css/css_path_value.cc b/third_party/blink/renderer/core/css/css_path_value.cc
index 573f1e8..d392a5f 100644
--- a/third_party/blink/renderer/core/css/css_path_value.cc
+++ b/third_party/blink/renderer/core/css/css_path_value.cc
@@ -39,7 +39,7 @@
 
 CSSPathValue* CreatePathValue() {
   std::unique_ptr<SVGPathByteStream> path_byte_stream =
-      SVGPathByteStream::Create();
+      std::make_unique<SVGPathByteStream>();
   // Need to be registered as LSan ignored, as it will be reachable and
   // separately referred to by emptyPathValue() callers.
   LEAK_SANITIZER_IGNORE_OBJECT(path_byte_stream.get());
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
index dbb4a8f2..71691b43 100644
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -10,6 +10,8 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
 #include "third_party/blink/renderer/core/css/css_test_helpers.h"
+#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
 #include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
diff --git a/third_party/blink/renderer/core/css/media_query.cc b/third_party/blink/renderer/core/css/media_query.cc
index 2748773..28b9ba20 100644
--- a/third_party/blink/renderer/core/css/media_query.cc
+++ b/third_party/blink/renderer/core/css/media_query.cc
@@ -78,14 +78,6 @@
                                       ExpressionHeapVector());
 }
 
-std::unique_ptr<MediaQuery> MediaQuery::Create(
-    RestrictorType restrictor,
-    String media_type,
-    ExpressionHeapVector expressions) {
-  return std::make_unique<MediaQuery>(restrictor, std::move(media_type),
-                                      std::move(expressions));
-}
-
 MediaQuery::MediaQuery(RestrictorType restrictor,
                        String media_type,
                        ExpressionHeapVector expressions)
diff --git a/third_party/blink/renderer/core/css/media_query.h b/third_party/blink/renderer/core/css/media_query.h
index bfb4b97b..d3bf1839 100644
--- a/third_party/blink/renderer/core/css/media_query.h
+++ b/third_party/blink/renderer/core/css/media_query.h
@@ -47,9 +47,6 @@
  public:
   enum RestrictorType { kOnly, kNot, kNone };
 
-  static std::unique_ptr<MediaQuery> Create(RestrictorType,
-                                            String media_type,
-                                            ExpressionHeapVector);
   static std::unique_ptr<MediaQuery> CreateNotAll();
 
   MediaQuery(RestrictorType, String media_type, ExpressionHeapVector);
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index 891c778..fc35d1e 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -319,10 +319,10 @@
 
   std::unique_ptr<CSSParserSelector> selector;
   if (!type_selector.IsNull() && pseudo.IsNull()) {
-    selector = CSSParserSelector::Create(
+    selector = std::make_unique<CSSParserSelector>(
         QualifiedName(g_null_atom, type_selector, g_star_atom));
   } else {
-    selector = CSSParserSelector::Create();
+    selector = std::make_unique<CSSParserSelector>();
     if (!pseudo.IsNull()) {
       selector->SetMatch(CSSSelector::kPagePseudoClass);
       selector->UpdatePseudoPage(pseudo.LowerASCII());
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
index de16b87d..1322bf3 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
@@ -97,7 +97,8 @@
 
 void CSSParserSelector::PrependTagSelector(const QualifiedName& tag_q_name,
                                            bool is_implicit) {
-  std::unique_ptr<CSSParserSelector> second = CSSParserSelector::Create();
+  std::unique_ptr<CSSParserSelector> second =
+      std::make_unique<CSSParserSelector>();
   second->selector_ = std::move(selector_);
   second->tag_history_ = std::move(tag_history_);
   tag_history_ = std::move(second);
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.h b/third_party/blink/renderer/core/css/parser/css_parser_selector.h
index 6cc89694..341013c 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_selector.h
+++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.h
@@ -39,15 +39,6 @@
  public:
   CSSParserSelector();
   explicit CSSParserSelector(const QualifiedName&, bool is_implicit = false);
-
-  static std::unique_ptr<CSSParserSelector> Create() {
-    return std::make_unique<CSSParserSelector>();
-  }
-  static std::unique_ptr<CSSParserSelector> Create(const QualifiedName& name,
-                                                   bool is_implicit = false) {
-    return std::make_unique<CSSParserSelector>(name, is_implicit);
-  }
-
   ~CSSParserSelector();
 
   std::unique_ptr<CSSSelector> ReleaseSelector() {
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index 87110a4f..093d0639 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -340,7 +340,7 @@
     if (namespace_uri == DefaultNamespace())
       namespace_prefix = g_null_atom;
     context_->Count(WebFeature::kHasIDClassTagAttribute);
-    return CSSParserSelector::Create(
+    return std::make_unique<CSSParserSelector>(
         QualifiedName(namespace_prefix, element_name, namespace_uri));
   }
   // TODO(futhark@chromium.org): Prepending a type selector to the compound is
@@ -422,7 +422,8 @@
   DCHECK_EQ(range.Peek().GetType(), kHashToken);
   if (range.Peek().GetHashTokenType() != kHashTokenId)
     return nullptr;
-  std::unique_ptr<CSSParserSelector> selector = CSSParserSelector::Create();
+  std::unique_ptr<CSSParserSelector> selector =
+      std::make_unique<CSSParserSelector>();
   selector->SetMatch(CSSSelector::kId);
   AtomicString value = range.Consume().Value().ToAtomicString();
   selector->SetValue(value, IsQuirksModeBehavior(context_->MatchMode()));
@@ -437,7 +438,8 @@
   range.Consume();
   if (range.Peek().GetType() != kIdentToken)
     return nullptr;
-  std::unique_ptr<CSSParserSelector> selector = CSSParserSelector::Create();
+  std::unique_ptr<CSSParserSelector> selector =
+      std::make_unique<CSSParserSelector>();
   selector->SetMatch(CSSSelector::kClass);
   AtomicString value = range.Consume().Value().ToAtomicString();
   selector->SetValue(value, IsQuirksModeBehavior(context_->MatchMode()));
@@ -471,7 +473,8 @@
           ? QualifiedName(g_null_atom, attribute_name, g_null_atom)
           : QualifiedName(namespace_prefix, attribute_name, namespace_uri);
 
-  std::unique_ptr<CSSParserSelector> selector = CSSParserSelector::Create();
+  std::unique_ptr<CSSParserSelector> selector =
+      std::make_unique<CSSParserSelector>();
 
   if (block.AtEnd()) {
     selector->SetAttribute(qualified_name, CSSSelector::kCaseSensitive);
@@ -510,7 +513,8 @@
   if (token.GetType() != kIdentToken && token.GetType() != kFunctionToken)
     return nullptr;
 
-  std::unique_ptr<CSSParserSelector> selector = CSSParserSelector::Create();
+  std::unique_ptr<CSSParserSelector> selector =
+      std::make_unique<CSSParserSelector>();
   selector->SetMatch(colons == 1 ? CSSSelector::kPseudoClass
                                  : CSSSelector::kPseudoElement);
 
diff --git a/third_party/blink/renderer/core/css/parser/media_query_parser.cc b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
index 0dcf599e..fef2f9c 100644
--- a/third_party/blink/renderer/core/css/parser/media_query_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/media_query_parser.cc
@@ -300,7 +300,7 @@
 }
 
 std::unique_ptr<MediaQuery> MediaQueryData::TakeMediaQuery() {
-  std::unique_ptr<MediaQuery> media_query = MediaQuery::Create(
+  std::unique_ptr<MediaQuery> media_query = std::make_unique<MediaQuery>(
       restrictor_, std::move(media_type_), std::move(expressions_));
   Clear();
   return media_query;
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index ffe3ec7..2d1a4b7 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -2158,7 +2158,8 @@
   if (function_args.Peek().GetType() != kStringToken)
     return nullptr;
   StringView path_string = function_args.ConsumeIncludingWhitespace().Value();
-  std::unique_ptr<SVGPathByteStream> byte_stream = SVGPathByteStream::Create();
+  std::unique_ptr<SVGPathByteStream> byte_stream =
+      std::make_unique<SVGPathByteStream>();
   if (BuildByteStreamFromString(path_string, *byte_stream) !=
           SVGParseStatus::kNoError ||
       !function_args.AtEnd()) {
diff --git a/third_party/blink/renderer/core/css/properties/css_property.cc b/third_party/blink/renderer/core/css/properties/css_property.cc
new file mode 100644
index 0000000..905f389
--- /dev/null
+++ b/third_party/blink/renderer/core/css/properties/css_property.cc
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
+
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_style_value.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
+
+namespace blink {
+
+const CSSProperty& GetCSSPropertyVariable() {
+  return To<CSSProperty>(GetCSSPropertyVariableInternal());
+}
+
+const CSSProperty& CSSProperty::Get(CSSPropertyID id) {
+  DCHECK_NE(id, CSSPropertyInvalid);
+  DCHECK_LE(id, lastCSSProperty);  // last property id
+  return To<CSSProperty>(CSSUnresolvedProperty::GetNonAliasProperty(id));
+}
+
+std::unique_ptr<CrossThreadStyleValue>
+CSSProperty::CrossThreadStyleValueFromComputedStyle(
+    const ComputedStyle& computed_style,
+    const LayoutObject* layout_object,
+    Node* node,
+    bool allow_visited_style) const {
+  const CSSValue* css_value = CSSValueFromComputedStyle(
+      computed_style, layout_object, node, allow_visited_style);
+  if (!css_value)
+    return std::make_unique<CrossThreadUnsupportedValue>("");
+  CSSStyleValue* style_value =
+      StyleValueFactory::CssValueToStyleValue(GetCSSPropertyName(), *css_value);
+  if (!style_value)
+    return std::make_unique<CrossThreadUnsupportedValue>("");
+  switch (style_value->GetType()) {
+    case CSSStyleValue::StyleValueType::kKeywordType:
+      return std::make_unique<CrossThreadKeywordValue>(
+          To<CSSKeywordValue>(style_value)->value().IsolatedCopy());
+    case CSSStyleValue::StyleValueType::kUnitType:
+      return std::make_unique<CrossThreadUnitValue>(
+          To<CSSUnitValue>(style_value)->value(),
+          To<CSSUnitValue>(style_value)->GetInternalUnit());
+    default:
+      // Make an isolated copy to ensure that it is safe to pass cross thread.
+      return std::make_unique<CrossThreadUnsupportedValue>(
+          css_value->CssText().IsolatedCopy());
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/css_property.h b/third_party/blink/renderer/core/css/properties/css_property.h
new file mode 100644
index 0000000..f88fd19
--- /dev/null
+++ b/third_party/blink/renderer/core/css/properties/css_property.h
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PROPERTY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PROPERTY_H_
+
+#include <memory>
+#include "third_party/blink/renderer/core/css/css_property_name.h"
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css/properties/css_unresolved_property.h"
+#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
+#include "third_party/blink/renderer/platform/text/writing_mode.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ComputedStyle;
+class CrossThreadStyleValue;
+class LayoutObject;
+class StylePropertyShorthand;
+class SVGComputedStyle;
+
+enum PhysicalBoxSide { kTopSide, kRightSide, kBottomSide, kLeftSide };
+
+class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
+ public:
+  static const CSSProperty& Get(CSSPropertyID);
+
+  // For backwards compatibility when passing around CSSUnresolvedProperty
+  // references. In case we need to call a function that hasn't been converted
+  // to using property classes yet.
+  virtual CSSPropertyID PropertyID() const {
+    NOTREACHED();
+    return CSSPropertyInvalid;
+  }
+  virtual CSSPropertyName GetCSSPropertyName() const {
+    return CSSPropertyName(PropertyID());
+  }
+  bool IDEquals(CSSPropertyID id) const { return PropertyID() == id; }
+  bool IsResolvedProperty() const override { return true; }
+  virtual bool IsInterpolable() const { return false; }
+  virtual bool IsInherited() const { return false; }
+  virtual bool IsCompositableProperty() const { return false; }
+  virtual bool IsRepeated() const { return false; }
+  virtual char RepetitionSeparator() const {
+    NOTREACHED();
+    return 0;
+  }
+  virtual bool IsDescriptor() const { return false; }
+  virtual bool SupportsPercentage() const { return false; }
+  virtual bool IsProperty() const { return true; }
+  virtual bool IsAffectedByAll() const { return IsEnabled() && IsProperty(); }
+  virtual bool IsLayoutDependentProperty() const { return false; }
+  virtual bool IsLayoutDependent(const ComputedStyle* style,
+                                 LayoutObject* layout_object) const {
+    return false;
+  }
+  virtual bool IsValidForVisitedLink() const { return false; }
+
+  virtual const CSSValue* CSSValueFromComputedStyleInternal(
+      const ComputedStyle&,
+      const SVGComputedStyle&,
+      const LayoutObject*,
+      Node*,
+      bool allow_visited_style) const {
+    return nullptr;
+  }
+  // TODO: Resolve computed auto alignment in applyProperty/ComputedStyle and
+  // remove this non-const Node parameter.
+  const CSSValue* CSSValueFromComputedStyle(const ComputedStyle&,
+                                            const LayoutObject*,
+                                            Node*,
+                                            bool allow_visited_style) const;
+  virtual std::unique_ptr<CrossThreadStyleValue>
+  CrossThreadStyleValueFromComputedStyle(const ComputedStyle& computed_style,
+                                         const LayoutObject* layout_object,
+                                         Node* node,
+                                         bool allow_visited_style) const;
+  virtual const CSSProperty& ResolveDirectionAwareProperty(TextDirection,
+                                                           WritingMode) const {
+    return *this;
+  }
+  virtual bool IsShorthand() const { return false; }
+  virtual bool IsLonghand() const { return false; }
+  static void FilterEnabledCSSPropertiesIntoVector(const CSSPropertyID*,
+                                                   size_t length,
+                                                   Vector<const CSSProperty*>&);
+
+ protected:
+  constexpr CSSProperty() : CSSUnresolvedProperty() {}
+
+  static const StylePropertyShorthand& BorderDirections();
+  static const CSSProperty& ResolveAfterToPhysicalProperty(
+      TextDirection,
+      WritingMode,
+      const StylePropertyShorthand&);
+  static const CSSProperty& ResolveBeforeToPhysicalProperty(
+      TextDirection,
+      WritingMode,
+      const StylePropertyShorthand&);
+  static const CSSProperty& ResolveEndToPhysicalProperty(
+      TextDirection,
+      WritingMode,
+      const StylePropertyShorthand&);
+  static const CSSProperty& ResolveStartToPhysicalProperty(
+      TextDirection,
+      WritingMode,
+      const StylePropertyShorthand&);
+};
+
+template <>
+struct DowncastTraits<CSSProperty> {
+  static bool AllowFrom(const CSSUnresolvedProperty& unresolved) {
+    return unresolved.IsResolvedProperty();
+  }
+};
+
+CORE_EXPORT const CSSProperty& GetCSSPropertyVariable();
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PROPERTY_H_
diff --git a/third_party/blink/renderer/core/css/properties/longhand.h b/third_party/blink/renderer/core/css/properties/longhand.h
index 52a04325..f24246c 100644
--- a/third_party/blink/renderer/core/css/properties/longhand.h
+++ b/third_party/blink/renderer/core/css/properties/longhand.h
@@ -15,6 +15,9 @@
 
 class CSSValue;
 class StyleResolverState;
+class CSSParserContext;
+class CSSParserLocalContext;
+class CSSParserTokenRange;
 
 class Longhand : public CSSProperty {
  public:
diff --git a/third_party/blink/renderer/core/css/properties/shorthand.h b/third_party/blink/renderer/core/css/properties/shorthand.h
index 89d5580..f867152a 100644
--- a/third_party/blink/renderer/core/css/properties/shorthand.h
+++ b/third_party/blink/renderer/core/css/properties/shorthand.h
@@ -10,6 +10,9 @@
 
 namespace blink {
 
+class CSSParserContext;
+class CSSParserLocalContext;
+class CSSParserTokenRange;
 class CSSPropertyValue;
 
 class Shorthand : public CSSProperty {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index bd8eadd..a20b6a3d 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -133,7 +133,7 @@
   if (!Style()->HasAppearance())
     return;
 
-  cached_ua_style_ = CachedUAStyle::Create(Style());
+  cached_ua_style_ = std::make_unique<CachedUAStyle>(Style());
 }
 
 void StyleResolverState::LoadPendingResources() {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_stats.h b/third_party/blink/renderer/core/css/resolver/style_resolver_stats.h
index 240fe20..f4a1da0d 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_stats.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_stats.h
@@ -43,9 +43,7 @@
   USING_FAST_MALLOC(StyleResolverStats);
 
  public:
-  static std::unique_ptr<StyleResolverStats> Create() {
-    return base::WrapUnique(new StyleResolverStats);
-  }
+  StyleResolverStats() { Reset(); }
 
   void Reset();
   std::unique_ptr<TracedValue> ToTracedValue() const;
@@ -65,9 +63,6 @@
   unsigned base_styles_used;
   unsigned independent_inherited_styles_propagated;
   unsigned custom_properties_applied;
-
- private:
-  StyleResolverStats() { Reset(); }
 };
 
 #define INCREMENT_STYLE_STATS_COUNTER(styleEngine, counter, n) \
diff --git a/third_party/blink/renderer/core/css/style_change_reason.cc b/third_party/blink/renderer/core/css/style_change_reason.cc
index 0dc147bf..8df8ebc 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.cc
+++ b/third_party/blink/renderer/core/css/style_change_reason.cc
@@ -19,6 +19,7 @@
 const char kControl[] = "Control";
 const char kDeclarativeContent[] = "Extension declarativeContent.css";
 const char kDesignMode[] = "DesignMode";
+const char kDisplayLock[] = "DisplayLock";
 const char kFindInvisible[] = "FindInvisible";
 const char kFlatTreeChange[] = "FlatTreeChange";
 const char kFontSizeChange[] = "FontSizeChange";
diff --git a/third_party/blink/renderer/core/css/style_change_reason.h b/third_party/blink/renderer/core/css/style_change_reason.h
index a712e1c3..a7a3f38 100644
--- a/third_party/blink/renderer/core/css/style_change_reason.h
+++ b/third_party/blink/renderer/core/css/style_change_reason.h
@@ -22,6 +22,7 @@
 extern const char kControl[];
 extern const char kDeclarativeContent[];
 extern const char kDesignMode[];
+extern const char kDisplayLock[];
 extern const char kFrame[];
 extern const char kFlatTreeChange[];
 extern const char kFontSizeChange[];
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index fc15e32..ca0768b 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -1221,7 +1221,7 @@
     return;
   }
   if (!style_resolver_stats_)
-    style_resolver_stats_ = StyleResolverStats::Create();
+    style_resolver_stats_ = std::make_unique<StyleResolverStats>();
   else
     style_resolver_stats_->Reset();
 }
@@ -1781,16 +1781,10 @@
 
 void StyleEngine::UpdateStyleRecalcRoot(ContainerNode* ancestor,
                                         Node* dirty_node) {
-  if (!GetDocument().IsActive())
-    return;
-  if (in_layout_tree_rebuild_) {
-    // TODO(futhark@chromium.org): This happens because we call
-    // LazyReattachIfAttached() from HTMLSlotElement::DetachLayoutTree(). We
-    // probably want to get rid of LazyReattachIfAttached() altogether and call
-    // DetachLayoutTree on assigned nodes instead.
-    return;
+  if (GetDocument().IsActive()) {
+    DCHECK(!in_layout_tree_rebuild_);
+    style_recalc_root_.Update(ancestor, dirty_node);
   }
-  style_recalc_root_.Update(ancestor, dirty_node);
 }
 
 void StyleEngine::UpdateLayoutTreeRebuildRoot(ContainerNode* ancestor,
diff --git a/third_party/blink/renderer/core/dom/context_features_client_impl.h b/third_party/blink/renderer/core/dom/context_features_client_impl.h
index 58fe8c88..d8130f7 100644
--- a/third_party/blink/renderer/core/dom/context_features_client_impl.h
+++ b/third_party/blink/renderer/core/dom/context_features_client_impl.h
@@ -42,9 +42,7 @@
 class CORE_EXPORT ContextFeaturesClientImpl final
     : public ContextFeaturesClient {
  public:
-  static std::unique_ptr<ContextFeaturesClientImpl> Create() {
-    return base::WrapUnique(new ContextFeaturesClientImpl());
-  }
+  ContextFeaturesClientImpl() = default;
 
   bool IsEnabled(Document*,
                  ContextFeatures::FeatureType,
@@ -52,8 +50,6 @@
   void UrlDidChange(Document*) override;
 
  private:
-  ContextFeaturesClientImpl() = default;
-
   bool AskIfIsEnabled(Document*,
                       ContextFeatures::FeatureType,
                       bool default_value);
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 56ccfad..951ab6f 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2224,8 +2224,17 @@
   DCHECK(GetDocument().InStyleRecalc());
   DCHECK(!GetDocument().Lifecycle().InDetach());
 
-  if (StyleRecalcBlockedByDisplayLock())
+  if (StyleRecalcBlockedByDisplayLock()) {
+    // Mark this so that we will traverse back here when the style recalc is not
+    // blocked anymore (e.g. forced update, element getting unlocked).
+    if (change.RecalcChildren()) {
+      SetNeedsStyleRecalc(
+          change.RecalcDescendants() ? kSubtreeStyleChange : kLocalStyleChange,
+          StyleChangeReasonForTracing::Create(
+              style_change_reason::kDisplayLock));
+    }
     return;
+  }
 
   if (HasCustomStyleCallbacks())
     WillRecalcStyle(change);
diff --git a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.cc b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.cc
index f24a87f8..1c55e598 100644
--- a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.cc
+++ b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.cc
@@ -11,11 +11,6 @@
 
 namespace blink {
 
-std::unique_ptr<IncrementLoadEventDelayCount>
-IncrementLoadEventDelayCount::Create(Document& document) {
-  return base::WrapUnique(new IncrementLoadEventDelayCount(document));
-}
-
 IncrementLoadEventDelayCount::IncrementLoadEventDelayCount(Document& document)
     : document_(&document) {
   document.IncrementLoadEventDelayCount();
diff --git a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
index 4c853f6..e2a155d 100644
--- a/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
+++ b/third_party/blink/renderer/core/dom/increment_load_event_delay_count.h
@@ -22,7 +22,7 @@
   USING_FAST_MALLOC(IncrementLoadEventDelayCount);
 
  public:
-  static std::unique_ptr<IncrementLoadEventDelayCount> Create(Document&);
+  explicit IncrementLoadEventDelayCount(Document&);
   ~IncrementLoadEventDelayCount();
 
   // Decrements the loadEventDelayCount and checks load event synchronously,
@@ -36,7 +36,6 @@
   void DocumentChanged(Document& new_document);
 
  private:
-  IncrementLoadEventDelayCount(Document&);
   WeakPersistent<Document> document_;
   DISALLOW_COPY_AND_ASSIGN(IncrementLoadEventDelayCount);
 };
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index f7e1f8b..011c50d 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1201,7 +1201,8 @@
   if (change_type > existing_change_type)
     SetStyleChange(change_type);
 
-  if (existing_change_type == kNoStyleChange)
+  if (existing_change_type == kNoStyleChange &&
+      (!IsElementNode() || !ToElement(this)->StyleRecalcBlockedByDisplayLock()))
     MarkAncestorsWithChildNeedsStyleRecalc();
 
   if (IsElementNode() && HasRareData())
diff --git a/third_party/blink/renderer/core/dom/processing_instruction.cc b/third_party/blink/renderer/core/dom/processing_instruction.cc
index dcb70413..fce0804 100644
--- a/third_party/blink/renderer/core/dom/processing_instruction.cc
+++ b/third_party/blink/renderer/core/dom/processing_instruction.cc
@@ -196,7 +196,8 @@
   }
 
   std::unique_ptr<IncrementLoadEventDelayCount> delay =
-      is_xsl_ ? IncrementLoadEventDelayCount::Create(GetDocument()) : nullptr;
+      is_xsl_ ? std::make_unique<IncrementLoadEventDelayCount>(GetDocument())
+              : nullptr;
   if (is_xsl_) {
     sheet_ = XSLStyleSheet::Create(this, resource->Url(),
                                    resource->GetResponse().ResponseUrl());
diff --git a/third_party/blink/renderer/core/editing/dom_selection.cc b/third_party/blink/renderer/core/editing/dom_selection.cc
index dd45826e..e57a6a83 100644
--- a/third_party/blink/renderer/core/editing/dom_selection.cc
+++ b/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -669,7 +669,7 @@
   // TODO(tkent): "Merge the ranges if they intersect" was removed. We show a
   // warning message for a while, and continue to collect the usage data.
   // <https://code.google.com/p/chromium/issues/detail?id=353069>.
-  Deprecation::CountDeprecation(GetFrame(),
+  Deprecation::CountDeprecation(tree_scope_->GetDocument(),
                                 WebFeature::kSelectionAddRangeIntersect);
 }
 
diff --git a/third_party/blink/renderer/core/editing/keyboard_test.cc b/third_party/blink/renderer/core/editing/keyboard_test.cc
index a336c00..d216985 100644
--- a/third_party/blink/renderer/core/editing/keyboard_test.cc
+++ b/third_party/blink/renderer/core/editing/keyboard_test.cc
@@ -53,7 +53,7 @@
   const char* InterpretKeyEvent(const WebKeyboardEvent& web_keyboard_event) {
     KeyboardEvent* keyboard_event =
         KeyboardEvent::Create(web_keyboard_event, nullptr);
-    std::unique_ptr<Settings> settings = Settings::Create();
+    std::unique_ptr<Settings> settings = std::make_unique<Settings>();
     EditingBehavior behavior(settings->GetEditingBehaviorType());
     return behavior.InterpretKeyEvent(*keyboard_event);
   }
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index 17edfdb..f7dc533 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -505,11 +505,12 @@
   return nullptr;
 }
 
-HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>
+HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
 DocumentMarkerController::MarkersIntersectingRange(
     const EphemeralRangeInFlatTree& range,
     DocumentMarker::MarkerTypes types) {
-  HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>> node_marker_pairs;
+  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
+      node_marker_pairs;
   if (!PossiblyHasMarkers(types))
     return node_marker_pairs;
 
@@ -550,7 +551,7 @@
       const DocumentMarkerVector& markers_from_this_list =
           list->MarkersIntersectingRange(start_offset, end_offset);
       for (DocumentMarker* marker : markers_from_this_list)
-        node_marker_pairs.push_back(std::make_pair(&node, marker));
+        node_marker_pairs.push_back(std::make_pair(&ToText(node), marker));
     }
   }
 
@@ -786,14 +787,14 @@
     const EphemeralRangeInFlatTree& range) {
   // MarkersIntersectingRange() might be expensive. In practice, we hope we will
   // only check one node for composing range.
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
       node_marker_pairs = MarkersIntersectingRange(
           range, DocumentMarker::MarkerTypes::Suggestion());
   for (const auto& node_marker_pair : node_marker_pairs) {
     SuggestionMarker* suggestion_marker =
         ToSuggestionMarker(node_marker_pair.second);
     if (suggestion_marker->NeedsRemovalOnFinishComposing()) {
-      const Text& text = ToText(*node_marker_pair.first);
+      const Text& text = *node_marker_pair.first;
       DocumentMarkerList* const list =
           ListForType(markers_.at(&text), DocumentMarker::kSuggestion);
       // RemoveMarkerByTag() might be expensive. In practice, we have at most
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.h b/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
index 46bb497..b16ee42 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
@@ -48,7 +48,6 @@
 namespace blink {
 
 class DocumentMarkerList;
-class Node;
 class SuggestionMarkerProperties;
 
 class CORE_EXPORT DocumentMarkerController final
@@ -135,7 +134,7 @@
   // overlap with the specified range. Note that the range can be collapsed, in
   // in which case markers containing the position in their interiors are
   // returned.
-  HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>
+  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
   MarkersIntersectingRange(const EphemeralRangeInFlatTree&,
                            DocumentMarker::MarkerTypes);
   DocumentMarkerVector MarkersFor(
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
index 3a9e3f559..498146a 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
@@ -476,8 +476,8 @@
 
   // Query for spellcheck markers intersecting "3456". The text match marker
   // should not be returned, nor should the spelling marker touching the range.
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>& results =
-      MarkerController().MarkersIntersectingRange(
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
+      results = MarkerController().MarkersIntersectingRange(
           EphemeralRangeInFlatTree(PositionInFlatTree(text, 2),
                                    PositionInFlatTree(text, 6)),
           DocumentMarker::MarkerTypes::Misspelling());
@@ -498,8 +498,8 @@
       EphemeralRange(Position(text, 0), Position(text, 3)));
 
   // Query for spellcheck markers containing the position between "1" and "2"
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>& results =
-      MarkerController().MarkersIntersectingRange(
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
+      results = MarkerController().MarkersIntersectingRange(
           EphemeralRangeInFlatTree(PositionInFlatTree(text, 1),
                                    PositionInFlatTree(text, 1)),
           DocumentMarker::MarkerTypes::Misspelling());
@@ -537,8 +537,8 @@
                      Position(not_shadow_text, 10)),
       TextMatchMarker::MatchStatus::kInactive);
 
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>& results =
-      MarkerController().MarkersIntersectingRange(
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
+      results = MarkerController().MarkersIntersectingRange(
           EphemeralRangeInFlatTree(PositionInFlatTree(not_shadow_text, 9),
                                    PositionInFlatTree(shadow1_text, 1)),
           DocumentMarker::MarkerTypes::TextMatch());
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
index aec06ae68..be988931 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc
@@ -103,26 +103,26 @@
   STACK_ALLOCATED();
 
  public:
-  Persistent<Node> text_node;
+  Persistent<const Text> text_node;
   Color highlight_color;
   Vector<TextSuggestionInfo> suggestion_infos;
 };
 
 SuggestionInfosWithNodeAndHighlightColor ComputeSuggestionInfos(
-    const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+    const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
         node_suggestion_marker_pairs,
     size_t max_number_of_suggestions) {
   // We look at all suggestion markers touching or overlapping the touched
   // location to pull suggestions from. We preferentially draw suggestions from
   // shorter markers first (since we assume they're more specific to the tapped
   // location) until we hit our limit.
-  HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>
+  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
       node_suggestion_marker_pairs_sorted_by_length =
           node_suggestion_marker_pairs;
   std::sort(node_suggestion_marker_pairs_sorted_by_length.begin(),
             node_suggestion_marker_pairs_sorted_by_length.end(),
-            [](const std::pair<Node*, DocumentMarker*>& pair1,
-               const std::pair<Node*, DocumentMarker*>& pair2) {
+            [](const std::pair<const Text*, DocumentMarker*>& pair1,
+               const std::pair<const Text*, DocumentMarker*>& pair2) {
               const int length1 =
                   pair1.second->EndOffset() - pair1.second->StartOffset();
               const int length2 =
@@ -154,7 +154,7 @@
 
   Vector<TextSuggestionInfo>& suggestion_infos =
       suggestion_infos_with_node_and_highlight_color.suggestion_infos;
-  for (const std::pair<Node*, DocumentMarker*>& node_marker_pair :
+  for (const std::pair<const Text*, DocumentMarker*>& node_marker_pair :
        node_suggestion_marker_pairs_sorted_by_length) {
     if (node_marker_pair.first !=
         suggestion_infos_with_node_and_highlight_color.text_node)
@@ -260,7 +260,7 @@
   const EphemeralRangeInFlatTree& range_to_check =
       selection.IsRange() ? selection.ToNormalizedEphemeralRange()
                           : ComputeRangeSurroundingCaret(selection.Start());
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
       node_marker_pairs =
           GetFrame().GetDocument()->Markers().MarkersIntersectingRange(
               range_to_check, DocumentMarker::MarkerTypes::ActiveSuggestion());
@@ -268,7 +268,7 @@
   if (node_marker_pairs.IsEmpty())
     return;
 
-  Node* const marker_text_node = node_marker_pairs.front().first;
+  const Text* const marker_text_node = node_marker_pairs.front().first;
   const DocumentMarker* const marker = node_marker_pairs.front().second;
 
   const EphemeralRange& range_to_replace =
@@ -296,19 +296,19 @@
       selection.IsRange() ? selection.ToNormalizedEphemeralRange()
                           : ComputeRangeSurroundingCaret(selection.Start());
 
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
       node_marker_pairs =
           GetFrame().GetDocument()->Markers().MarkersIntersectingRange(
               range_to_check, DocumentMarker::MarkerTypes::Suggestion());
 
   const Text* marker_text_node = nullptr;
   SuggestionMarker* marker = nullptr;
-  for (const std::pair<Member<Node>, Member<DocumentMarker>>& node_marker_pair :
-       node_marker_pairs) {
+  for (const std::pair<Member<const Text>, Member<DocumentMarker>>&
+           node_marker_pair : node_marker_pairs) {
     SuggestionMarker* suggestion_marker =
         ToSuggestionMarker(node_marker_pair.second);
     if (suggestion_marker->Tag() == marker_tag) {
-      marker_text_node = ToText(node_marker_pair.first);
+      marker_text_node = node_marker_pair.first;
       marker = suggestion_marker;
       break;
     }
@@ -386,7 +386,7 @@
   // We can show a menu if the user tapped on either a spellcheck marker or a
   // suggestion marker. Suggestion markers take precedence (we don't even try
   // to draw both underlines, suggestion wins).
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
       node_suggestion_marker_pairs =
           GetFrame().GetDocument()->Markers().MarkersIntersectingRange(
               range_to_check, DocumentMarker::MarkerTypes::Suggestion());
@@ -396,7 +396,7 @@
   }
 
   // If we didn't find any suggestion markers, look for spell check markers.
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
       node_spelling_marker_pairs =
           GetFrame().GetDocument()->Markers().MarkersIntersectingRange(
               range_to_check, DocumentMarker::MarkerTypes::Misspelling());
@@ -409,8 +409,8 @@
 }
 
 void TextSuggestionController::ShowSpellCheckMenu(
-    const std::pair<Node*, DocumentMarker*>& node_spelling_marker_pair) {
-  Node* const marker_text_node = node_spelling_marker_pair.first;
+    const std::pair<const Text*, DocumentMarker*>& node_spelling_marker_pair) {
+  const Text* const marker_text_node = node_spelling_marker_pair.first;
   SpellCheckMarker* const marker =
       ToSpellCheckMarker(node_spelling_marker_pair.second);
 
@@ -448,7 +448,7 @@
 }
 
 void TextSuggestionController::ShowSuggestionMenu(
-    const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+    const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
         node_suggestion_marker_pairs,
     size_t max_number_of_suggestions) {
   DCHECK(!node_suggestion_marker_pairs.IsEmpty());
@@ -470,7 +470,7 @@
     span_union_end = std::max(span_union_end, suggestion_infos[i].span_end);
   }
 
-  const Node* text_node =
+  const Text* text_node =
       suggestion_infos_with_node_and_highlight_color.text_node;
   for (TextSuggestionInfo& info : suggestion_infos) {
     const EphemeralRange prefix_range(Position(text_node, span_union_start),
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
index bd6fe79..e1ab2e4 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_CONTROLLER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SUGGESTION_TEXT_SUGGESTION_CONTROLLER_H_
 
+#include <utility>
 #include "third_party/blink/public/mojom/input/input_host.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -63,9 +64,9 @@
       const Vector<TextSuggestionInfo>& text_suggestion_infos,
       const String& misspelled_word);
   void ShowSpellCheckMenu(
-      const std::pair<Node*, DocumentMarker*>& node_spelling_marker_pair);
+      const std::pair<const Text*, DocumentMarker*>& node_spelling_marker_pair);
   void ShowSuggestionMenu(
-      const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+      const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
           node_suggestion_marker_pairs,
       size_t max_number_of_suggestions);
   void ReplaceActiveSuggestionRange(const String&);
diff --git a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
index 1f1d3ac..a86bfbe 100644
--- a/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc
@@ -27,7 +27,7 @@
   }
 
   void ShowSuggestionMenu(
-      const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+      const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
           node_suggestion_marker_pairs,
       size_t max_number_of_suggestions) {
     GetDocument().GetFrame()->GetTextSuggestionController().ShowSuggestionMenu(
@@ -504,7 +504,7 @@
   const EphemeralRangeInFlatTree& range_to_check =
       ComputeRangeSurroundingCaret(selection.Start());
 
-  const HeapVector<std::pair<Member<Node>, Member<DocumentMarker>>>&
+  const HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>&
       node_suggestion_marker_pairs =
           GetFrame().GetDocument()->Markers().MarkersIntersectingRange(
               range_to_check, DocumentMarker::MarkerTypes::Suggestion());
diff --git a/third_party/blink/renderer/core/events/error_event.cc b/third_party/blink/renderer/core/events/error_event.cc
index 2a2bd50..655a599f 100644
--- a/third_party/blink/renderer/core/events/error_event.cc
+++ b/third_party/blink/renderer/core/events/error_event.cc
@@ -30,8 +30,6 @@
 
 #include "third_party/blink/renderer/core/events/error_event.h"
 
-#include <memory>
-
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/event_interface_names.h"
 #include "v8/include/v8.h"
@@ -111,8 +109,8 @@
   //    thus passing it around would cause leakage.
   // 2) Errors cannot be cloned (or serialized):
   if (World() != &script_state->World() || error_.IsEmpty())
-    return ScriptValue();
-  return ScriptValue(script_state, error_.NewLocal(script_state->GetIsolate()));
+    return ScriptValue::CreateNull(script_state);
+  return ScriptValue(script_state, error_.Get(script_state));
 }
 
 void ErrorEvent::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/events/error_event.h b/third_party/blink/renderer/core/events/error_event.h
index e3d1ed4..9f0b4c0 100644
--- a/third_party/blink/renderer/core/events/error_event.h
+++ b/third_party/blink/renderer/core/events/error_event.h
@@ -32,12 +32,13 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_ERROR_EVENT_H_
 
 #include <memory>
+
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/events/error_event_init.h"
 #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -107,8 +108,7 @@
   String unsanitized_message_;
   String sanitized_message_;
   std::unique_ptr<SourceLocation> location_;
-  TraceWrapperV8Reference<v8::Value> error_;
-
+  WorldSafeV8Reference<v8::Value> error_;
   scoped_refptr<DOMWrapperWorld> world_;
 };
 
diff --git a/third_party/blink/renderer/core/events/error_event.idl b/third_party/blink/renderer/core/events/error_event.idl
index 91f3e0d..4ceb73c 100644
--- a/third_party/blink/renderer/core/events/error_event.idl
+++ b/third_party/blink/renderer/core/events/error_event.idl
@@ -39,5 +39,5 @@
     readonly attribute DOMString filename;
     readonly attribute unsigned long lineno;
     readonly attribute unsigned long colno;
-    [Custom=Getter] readonly attribute any error;
+    [CallWith=ScriptState] readonly attribute any error;
 };
diff --git a/third_party/blink/renderer/core/exported/web_frame.cc b/third_party/blink/renderer/core/exported/web_frame.cc
index 5815a6c..a5a93dd 100644
--- a/third_party/blink/renderer/core/exported/web_frame.cc
+++ b/third_party/blink/renderer/core/exported/web_frame.cc
@@ -50,7 +50,7 @@
   auto* parent_web_local_frame = DynamicTo<WebLocalFrameImpl>(parent_);
   std::unique_ptr<IncrementLoadEventDelayCount> delay_parent_load =
       parent_web_local_frame
-          ? IncrementLoadEventDelayCount::Create(
+          ? std::make_unique<IncrementLoadEventDelayCount>(
                 *parent_web_local_frame->GetFrame()->GetDocument())
           : nullptr;
 
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index bff13003..b27e24a 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -298,7 +298,7 @@
       minimum_zoom_level_(ZoomFactorToZoomLevel(kMinTextSizeMultiplier)),
       maximum_zoom_level_(ZoomFactorToZoomLevel(kMaxTextSizeMultiplier)),
       does_composite_(does_composite),
-      fullscreen_controller_(FullscreenController::Create(this)) {
+      fullscreen_controller_(std::make_unique<FullscreenController>(this)) {
   if (!AsView().client) {
     DCHECK(!does_composite_);
   }
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index 881d668..802fc6a 100644
--- a/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -362,7 +362,7 @@
                                                          : content_type);
       } else {
         if (!string_decoder_) {
-          string_decoder_ = TextResourceDecoder::Create(
+          string_decoder_ = std::make_unique<TextResourceDecoder>(
               TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
         }
         string_builder_.reset(new StringBuilder);
@@ -428,7 +428,7 @@
     DCHECK(!decoder_);
     DCHECK(!consumer_);
     client_ = client;
-    decoder_ = TextResourceDecoder::Create(
+    decoder_ = std::make_unique<TextResourceDecoder>(
         TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
     consumer_ = consumer;
     consumer_->SetClient(this);
diff --git a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
index 69563a6..87db295 100644
--- a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
+++ b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -425,7 +425,7 @@
   // FIXME: consider supporting incremental decoding to improve the perf.
   StringBuilder builder;
   if (!decoder_) {
-    decoder_ = TextResourceDecoder::Create(TextResourceDecoderOptions(
+    decoder_ = std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent,
         encoding_.IsValid() ? encoding_ : UTF8Encoding()));
   }
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index a733176..9cabebe 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -725,18 +725,6 @@
   return g_empty_string;
 }
 
-// TODO(loonybear): Replace CountDeprecation(LocalFrame*) by CountDeprecation(
-// DocumentLoader*) eventually.
-void Deprecation::CountDeprecation(const LocalFrame* frame,
-                                   WebFeature feature) {
-  if (!frame)
-    return;
-  DocumentLoader* loader = frame->GetDocument()
-                               ? frame->GetDocument()->Loader()
-                               : frame->Loader().GetProvisionalDocumentLoader();
-  Deprecation::CountDeprecation(loader, feature);
-}
-
 void Deprecation::CountDeprecation(ExecutionContext* context,
                                    WebFeature feature) {
   if (!context)
@@ -771,23 +759,19 @@
   GenerateReport(frame, feature);
 }
 
-void Deprecation::CountDeprecationCrossOriginIframe(const LocalFrame* frame,
+void Deprecation::CountDeprecationCrossOriginIframe(const Document& document,
                                                     WebFeature feature) {
+  LocalFrame* frame = document.GetFrame();
+  if (!frame)
+    return;
+
   // Check to see if the frame can script into the top level document.
   const SecurityOrigin* security_origin =
       frame->GetSecurityContext()->GetSecurityOrigin();
   Frame& top = frame->Tree().Top();
   if (!security_origin->CanAccess(
           top.GetSecurityContext()->GetSecurityOrigin()))
-    CountDeprecation(frame, feature);
-}
-
-void Deprecation::CountDeprecationCrossOriginIframe(const Document& document,
-                                                    WebFeature feature) {
-  LocalFrame* frame = document.GetFrame();
-  if (!frame)
-    return;
-  CountDeprecationCrossOriginIframe(frame, feature);
+    CountDeprecation(document, feature);
 }
 
 void Deprecation::GenerateReport(const LocalFrame* frame, WebFeature feature) {
diff --git a/third_party/blink/renderer/core/frame/deprecation.h b/third_party/blink/renderer/core/frame/deprecation.h
index dbdc93be..db6f93b 100644
--- a/third_party/blink/renderer/core/frame/deprecation.h
+++ b/third_party/blink/renderer/core/frame/deprecation.h
@@ -39,14 +39,12 @@
   // Be considerate to developers' consoles: features should only send
   // deprecation warnings when we're actively interested in removing them from
   // the platform.
-  static void CountDeprecation(const LocalFrame*, WebFeature);
   static void CountDeprecation(ExecutionContext*, WebFeature);
   static void CountDeprecation(const Document&, WebFeature);
   static void CountDeprecation(DocumentLoader*, WebFeature);
 
   // Count only features if they're being used in an iframe which does not
   // have script access into the top level document.
-  static void CountDeprecationCrossOriginIframe(const LocalFrame*, WebFeature);
   static void CountDeprecationCrossOriginIframe(const Document&, WebFeature);
 
   static String DeprecationMessage(WebFeature);
diff --git a/third_party/blink/renderer/core/frame/frame_overlay.cc b/third_party/blink/renderer/core/frame/frame_overlay.cc
index d3f3eb1..191eba6 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay.cc
+++ b/third_party/blink/renderer/core/frame/frame_overlay.cc
@@ -47,12 +47,6 @@
 
 namespace blink {
 
-std::unique_ptr<FrameOverlay> FrameOverlay::Create(
-    LocalFrame* local_frame,
-    std::unique_ptr<FrameOverlay::Delegate> delegate) {
-  return base::WrapUnique(new FrameOverlay(local_frame, std::move(delegate)));
-}
-
 FrameOverlay::FrameOverlay(LocalFrame* local_frame,
                            std::unique_ptr<FrameOverlay::Delegate> delegate)
     : frame_(local_frame), delegate_(std::move(delegate)) {
diff --git a/third_party/blink/renderer/core/frame/frame_overlay.h b/third_party/blink/renderer/core/frame/frame_overlay.h
index df49684..0aa1522 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay.h
+++ b/third_party/blink/renderer/core/frame/frame_overlay.h
@@ -58,10 +58,7 @@
     virtual void Invalidate() {}
   };
 
-  static std::unique_ptr<FrameOverlay> Create(
-      LocalFrame*,
-      std::unique_ptr<FrameOverlay::Delegate>);
-
+  FrameOverlay(LocalFrame*, std::unique_ptr<FrameOverlay::Delegate>);
   ~FrameOverlay() override;
 
   void Update();
@@ -100,8 +97,6 @@
   String DebugName(const GraphicsLayer*) const override;
 
  private:
-  FrameOverlay(LocalFrame*, std::unique_ptr<FrameOverlay::Delegate>);
-
   Persistent<LocalFrame> frame_;
   std::unique_ptr<FrameOverlay::Delegate> delegate_;
   std::unique_ptr<GraphicsLayer> layer_;
diff --git a/third_party/blink/renderer/core/frame/frame_overlay_test.cc b/third_party/blink/renderer/core/frame/frame_overlay_test.cc
index d84e728e..27cf3ea 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_overlay_test.cc
@@ -64,7 +64,7 @@
   WebViewImpl* GetWebView() const { return helper_.GetWebView(); }
 
   std::unique_ptr<FrameOverlay> CreateSolidYellowOverlay() {
-    return FrameOverlay::Create(
+    return std::make_unique<FrameOverlay>(
         GetWebView()->MainFrameImpl()->GetFrame(),
         std::make_unique<SolidColorOverlay>(SK_ColorYELLOW));
   }
diff --git a/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
index cac7afe..671367d 100644
--- a/third_party/blink/renderer/core/frame/fullscreen_controller.cc
+++ b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -58,11 +58,6 @@
 
 }  // anonymous namespace
 
-std::unique_ptr<FullscreenController> FullscreenController::Create(
-    WebViewImpl* web_view_base) {
-  return base::WrapUnique(new FullscreenController(web_view_base));
-}
-
 FullscreenController::FullscreenController(WebViewImpl* web_view_base)
     : web_view_base_(web_view_base),
       pending_frames_(MakeGarbageCollected<PendingFullscreenSet>()) {}
diff --git a/third_party/blink/renderer/core/frame/fullscreen_controller.h b/third_party/blink/renderer/core/frame/fullscreen_controller.h
index 3bffc9a7..c2893be 100644
--- a/third_party/blink/renderer/core/frame/fullscreen_controller.h
+++ b/third_party/blink/renderer/core/frame/fullscreen_controller.h
@@ -54,7 +54,7 @@
   USING_FAST_MALLOC(FullscreenController);
 
  public:
-  static std::unique_ptr<FullscreenController> Create(WebViewImpl*);
+  explicit FullscreenController(WebViewImpl*);
 
   // Called by Fullscreen (via ChromeClient) to request entering or exiting
   // fullscreen.
@@ -75,9 +75,6 @@
 
   void UpdateSize();
 
- protected:
-  explicit FullscreenController(WebViewImpl*);
-
  private:
   void UpdatePageScaleConstraints(bool reset_constraints);
   void RestoreBackgroundColorOverride();
diff --git a/third_party/blink/renderer/core/frame/link_highlights.cc b/third_party/blink/renderer/core/frame/link_highlights.cc
index 41bfc96..1ec0276 100644
--- a/third_party/blink/renderer/core/frame/link_highlights.cc
+++ b/third_party/blink/renderer/core/frame/link_highlights.cc
@@ -66,7 +66,7 @@
     if (!highlight_color.Alpha())
       continue;
 
-    link_highlights_.push_back(LinkHighlightImpl::Create(node));
+    link_highlights_.push_back(std::make_unique<LinkHighlightImpl>(node));
     if (timeline_)
       timeline_->AnimationAttached(*link_highlights_.back());
     node->GetLayoutObject()->SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index f428654..4bb0f754 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -518,7 +518,7 @@
     return nullptr;
   if (!isSecureContext()) {
     Deprecation::CountDeprecation(
-        GetFrame(), WebFeature::kApplicationCacheAPIInsecureOrigin);
+        document(), WebFeature::kApplicationCacheAPIInsecureOrigin);
   }
   if (!application_cache_)
     application_cache_ = ApplicationCache::Create(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index b7b351f0..803d4e18 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1735,7 +1735,7 @@
   if (color == Color::kTransparent)
     return;
 
-  frame_color_overlay_ = FrameOverlay::Create(
+  frame_color_overlay_ = std::make_unique<FrameOverlay>(
       this, std::make_unique<FrameColorOverlay>(this, color));
 
   // Update compositing which will create graphics layers so the page color
diff --git a/third_party/blink/renderer/core/frame/settings.cc b/third_party/blink/renderer/core/frame/settings.cc
index af190e0..d91bf99 100644
--- a/third_party/blink/renderer/core/frame/settings.cc
+++ b/third_party/blink/renderer/core/frame/settings.cc
@@ -65,10 +65,6 @@
 Settings::Settings()
     : text_autosizing_enabled_(false) SETTINGS_INITIALIZER_LIST {}
 
-std::unique_ptr<Settings> Settings::Create() {
-  return base::WrapUnique(new Settings);
-}
-
 SETTINGS_SETTER_BODIES
 
 void Settings::SetDelegate(SettingsDelegate* delegate) {
diff --git a/third_party/blink/renderer/core/frame/settings.h b/third_party/blink/renderer/core/frame/settings.h
index 688bf8e..d1e46f6 100644
--- a/third_party/blink/renderer/core/frame/settings.h
+++ b/third_party/blink/renderer/core/frame/settings.h
@@ -59,7 +59,7 @@
   USING_FAST_MALLOC(Settings);
 
  public:
-  static std::unique_ptr<Settings> Create();
+  Settings();
 
   GenericFontFamilySettings& GetGenericFontFamilySettings() {
     return generic_font_family_settings_;
@@ -93,8 +93,6 @@
   void SetDelegate(SettingsDelegate*);
 
  private:
-  Settings();
-
   void Invalidate(SettingsDelegate::ChangeType);
 
   SettingsDelegate* delegate_;
diff --git a/third_party/blink/renderer/core/frame/use_counter_test.cc b/third_party/blink/renderer/core/frame/use_counter_test.cc
index de146ec..b0de1dd 100644
--- a/third_party/blink/renderer/core/frame/use_counter_test.cc
+++ b/third_party/blink/renderer/core/frame/use_counter_test.cc
@@ -397,26 +397,26 @@
   deprecation_.MuteForInspector();
   Deprecation::WarnOnDeprecatedProperties(GetFrame(), property);
   EXPECT_FALSE(deprecation_.IsSuppressed(property));
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  Deprecation::CountDeprecation(dummy_->GetDocument(), feature);
   EXPECT_FALSE(use_counter_.HasRecordedMeasurement(feature));
 
   deprecation_.MuteForInspector();
   Deprecation::WarnOnDeprecatedProperties(GetFrame(), property);
   EXPECT_FALSE(deprecation_.IsSuppressed(property));
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  Deprecation::CountDeprecation(dummy_->GetDocument(), feature);
   EXPECT_FALSE(use_counter_.HasRecordedMeasurement(feature));
 
   deprecation_.UnmuteForInspector();
   Deprecation::WarnOnDeprecatedProperties(GetFrame(), property);
   EXPECT_FALSE(deprecation_.IsSuppressed(property));
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  Deprecation::CountDeprecation(dummy_->GetDocument(), feature);
   EXPECT_FALSE(use_counter_.HasRecordedMeasurement(feature));
 
   deprecation_.UnmuteForInspector();
   Deprecation::WarnOnDeprecatedProperties(GetFrame(), property);
   // TODO: use the actually deprecated property to get a deprecation message.
   EXPECT_FALSE(deprecation_.IsSuppressed(property));
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  Deprecation::CountDeprecation(dummy_->GetDocument(), feature);
   EXPECT_TRUE(use_counter_.HasRecordedMeasurement(feature));
 }
 
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 5814a03..2e04330 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2379,7 +2379,7 @@
   } else if (metric == "connectionInfo") {
     feature = WebFeature::kChromeLoadTimesConnectionInfo;
   }
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  Deprecation::CountDeprecation(GetFrame()->GetDocument(), feature);
 }
 
 FrameScheduler* WebLocalFrameImpl::Scheduler() const {
diff --git a/third_party/blink/renderer/core/html/forms/form_controller.cc b/third_party/blink/renderer/core/html/forms/form_controller.cc
index f09b242c..0b77b86 100644
--- a/third_party/blink/renderer/core/html/forms/form_controller.cc
+++ b/third_party/blink/renderer/core/html/forms/form_controller.cc
@@ -197,7 +197,8 @@
   USING_FAST_MALLOC(SavedFormState);
 
  public:
-  static std::unique_ptr<SavedFormState> Create();
+  SavedFormState() : control_state_count_(0) {}
+
   static std::unique_ptr<SavedFormState> Deserialize(const Vector<String>&,
                                                      wtf_size_t& index);
   void SerializeTo(Vector<String>&) const;
@@ -211,8 +212,6 @@
   Vector<String> GetReferencedFilePaths() const;
 
  private:
-  SavedFormState() : control_state_count_(0) {}
-
   using FormElementStateMap = HashMap<FormElementKey,
                                       Deque<FormControlState>,
                                       FormElementKeyHash,
@@ -223,10 +222,6 @@
   DISALLOW_COPY_AND_ASSIGN(SavedFormState);
 };
 
-std::unique_ptr<SavedFormState> SavedFormState::Create() {
-  return base::WrapUnique(new SavedFormState);
-}
-
 static bool IsNotFormControlTypeCharacter(UChar ch) {
   return ch != '-' && (ch > 'z' || ch < 'a');
 }
@@ -459,7 +454,7 @@
     SavedFormStateMap::AddResult result =
         state_map->insert(key_generator->FormKey(*control), nullptr);
     if (result.is_new_entry)
-      result.stored_value->value = SavedFormState::Create();
+      result.stored_value->value = std::make_unique<SavedFormState>();
     result.stored_value->value->AppendControlState(
         control->GetName(), ControlType(*control),
         control->SaveFormControlState());
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index 0060f0b..7d6723a1 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -453,8 +454,14 @@
     }
   }
 
+  ContentSecurityPolicyDisposition content_security_policy_disposition =
+      ContentSecurityPolicy::ShouldBypassMainWorld(&GetDocument())
+          ? kDoNotCheckContentSecurityPolicy
+          : kCheckContentSecurityPolicy;
   child_frame->Loader().StartNavigation(
-      FrameLoadRequest(&GetDocument(), request), child_load_type);
+      FrameLoadRequest(&GetDocument(), request, AtomicString(),
+                       content_security_policy_disposition),
+      child_load_type);
 
   return true;
 }
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc
index 5ddd770..98cf565 100644
--- a/third_party/blink/renderer/core/html/html_link_element.cc
+++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -348,11 +348,12 @@
 void HTMLLinkElement::ScheduleEvent() {
   GetDocument()
       .GetTaskRunner(TaskType::kDOMManipulation)
-      ->PostTask(FROM_HERE,
-                 WTF::Bind(&HTMLLinkElement::DispatchPendingEvent,
-                           WrapPersistent(this),
-                           WTF::Passed(IncrementLoadEventDelayCount::Create(
-                               GetDocument()))));
+      ->PostTask(
+          FROM_HERE,
+          WTF::Bind(&HTMLLinkElement::DispatchPendingEvent,
+                    WrapPersistent(this),
+                    WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
+                        GetDocument()))));
 }
 
 void HTMLLinkElement::StartLoadingDynamicSheet() {
diff --git a/third_party/blink/renderer/core/html/html_style_element.cc b/third_party/blink/renderer/core/html/html_style_element.cc
index 1a3c59a6..26514ea 100644
--- a/third_party/blink/renderer/core/html/html_style_element.cc
+++ b/third_party/blink/renderer/core/html/html_style_element.cc
@@ -131,11 +131,12 @@
   loaded_sheet_ = is_load_event;
   GetDocument()
       .GetTaskRunner(TaskType::kDOMManipulation)
-      ->PostTask(FROM_HERE,
-                 WTF::Bind(&HTMLStyleElement::DispatchPendingEvent,
-                           WrapPersistent(this),
-                           WTF::Passed(IncrementLoadEventDelayCount::Create(
-                               GetDocument()))));
+      ->PostTask(
+          FROM_HERE,
+          WTF::Bind(&HTMLStyleElement::DispatchPendingEvent,
+                    WrapPersistent(this),
+                    WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
+                        GetDocument()))));
   fired_load_ = true;
 }
 
diff --git a/third_party/blink/renderer/core/html/parser/background_html_parser.cc b/third_party/blink/renderer/core/html/parser/background_html_parser.cc
index 43a805e7..7ebc9c1 100644
--- a/third_party/blink/renderer/core/html/parser/background_html_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/background_html_parser.cc
@@ -90,7 +90,7 @@
     std::unique_ptr<Configuration> config,
     scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner)
     : token_(std::make_unique<HTMLToken>()),
-      tokenizer_(HTMLTokenizer::Create(config->options)),
+      tokenizer_(std::make_unique<HTMLTokenizer>(config->options)),
       tree_builder_simulator_(config->options),
       options_(config->options),
       parser_(config->parser),
@@ -100,8 +100,7 @@
       pending_csp_meta_token_index_(
           HTMLDocumentParser::TokenizedChunk::kNoPendingToken),
       starting_script_(false),
-      weak_factory_(this) {
-}
+      weak_factory_(this) {}
 
 BackgroundHTMLParser::~BackgroundHTMLParser() = default;
 
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 39b39d81..a83b517 100644
--- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -132,7 +132,7 @@
                  ? std::make_unique<HTMLToken>()
                  : nullptr),
       tokenizer_(sync_policy == kForceSynchronousParsing
-                     ? HTMLTokenizer::Create(options_)
+                     ? std::make_unique<HTMLTokenizer>(options_)
                      : nullptr),
       loading_task_runner_(document.GetTaskRunner(TaskType::kNetworking)),
       parser_scheduler_(
@@ -776,7 +776,7 @@
     DCHECK(!InPumpSession());
     DCHECK(have_background_parser_ || WasCreatedByScript());
     token_ = std::make_unique<HTMLToken>();
-    tokenizer_ = HTMLTokenizer::Create(options_);
+    tokenizer_ = std::make_unique<HTMLTokenizer>(options_);
   }
 
   SegmentedString excluded_line_number_source(source);
@@ -836,7 +836,8 @@
       origin_trials::PriorityHintsEnabled(GetDocument());
 
   background_parser_->Init(
-      GetDocument()->Url(), CachedDocumentParameters::Create(GetDocument()),
+      GetDocument()->Url(),
+      std::make_unique<CachedDocumentParameters>(GetDocument()),
       MediaValuesCached::MediaValuesCachedData(*GetDocument()),
       priority_hints_origin_trial_enabled);
 }
@@ -985,7 +986,7 @@
     // We're finishing before receiving any data. Rather than booting up the
     // background parser just to spin it down, we finish parsing synchronously.
     token_ = std::make_unique<HTMLToken>();
-    tokenizer_ = HTMLTokenizer::Create(options_);
+    tokenizer_ = std::make_unique<HTMLTokenizer>(options_);
   }
 
   // We're not going to get any more data off the network, so we tell the input
@@ -1206,7 +1207,7 @@
     if (!have_background_parser_) {
       should_use_threading_ = false;
       token_ = std::make_unique<HTMLToken>();
-      tokenizer_ = HTMLTokenizer::Create(options_);
+      tokenizer_ = std::make_unique<HTMLTokenizer>(options_);
       DecodedDataDocumentParser::Flush();
       return;
     }
@@ -1269,9 +1270,9 @@
 
 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::CreatePreloadScanner(
     TokenPreloadScanner::ScannerType scanner_type) {
-  return HTMLPreloadScanner::Create(
+  return std::make_unique<HTMLPreloadScanner>(
       options_, GetDocument()->Url(),
-      CachedDocumentParameters::Create(GetDocument()),
+      std::make_unique<CachedDocumentParameters>(GetDocument()),
       MediaValuesCached::MediaValuesCachedData(*GetDocument()), scanner_type);
 }
 
diff --git a/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.cc b/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.cc
index be893b42..5b961d1 100644
--- a/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.cc
@@ -37,7 +37,7 @@
 using namespace html_names;
 
 HTMLMetaCharsetParser::HTMLMetaCharsetParser()
-    : tokenizer_(HTMLTokenizer::Create(HTMLParserOptions(nullptr))),
+    : tokenizer_(std::make_unique<HTMLTokenizer>(HTMLParserOptions(nullptr))),
       assumed_codec_(NewTextCodec(Latin1Encoding())),
       in_head_section_(true),
       done_checking_(false) {}
diff --git a/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h b/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
index 3394099..212be6b 100644
--- a/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
+++ b/third_party/blink/renderer/core/html/parser/html_meta_charset_parser.h
@@ -43,10 +43,7 @@
   USING_FAST_MALLOC(HTMLMetaCharsetParser);
 
  public:
-  static std::unique_ptr<HTMLMetaCharsetParser> Create() {
-    return base::WrapUnique(new HTMLMetaCharsetParser());
-  }
-
+  HTMLMetaCharsetParser();
   ~HTMLMetaCharsetParser();
 
   // Returns true if done checking, regardless whether an encoding is found.
@@ -55,8 +52,6 @@
   const WTF::TextEncoding& Encoding() { return encoding_; }
 
  private:
-  HTMLMetaCharsetParser();
-
   bool ProcessMeta();
 
   std::unique_ptr<HTMLTokenizer> tokenizer_;
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
index f6564ce..f89cf519 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -967,7 +967,7 @@
                media_values_cached_data,
                scanner_type,
                options.priority_hints_origin_trial_enabled),
-      tokenizer_(HTMLTokenizer::Create(options)) {}
+      tokenizer_(std::make_unique<HTMLTokenizer>(options)) {}
 
 HTMLPreloadScanner::~HTMLPreloadScanner() = default;
 
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
index 9dc91e13..e480e1d 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -60,13 +60,8 @@
   USING_FAST_MALLOC(CachedDocumentParameters);
 
  public:
-  static std::unique_ptr<CachedDocumentParameters> Create(Document* document) {
-    return base::WrapUnique(new CachedDocumentParameters(document));
-  }
-
-  static std::unique_ptr<CachedDocumentParameters> Create() {
-    return base::WrapUnique(new CachedDocumentParameters);
-  }
+  explicit CachedDocumentParameters(Document*);
+  CachedDocumentParameters() = default;
 
   bool do_html_preload_scanning;
   Length default_viewport_min_width;
@@ -75,10 +70,6 @@
   network::mojom::ReferrerPolicy referrer_policy;
   SubresourceIntegrity::IntegrityFeatures integrity_features;
   bool lazyload_policy_enforced;
-
- private:
-  explicit CachedDocumentParameters(Document*);
-  CachedDocumentParameters() = default;
 };
 
 class TokenPreloadScanner {
@@ -181,17 +172,11 @@
   USING_FAST_MALLOC(HTMLPreloadScanner);
 
  public:
-  static std::unique_ptr<HTMLPreloadScanner> Create(
-      const HTMLParserOptions& options,
-      const KURL& document_url,
-      std::unique_ptr<CachedDocumentParameters> document_parameters,
-      const MediaValuesCached::MediaValuesCachedData& media_values_cached_data,
-      const TokenPreloadScanner::ScannerType scanner_type) {
-    return base::WrapUnique(new HTMLPreloadScanner(
-        options, document_url, std::move(document_parameters),
-        media_values_cached_data, scanner_type));
-  }
-
+  HTMLPreloadScanner(const HTMLParserOptions&,
+                     const KURL& document_url,
+                     std::unique_ptr<CachedDocumentParameters>,
+                     const MediaValuesCached::MediaValuesCachedData&,
+                     const TokenPreloadScanner::ScannerType);
   ~HTMLPreloadScanner();
 
   void AppendToEnd(const SegmentedString&);
@@ -200,12 +185,6 @@
                             bool& has_csp_meta_tag);
 
  private:
-  HTMLPreloadScanner(const HTMLParserOptions&,
-                     const KURL& document_url,
-                     std::unique_ptr<CachedDocumentParameters>,
-                     const MediaValuesCached::MediaValuesCachedData&,
-                     const TokenPreloadScanner::ScannerType);
-
   TokenPreloadScanner scanner_;
   SegmentedString source_;
   HTMLToken token_;
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
index e0e30a7..98d1c8c2 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
@@ -17,7 +17,7 @@
 std::unique_ptr<CachedDocumentParameters> CachedDocumentParametersForFuzzing(
     FuzzedDataProvider& fuzzed_data) {
   std::unique_ptr<CachedDocumentParameters> document_parameters =
-      CachedDocumentParameters::Create();
+      std::make_unique<CachedDocumentParameters>();
   document_parameters->do_html_preload_scanning = fuzzed_data.ConsumeBool();
   // TODO(csharrison): How should this be fuzzed?
   document_parameters->default_viewport_min_width = Length();
@@ -66,9 +66,10 @@
 
   MockResourcePreloader preloader;
 
-  std::unique_ptr<HTMLPreloadScanner> scanner = HTMLPreloadScanner::Create(
-      options, document_url, std::move(document_parameters), media_data,
-      TokenPreloadScanner::ScannerType::kMainDocument);
+  std::unique_ptr<HTMLPreloadScanner> scanner =
+      std::make_unique<HTMLPreloadScanner>(
+          options, document_url, std::move(document_parameters), media_data,
+          TokenPreloadScanner::ScannerType::kMainDocument);
 
   TextResourceDecoderForFuzzing decoder(fuzzed_data);
   CString bytes = fuzzed_data.ConsumeRemainingBytes();
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
index e18252e..cfbc88c 100644
--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -257,8 +257,9 @@
     GetDocument().GetSettings()->SetDoHtmlPreloadScanning(preload_state ==
                                                           kPreloadEnabled);
     GetDocument().SetReferrerPolicy(document_referrer_policy);
-    scanner_ = HTMLPreloadScanner::Create(
-        options, document_url, CachedDocumentParameters::Create(&GetDocument()),
+    scanner_ = std::make_unique<HTMLPreloadScanner>(
+        options, document_url,
+        std::make_unique<CachedDocumentParameters>(&GetDocument()),
         CreateMediaValuesData(),
         TokenPreloadScanner::ScannerType::kMainDocument);
   }
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer.h b/third_party/blink/renderer/core/html/parser/html_tokenizer.h
index ca69ee9..0fb8655 100644
--- a/third_party/blink/renderer/core/html/parser/html_tokenizer.h
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer.h
@@ -43,10 +43,7 @@
   USING_FAST_MALLOC(HTMLTokenizer);
 
  public:
-  static std::unique_ptr<HTMLTokenizer> Create(
-      const HTMLParserOptions& options) {
-    return base::WrapUnique(new HTMLTokenizer(options));
-  }
+  explicit HTMLTokenizer(const HTMLParserOptions&);
   ~HTMLTokenizer();
 
   void Reset();
@@ -198,8 +195,6 @@
   }
 
  private:
-  explicit HTMLTokenizer(const HTMLParserOptions&);
-
   inline bool ProcessEntity(SegmentedString&);
 
   inline void ParseError();
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc b/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
index ec60e5a..e0fb488 100644
--- a/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer_fuzzer.cc
@@ -22,7 +22,8 @@
   HTMLParserOptions options;
   options.script_enabled = fuzzed_data_provider.ConsumeBool();
 
-  std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
+  std::unique_ptr<HTMLTokenizer> tokenizer =
+      std::make_unique<HTMLTokenizer>(options);
   SegmentedString input;
   HTMLToken token;
   while (fuzzed_data_provider.RemainingBytes() > 0) {
diff --git a/third_party/blink/renderer/core/html/parser/html_tokenizer_test.cc b/third_party/blink/renderer/core/html/parser/html_tokenizer_test.cc
index 7bf3559..1ba8fce6 100644
--- a/third_party/blink/renderer/core/html/parser/html_tokenizer_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tokenizer_test.cc
@@ -15,7 +15,8 @@
 // This is a regression test for crbug.com/619141
 TEST(HTMLTokenizerTest, ZeroOffsetAttributeNameRange) {
   HTMLParserOptions options;
-  std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
+  std::unique_ptr<HTMLTokenizer> tokenizer =
+      std::make_unique<HTMLTokenizer>(options);
   HTMLToken token;
 
   SegmentedString input("<script ");
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator_test.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator_test.cc
index 373bfd9..d3ebc641 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator_test.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder_simulator_test.cc
@@ -14,7 +14,8 @@
 TEST(HTMLTreeBuilderSimulatorTest, SelfClosingSVGFollowedByScript) {
   HTMLParserOptions options;
   HTMLTreeBuilderSimulator simulator(options);
-  std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
+  std::unique_ptr<HTMLTokenizer> tokenizer =
+      std::make_unique<HTMLTokenizer>(options);
   SegmentedString input("<svg/><script></script>");
   HTMLToken token;
   EXPECT_TRUE(tokenizer->NextToken(input, token));
@@ -40,7 +41,8 @@
 TEST(HTMLTreeBuilderSimulatorTest, SelfClosingMathFollowedByScript) {
   HTMLParserOptions options;
   HTMLTreeBuilderSimulator simulator(options);
-  std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
+  std::unique_ptr<HTMLTokenizer> tokenizer =
+      std::make_unique<HTMLTokenizer>(options);
   SegmentedString input("<math/><script></script>");
   HTMLToken token;
   EXPECT_TRUE(tokenizer->NextToken(input, token));
@@ -66,7 +68,8 @@
 TEST(HTMLTreeBuilderSimulatorTest, DetectInvalidScriptType) {
   HTMLParserOptions options;
   HTMLTreeBuilderSimulator simulator(options);
-  std::unique_ptr<HTMLTokenizer> tokenizer = HTMLTokenizer::Create(options);
+  std::unique_ptr<HTMLTokenizer> tokenizer =
+      std::make_unique<HTMLTokenizer>(options);
   SegmentedString input("<script type=\"text/html\"></script>");
   HTMLToken token;
   EXPECT_TRUE(tokenizer->NextToken(input, token));
diff --git a/third_party/blink/renderer/core/html/parser/html_view_source_parser.cc b/third_party/blink/renderer/core/html/parser/html_view_source_parser.cc
index 77212bc..e1c20a3f 100644
--- a/third_party/blink/renderer/core/html/parser/html_view_source_parser.cc
+++ b/third_party/blink/renderer/core/html/parser/html_view_source_parser.cc
@@ -37,7 +37,8 @@
 HTMLViewSourceParser::HTMLViewSourceParser(HTMLViewSourceDocument& document,
                                            const String& mime_type)
     : DecodedDataDocumentParser(document),
-      tokenizer_(HTMLTokenizer::Create(HTMLParserOptions(&document))) {
+      tokenizer_(
+          std::make_unique<HTMLTokenizer>(HTMLParserOptions(&document))) {
   if (mime_type != "text/html" && !DOMImplementation::IsXMLMIMEType(mime_type))
     tokenizer_->SetState(HTMLTokenizer::kPLAINTEXTState);
 }
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
index b9a380e..fe832c57 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
@@ -356,7 +356,7 @@
   }
 
   if (!charset_parser_)
-    charset_parser_ = HTMLMetaCharsetParser::Create();
+    charset_parser_ = std::make_unique<HTMLMetaCharsetParser>();
 
   if (!charset_parser_->CheckForMetaCharset(data, length))
     return;
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder.h b/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
index 51e12bb..a6be624 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
@@ -58,11 +58,7 @@
     kEncodingFromParentFrame
   };
 
-  static std::unique_ptr<TextResourceDecoder> Create(
-      const TextResourceDecoderOptions& options) {
-    return base::WrapUnique(new TextResourceDecoder(options));
-  }
-
+  explicit TextResourceDecoder(const TextResourceDecoderOptions&);
   ~TextResourceDecoder();
 
   void SetEncoding(const WTF::TextEncoding&, EncodingSource);
@@ -78,9 +74,6 @@
   bool SawError() const { return saw_error_; }
   wtf_size_t CheckForBOM(const char*, wtf_size_t);
 
- protected:
-  TextResourceDecoder(const TextResourceDecoderOptions&);
-
  private:
   static const WTF::TextEncoding& DefaultEncoding(
       TextResourceDecoderOptions::ContentType,
diff --git a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
index ae1912f..4a12a42 100644
--- a/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
+++ b/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
@@ -10,7 +10,7 @@
 
 TEST(TextResourceDecoderTest, BasicUTF16) {
   std::unique_ptr<TextResourceDecoder> decoder =
-      TextResourceDecoder::Create(TextResourceDecoderOptions(
+      std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
           TextResourceDecoderOptions::kPlainTextContent));
   WTF::String decoded;
 
@@ -21,7 +21,7 @@
   decoded = decoded + decoder->Flush();
   EXPECT_EQ("foo", decoded);
 
-  decoder = TextResourceDecoder::Create(TextResourceDecoderOptions(
+  decoder = std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
       TextResourceDecoderOptions::kPlainTextContent));
   const unsigned char kFooBE[] = {0xfe, 0xff, 0x00, 0x66,
                                   0x00, 0x6f, 0x00, 0x6f};
@@ -33,7 +33,7 @@
 
 TEST(TextResourceDecoderTest, UTF16Pieces) {
   std::unique_ptr<TextResourceDecoder> decoder =
-      TextResourceDecoder::Create(TextResourceDecoderOptions(
+      std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
           TextResourceDecoderOptions::kPlainTextContent));
 
   WTF::String decoded;
@@ -45,10 +45,11 @@
 }
 
 TEST(TextResourceDecoderTest, ContentSniffingStopsAfterSuccess) {
-  std::unique_ptr<TextResourceDecoder> decoder = TextResourceDecoder::Create(
-      TextResourceDecoderOptions::CreateWithAutoDetection(
-          TextResourceDecoderOptions::kPlainTextContent, WTF::UTF8Encoding(),
-          WTF::UTF8Encoding(), KURL("")));
+  std::unique_ptr<TextResourceDecoder> decoder =
+      std::make_unique<TextResourceDecoder>(
+          TextResourceDecoderOptions::CreateWithAutoDetection(
+              TextResourceDecoderOptions::kPlainTextContent,
+              WTF::UTF8Encoding(), WTF::UTF8Encoding(), KURL("")));
 
   std::string utf8_bytes =
       "tnegirjji gosa gii beare s\xC3\xA1htt\xC3\xA1 \xC4\x8D\xC3"
diff --git a/third_party/blink/renderer/core/html/parser/xss_auditor.cc b/third_party/blink/renderer/core/html/parser/xss_auditor.cc
index 48aa1e2..521a192 100644
--- a/third_party/blink/renderer/core/html/parser/xss_auditor.cc
+++ b/third_party/blink/renderer/core/html/parser/xss_auditor.cc
@@ -511,8 +511,8 @@
   if (did_block_script) {
     bool did_block_entire_page = (xss_protection_ == kBlockReflectedXSS);
     std::unique_ptr<XSSInfo> xss_info =
-        XSSInfo::Create(document_url_, did_block_entire_page,
-                        did_send_valid_xss_protection_header_);
+        std::make_unique<XSSInfo>(document_url_, did_block_entire_page,
+                                  did_send_valid_xss_protection_header_);
     return xss_info;
   }
   return nullptr;
diff --git a/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h b/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h
index 4379dbb..5446448e 100644
--- a/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h
+++ b/third_party/blink/renderer/core/html/parser/xss_auditor_delegate.h
@@ -45,12 +45,12 @@
   USING_FAST_MALLOC(XSSInfo);
 
  public:
-  static std::unique_ptr<XSSInfo> Create(const String& original_url,
-                                         bool did_block_entire_page,
-                                         bool did_send_xss_protection_header) {
-    return base::WrapUnique(new XSSInfo(original_url, did_block_entire_page,
-                                        did_send_xss_protection_header));
-  }
+  XSSInfo(const String& original_url,
+          bool did_block_entire_page,
+          bool did_send_xss_protection_header)
+      : original_url_(original_url.IsolatedCopy()),
+        did_block_entire_page_(did_block_entire_page),
+        did_send_xss_protection_header_(did_send_xss_protection_header) {}
 
   String BuildConsoleError() const;
 
@@ -59,14 +59,6 @@
   bool did_send_xss_protection_header_;
   TextPosition text_position_;
 
- private:
-  XSSInfo(const String& original_url,
-          bool did_block_entire_page,
-          bool did_send_xss_protection_header)
-      : original_url_(original_url.IsolatedCopy()),
-        did_block_entire_page_(did_block_entire_page),
-        did_send_xss_protection_header_(did_send_xss_protection_header) {}
-
   DISALLOW_COPY_AND_ASSIGN(XSSInfo);
 };
 
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
index af2c7e5a..549899e5 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
@@ -85,7 +85,7 @@
 VTTParser::VTTParser(VTTParserClient* client, Document& document)
     : document_(&document),
       state_(kInitial),
-      decoder_(TextResourceDecoder::Create(TextResourceDecoderOptions(
+      decoder_(std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
           TextResourceDecoderOptions::kPlainTextContent,
           UTF8Encoding()))),
       current_start_time_(0),
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index 6c8be269..66e6653 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -498,7 +498,8 @@
         IntRect visible_rect = page->GetVisualViewport().VisibleContentRect();
         if (!visible_rect.Contains(cursor_rect)) {
           Deprecation::CountDeprecation(
-              frame_, WebFeature::kCustomCursorIntersectsViewport);
+              &node->GetDocument(),
+              WebFeature::kCustomCursorIntersectsViewport);
           continue;
         }
       }
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index cc7a1969..fe5add9 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -547,7 +547,7 @@
     return;
 
   if (!frame_overlay_) {
-    frame_overlay_ = FrameOverlay::Create(
+    frame_overlay_ = std::make_unique<FrameOverlay>(
         GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
   }
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
index 39c6aac..67ab4289f 100644
--- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -209,26 +209,26 @@
     const String& mime_type,
     const String& text_encoding_name) {
   if (!text_encoding_name.IsEmpty()) {
-    return TextResourceDecoder::Create(TextResourceDecoderOptions(
+    return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent,
         WTF::TextEncoding(text_encoding_name)));
   }
   if (DOMImplementation::IsXMLMIMEType(mime_type)) {
     TextResourceDecoderOptions options(TextResourceDecoderOptions::kXMLContent);
     options.SetUseLenientXMLDecoding();
-    return TextResourceDecoder::Create(options);
+    return std::make_unique<TextResourceDecoder>(options);
   }
   if (DeprecatedEqualIgnoringCase(mime_type, "text/html")) {
-    return TextResourceDecoder::Create(TextResourceDecoderOptions(
+    return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kHTMLContent, UTF8Encoding()));
   }
   if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type) ||
       DOMImplementation::IsJSONMIMEType(mime_type)) {
-    return TextResourceDecoder::Create(TextResourceDecoderOptions(
+    return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent, UTF8Encoding()));
   }
   if (DOMImplementation::IsTextMIMEType(mime_type)) {
-    return TextResourceDecoder::Create(TextResourceDecoderOptions(
+    return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent,
         WTF::TextEncoding("ISO-8859-1")));
   }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 06868ea..7ef03df 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -5644,14 +5644,6 @@
                    overflow_->visual_overflow->ContentsVisualOverflowRect());
 }
 
-// TODO(kojii): The concept of this function is not clear. crbug.com/940991
-LayoutRect LayoutBox::VisualOverflowRectIgnoringOverflowClip() const {
-  if (!VisualOverflowIsSet())
-    return BorderBoxRect();
-  return UnionRect(overflow_->visual_overflow->SelfVisualOverflowRect(),
-                   overflow_->visual_overflow->ContentsVisualOverflowRect());
-}
-
 LayoutPoint LayoutBox::OffsetPoint(const Element* parent) const {
   return AdjustedPositionRelativeTo(PhysicalLocation(), parent);
 }
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index 9b8a501..23514bf 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -499,7 +499,6 @@
   }
 
   LayoutRect VisualOverflowRect() const override;
-  LayoutRect VisualOverflowRectIgnoringOverflowClip() const;
   LayoutRect PhysicalVisualOverflowRect() const {
     LayoutRect overflow_rect = VisualOverflowRect();
     FlipForWritingMode(overflow_rect);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc
index 5fa9ab2..7a6692aa 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc
@@ -105,8 +105,8 @@
 
   path_start_offset *= offset_scale;
 
-  return PathPositionMapper::Create(path_data, computed_path_length,
-                                    path_start_offset);
+  return std::make_unique<PathPositionMapper>(path_data, computed_path_length,
+                                              path_start_offset);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h
index f343c5e..92ccd99 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h
@@ -35,12 +35,9 @@
   USING_FAST_MALLOC(PathPositionMapper);
 
  public:
-  static std::unique_ptr<PathPositionMapper> Create(const Path& path,
-                                                    float computed_path_length,
-                                                    float start_offset) {
-    return base::WrapUnique(
-        new PathPositionMapper(path, computed_path_length, start_offset));
-  }
+  PathPositionMapper(const Path&,
+                     float computed_path_length,
+                     float start_offset);
 
   enum PositionType {
     kOnPath,
@@ -52,10 +49,6 @@
   float StartOffset() const { return path_start_offset_; }
 
  private:
-  PathPositionMapper(const Path&,
-                     float computed_path_length,
-                     float start_offset);
-
   Path::PositionCalculator position_calculator_;
   float path_length_;
   float path_start_offset_;
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_root_inline_box.cc b/third_party/blink/renderer/core/layout/svg/line/svg_root_inline_box.cc
index 5319bbbf..7e61e2b2 100644
--- a/third_party/blink/renderer/core/layout/svg/line/svg_root_inline_box.cc
+++ b/third_party/blink/renderer/core/layout/svg/line/svg_root_inline_box.cc
@@ -94,7 +94,7 @@
       rect.Unite(LayoutInlineBoxes(*child));
   }
 
-  LayoutRect logical_rect(rect);
+  LayoutRect logical_rect(EnclosingLayoutRect(rect));
   if (!box.IsHorizontal())
     logical_rect.SetSize(logical_rect.Size().TransposedSize());
 
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
index a24b06dc..df89043 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -465,7 +465,7 @@
   DCHECK_EQ(clipper->ResourceType(), kClipperResourceType);
 
   if (!clipper_filter_masker_data_)
-    clipper_filter_masker_data_ = ClipperFilterMaskerData::Create();
+    clipper_filter_masker_data_ = std::make_unique<ClipperFilterMaskerData>();
 
   clipper_filter_masker_data_->clipper = clipper;
 }
@@ -477,7 +477,7 @@
   DCHECK_EQ(filter->ResourceType(), kFilterResourceType);
 
   if (!clipper_filter_masker_data_)
-    clipper_filter_masker_data_ = ClipperFilterMaskerData::Create();
+    clipper_filter_masker_data_ = std::make_unique<ClipperFilterMaskerData>();
 
   clipper_filter_masker_data_->filter = filter;
 }
@@ -489,7 +489,7 @@
   DCHECK_EQ(marker_start->ResourceType(), kMarkerResourceType);
 
   if (!marker_data_)
-    marker_data_ = MarkerData::Create();
+    marker_data_ = std::make_unique<MarkerData>();
 
   marker_data_->marker_start = marker_start;
 }
@@ -501,7 +501,7 @@
   DCHECK_EQ(marker_mid->ResourceType(), kMarkerResourceType);
 
   if (!marker_data_)
-    marker_data_ = MarkerData::Create();
+    marker_data_ = std::make_unique<MarkerData>();
 
   marker_data_->marker_mid = marker_mid;
 }
@@ -513,7 +513,7 @@
   DCHECK_EQ(marker_end->ResourceType(), kMarkerResourceType);
 
   if (!marker_data_)
-    marker_data_ = MarkerData::Create();
+    marker_data_ = std::make_unique<MarkerData>();
 
   marker_data_->marker_end = marker_end;
 }
@@ -525,7 +525,7 @@
   DCHECK_EQ(masker->ResourceType(), kMaskerResourceType);
 
   if (!clipper_filter_masker_data_)
-    clipper_filter_masker_data_ = ClipperFilterMaskerData::Create();
+    clipper_filter_masker_data_ = std::make_unique<ClipperFilterMaskerData>();
 
   clipper_filter_masker_data_->masker = masker;
 }
@@ -535,7 +535,7 @@
     return;
 
   if (!fill_stroke_data_)
-    fill_stroke_data_ = FillStrokeData::Create();
+    fill_stroke_data_ = std::make_unique<FillStrokeData>();
 
   fill_stroke_data_->fill = fill;
 }
@@ -545,7 +545,7 @@
     return;
 
   if (!fill_stroke_data_)
-    fill_stroke_data_ = FillStrokeData::Create();
+    fill_stroke_data_ = std::make_unique<FillStrokeData>();
 
   fill_stroke_data_->stroke = stroke;
 }
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.h b/third_party/blink/renderer/core/layout/svg/svg_resources.h
index a70b4f60..44f2d0b 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.h
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.h
@@ -147,10 +147,6 @@
     ClipperFilterMaskerData()
         : clipper(nullptr), filter(nullptr), masker(nullptr) {}
 
-    static std::unique_ptr<ClipperFilterMaskerData> Create() {
-      return base::WrapUnique(new ClipperFilterMaskerData);
-    }
-
     LayoutSVGResourceClipper* clipper;
     LayoutSVGResourceFilter* filter;
     LayoutSVGResourceMasker* masker;
@@ -165,10 +161,6 @@
     MarkerData()
         : marker_start(nullptr), marker_mid(nullptr), marker_end(nullptr) {}
 
-    static std::unique_ptr<MarkerData> Create() {
-      return std::make_unique<MarkerData>();
-    }
-
     LayoutSVGResourceMarker* marker_start;
     LayoutSVGResourceMarker* marker_mid;
     LayoutSVGResourceMarker* marker_end;
@@ -185,10 +177,6 @@
    public:
     FillStrokeData() : fill(nullptr), stroke(nullptr) {}
 
-    static std::unique_ptr<FillStrokeData> Create() {
-      return std::make_unique<FillStrokeData>();
-    }
-
     LayoutSVGResourcePaintServer* fill;
     LayoutSVGResourcePaintServer* stroke;
   };
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 779a6f0..094796c 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -970,7 +970,8 @@
 void FrameFetchContext::CountDeprecation(WebFeature feature) const {
   if (GetResourceFetcherProperties().IsDetached())
     return;
-  Deprecation::CountDeprecation(GetFrame(), feature);
+  if (MasterDocumentLoader())
+    Deprecation::CountDeprecation(MasterDocumentLoader(), feature);
 }
 
 bool FrameFetchContext::ShouldBlockWebSocketByMixedContentCheck(
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index a95b961..fef422f 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -945,7 +945,7 @@
   // Check for non-escaped new lines in the url.
   if (url.PotentiallyDanglingMarkup() && url.ProtocolIsInHTTPFamily()) {
     Deprecation::CountDeprecation(
-        frame_, WebFeature::kCanRequestURLHTTPContainingNewline);
+        origin_document, WebFeature::kCanRequestURLHTTPContainingNewline);
     return;
   }
 
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index 6e5ce0b..90706eb7c 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -432,7 +432,7 @@
       *GetElement()->GetDocument().GetTaskRunner(TaskType::kDOMManipulation),
       FROM_HERE,
       WTF::Bind(&ImageLoader::DispatchPendingErrorEvent, WrapPersistent(this),
-                WTF::Passed(IncrementLoadEventDelayCount::Create(
+                WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
                     GetElement()->GetDocument()))));
 }
 
@@ -455,7 +455,7 @@
   Microtask::EnqueueMicrotask(
       WTF::Bind(&Task::Run, WTF::Passed(std::move(task))));
   delay_until_do_update_from_element_ =
-      IncrementLoadEventDelayCount::Create(element_->GetDocument());
+      std::make_unique<IncrementLoadEventDelayCount>(element_->GetDocument());
 }
 
 void ImageLoader::UpdateImageState(ImageResourceContent* new_image_content) {
@@ -744,7 +744,7 @@
     return;
 
   delay_until_image_notify_finished_ =
-      IncrementLoadEventDelayCount::Create(document);
+      std::make_unique<IncrementLoadEventDelayCount>(document);
 }
 
 void ImageLoader::ImageNotifyFinished(ImageResourceContent* resource) {
@@ -843,7 +843,7 @@
       *GetElement()->GetDocument().GetTaskRunner(TaskType::kDOMManipulation),
       FROM_HERE,
       WTF::Bind(&ImageLoader::DispatchPendingLoadEvent, WrapPersistent(this),
-                WTF::Passed(IncrementLoadEventDelayCount::Create(
+                WTF::Passed(std::make_unique<IncrementLoadEventDelayCount>(
                     GetElement()->GetDocument()))));
 }
 
diff --git a/third_party/blink/renderer/core/loader/progress_tracker.cc b/third_party/blink/renderer/core/loader/progress_tracker.cc
index c9783cd1..d0c5c839 100644
--- a/third_party/blink/renderer/core/loader/progress_tracker.cc
+++ b/third_party/blink/renderer/core/loader/progress_tracker.cc
@@ -56,11 +56,11 @@
   USING_FAST_MALLOC(ProgressItem);
 
  public:
-  explicit ProgressItem(long long length)
+  explicit ProgressItem(int64_t length)
       : bytes_received(0), estimated_length(length) {}
 
-  long long bytes_received;
-  long long estimated_length;
+  int64_t bytes_received;
+  int64_t estimated_length;
 
   DISALLOW_COPY_AND_ASSIGN(ProgressItem);
 };
@@ -158,7 +158,7 @@
   if (!item)
     return;
 
-  long long estimated_length = response.ExpectedContentLength();
+  int64_t estimated_length = response.ExpectedContentLength();
   if (estimated_length < 0)
     estimated_length = kProgressItemDefaultEstimatedLength;
   item->bytes_received = 0;
@@ -191,8 +191,8 @@
   if (did_first_contentful_paint_)
     progress_value_ += 0.1;
 
-  long long bytes_received = 0;
-  long long estimated_bytes_for_pending_requests = 0;
+  int64_t bytes_received = 0;
+  int64_t estimated_bytes_for_pending_requests = 0;
   for (const auto& progress_item : progress_items_) {
     bytes_received += progress_item.value->bytes_received;
     estimated_bytes_for_pending_requests +=
diff --git a/third_party/blink/renderer/core/loader/resource/text_resource.cc b/third_party/blink/renderer/core/loader/resource/text_resource.cc
index 13f43c8..f63a0ab 100644
--- a/third_party/blink/renderer/core/loader/resource/text_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/text_resource.cc
@@ -16,7 +16,7 @@
                            const ResourceLoaderOptions& options,
                            const TextResourceDecoderOptions& decoder_options)
     : Resource(resource_request, type, options),
-      decoder_(TextResourceDecoder::Create(decoder_options)) {}
+      decoder_(std::make_unique<TextResourceDecoder>(decoder_options)) {}
 
 TextResource::~TextResource() = default;
 
diff --git a/third_party/blink/renderer/core/loader/text_resource_decoder_builder.cc b/third_party/blink/renderer/core/loader/text_resource_decoder_builder.cc
index a9c8924..8d040cdc 100644
--- a/third_party/blink/renderer/core/loader/text_resource_decoder_builder.cc
+++ b/third_party/blink/renderer/core/loader/text_resource_decoder_builder.cc
@@ -134,25 +134,27 @@
     // Disable autodetection for XML/JSON to honor the default encoding (UTF-8)
     // for unlabelled documents.
     if (DOMImplementation::IsXMLMIMEType(mime_type)) {
-      decoder = TextResourceDecoder::Create(TextResourceDecoderOptions(
-          TextResourceDecoderOptions::kXMLContent, default_encoding));
+      decoder =
+          std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
+              TextResourceDecoderOptions::kXMLContent, default_encoding));
       use_hint_encoding = false;
     } else if (DOMImplementation::IsJSONMIMEType(mime_type)) {
-      decoder = TextResourceDecoder::Create(TextResourceDecoderOptions(
-          TextResourceDecoderOptions::kJSONContent, default_encoding));
+      decoder =
+          std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
+              TextResourceDecoderOptions::kJSONContent, default_encoding));
       use_hint_encoding = false;
     } else {
       WTF::TextEncoding hint_encoding;
       if (use_hint_encoding &&
           parent_frame->GetDocument()->EncodingWasDetectedHeuristically())
         hint_encoding = parent_frame->GetDocument()->Encoding();
-      decoder = TextResourceDecoder::Create(
+      decoder = std::make_unique<TextResourceDecoder>(
           TextResourceDecoderOptions::CreateWithAutoDetection(
               DetermineContentType(mime_type), default_encoding, hint_encoding,
               document->Url()));
     }
   } else {
-    decoder = TextResourceDecoder::Create(TextResourceDecoderOptions(
+    decoder = std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         DetermineContentType(mime_type), encoding_from_domain));
   }
   DCHECK(decoder);
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc
index 1c0b3f2..c265cb5 100644
--- a/third_party/blink/renderer/core/page/page.cc
+++ b/third_party/blink/renderer/core/page/page.cc
@@ -154,7 +154,7 @@
 }
 
 Page::Page(PageClients& page_clients)
-    : SettingsDelegate(Settings::Create()),
+    : SettingsDelegate(std::make_unique<Settings>()),
       main_frame_(nullptr),
       animator_(PageAnimator::Create(*this)),
       autoscroll_controller_(AutoscrollController::Create(*this)),
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
index 2838b6ca..7b4b6a9 100644
--- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc
+++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -88,7 +88,7 @@
   auto delegate = ValidationMessageOverlayDelegate::Create(
       *page_, anchor, message_, message_dir, sub_message, sub_message_dir);
   overlay_delegate_ = delegate.get();
-  overlay_ = FrameOverlay::Create(target_frame, std::move(delegate));
+  overlay_ = std::make_unique<FrameOverlay>(target_frame, std::move(delegate));
   bool success =
       target_frame->View()->UpdateLifecycleToCompositingCleanPlusScrolling();
   ValidationMessageVisibilityChanged(anchor);
diff --git a/third_party/blink/renderer/core/paint/fragment_data.h b/third_party/blink/renderer/core/paint/fragment_data.h
index d253ac7..961b1bf 100644
--- a/third_party/blink/renderer/core/paint/fragment_data.h
+++ b/third_party/blink/renderer/core/paint/fragment_data.h
@@ -137,7 +137,7 @@
   ObjectPaintProperties& EnsurePaintProperties() {
     EnsureRareData();
     if (!rare_data_->paint_properties)
-      rare_data_->paint_properties = ObjectPaintProperties::Create();
+      rare_data_->paint_properties = std::make_unique<ObjectPaintProperties>();
     return *rare_data_->paint_properties;
   }
   void ClearPaintProperties() {
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index 7293c6d..aef684a 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -78,10 +78,6 @@
   return CompositorElementIdFromUniqueObjectId(NewUniqueObjectId());
 }
 
-std::unique_ptr<LinkHighlightImpl> LinkHighlightImpl::Create(Node* node) {
-  return base::WrapUnique(new LinkHighlightImpl(node));
-}
-
 LinkHighlightImpl::LinkHighlightImpl(Node* node)
     : node_(node),
       current_graphics_layer_(nullptr),
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.h b/third_party/blink/renderer/core/paint/link_highlight_impl.h
index 13913324..8ba01a3a 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.h
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.h
@@ -57,7 +57,7 @@
                                             public CompositorAnimationDelegate,
                                             public CompositorAnimationClient {
  public:
-  static std::unique_ptr<LinkHighlightImpl> Create(Node*);
+  explicit LinkHighlightImpl(Node*);
   ~LinkHighlightImpl() override;
 
   void StartHighlightAnimationIfNeeded();
@@ -99,8 +99,6 @@
   }
 
  private:
-  LinkHighlightImpl(Node*);
-
   void ReleaseResources();
   void ComputeQuads(const Node&, Vector<FloatQuad>&) const;
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index f14ebf89..8fd0c1f4 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -314,20 +314,24 @@
 void NGBoxFragmentPainter::PaintBlockFlowContents(
     const PaintInfo& paint_info,
     const LayoutPoint& paint_offset) {
-  // Avoid painting descendants of the root element when stylesheets haven't
-  // loaded. This eliminates FOUC.  It's ok not to draw, because later on, when
-  // all the stylesheets do load, styleResolverMayHaveChanged() on Document will
-  // trigger a full paint invalidation.
-  // TODO(layout-dev): Handle without delegating to LayoutObject.
   const NGPhysicalBoxFragment& fragment = PhysicalFragment();
   LayoutObject* layout_object = fragment.GetLayoutObject();
 
   DCHECK(fragment.ChildrenInline());
 
-  LayoutRect overflow_rect(
-      box_fragment_.InkOverflowIgnoringOverflowClip().ToLayoutRect());
-  overflow_rect.MoveBy(paint_offset);
-  if (!paint_info.GetCullRect().Intersects(overflow_rect))
+  // Check if there were contents to be painted and return early if none.
+  // The union of |ContentsInkOverflow()| and |LocalRect()| covers the rect to
+  // check, in both cases of:
+  // 1. Painting non-scrolling contents.
+  // 2. Painting scrolling contents.
+  // For 1, check with |ContentsInkOverflow()|, except when there is no
+  // overflow, in which case check with |LocalRect()|. For 2, check with
+  // |LayoutOverflow()|, but this can be approximiated with
+  // |ContentsInkOverflow()|.
+  NGPhysicalOffsetRect content_ink_rect = fragment.LocalRect();
+  content_ink_rect.Unite(box_fragment_.ContentsInkOverflow());
+  content_ink_rect.offset += NGPhysicalOffset(paint_offset);
+  if (!paint_info.GetCullRect().Intersects(content_ink_rect.ToLayoutRect()))
     return;
 
   if (paint_info.phase == PaintPhase::kMask) {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 3a46335..e440c62 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -538,21 +538,12 @@
 }
 
 NGPhysicalOffsetRect NGPaintFragment::InkOverflow() const {
-  if (HasOverflowClip())
-    return SelfInkOverflow();
-  return InkOverflowIgnoringOverflowClip();
-}
-
-// TODO(kojii): The concept of this function is not clear. crbug.com/940991
-NGPhysicalOffsetRect NGPaintFragment::InkOverflowIgnoringOverflowClip() const {
-  // TODO(kojii): Honoring |HasMask()| when |HasOverflowClip()| is ignored looks
-  // questionable. Needs review. crbug.com/940991
-  if (Style().HasMask())
+  if (HasOverflowClip() || Style().HasMask())
     return SelfInkOverflow();
 
   // Get the cached value in |LayoutBox| if there is one.
   if (const LayoutBox* box = InkOverflowOwnerBox())
-    return NGPhysicalOffsetRect(box->VisualOverflowRectIgnoringOverflowClip());
+    return NGPhysicalOffsetRect(box->VisualOverflowRect());
 
   // NGPhysicalTextFragment caches ink overflow in layout.
   const NGPhysicalFragment& fragment = PhysicalFragment();
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index 8f0de15..48a4d3d 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -156,8 +156,6 @@
   // InkOverflow of itself, including contents if they contribute to the ink
   // overflow of this object (e.g. when not clipped,) in the local coordinate.
   NGPhysicalOffsetRect InkOverflow() const;
-  // TODO(kojii): The concept of this function is not clear. crbug.com/940991
-  NGPhysicalOffsetRect InkOverflowIgnoringOverflowClip() const;
 
   void RecalcInlineChildrenInkOverflow();
 
diff --git a/third_party/blink/renderer/core/paint/object_paint_properties.h b/third_party/blink/renderer/core/paint/object_paint_properties.h
index 344c4e50..cba5a47 100644
--- a/third_party/blink/renderer/core/paint/object_paint_properties.h
+++ b/third_party/blink/renderer/core/paint/object_paint_properties.h
@@ -40,10 +40,7 @@
   USING_FAST_MALLOC(ObjectPaintProperties);
 
  public:
-  static std::unique_ptr<ObjectPaintProperties> Create() {
-    return base::WrapUnique(new ObjectPaintProperties());
-  }
-
+  ObjectPaintProperties() = default;
 #if DCHECK_IS_ON()
   ~ObjectPaintProperties() { DCHECK(!is_immutable_); }
 #endif
@@ -238,8 +235,6 @@
 #endif
 
  private:
-  ObjectPaintProperties() = default;
-
   // Return true if the property tree structure changes (an existing node was
   // deleted), and false otherwise. See the class-level comment ("update & clear
   // implementation note") for details about why this is needed for efficiency.
diff --git a/third_party/blink/renderer/core/style/cached_ua_style.h b/third_party/blink/renderer/core/style/cached_ua_style.h
index 8d1ff0bb..4a8a479 100644
--- a/third_party/blink/renderer/core/style/cached_ua_style.h
+++ b/third_party/blink/renderer/core/style/cached_ua_style.h
@@ -47,9 +47,7 @@
   friend class ComputedStyle;
 
  public:
-  static std::unique_ptr<CachedUAStyle> Create(const ComputedStyle* style) {
-    return base::WrapUnique(new CachedUAStyle(style));
-  }
+  explicit CachedUAStyle(const ComputedStyle*);
 
   bool BorderColorEquals(const ComputedStyle& other) const;
   bool BorderWidthEquals(const ComputedStyle& other) const;
@@ -81,7 +79,6 @@
   StyleColor background_color;
 
  private:
-  explicit CachedUAStyle(const ComputedStyle*);
   DISALLOW_COPY_AND_ASSIGN(CachedUAStyle);
 };
 
diff --git a/third_party/blink/renderer/core/style/style_path.cc b/third_party/blink/renderer/core/style/style_path.cc
index 4f4a33f6..c6acccee4 100644
--- a/third_party/blink/renderer/core/style/style_path.cc
+++ b/third_party/blink/renderer/core/style/style_path.cc
@@ -30,7 +30,7 @@
 
 StylePath* StylePath::EmptyPath() {
   DEFINE_STATIC_REF(StylePath, empty_path,
-                    StylePath::Create(SVGPathByteStream::Create()));
+                    StylePath::Create(std::make_unique<SVGPathByteStream>()));
   return empty_path;
 }
 
diff --git a/third_party/blink/renderer/core/svg/svg_path.cc b/third_party/blink/renderer/core/svg/svg_path.cc
index 79e67b6..eeea4dd0 100644
--- a/third_party/blink/renderer/core/svg/svg_path.cc
+++ b/third_party/blink/renderer/core/svg/svg_path.cc
@@ -43,7 +43,7 @@
     const SVGPathByteStream& to_stream,
     float progress) {
   std::unique_ptr<SVGPathByteStream> result_stream =
-      SVGPathByteStream::Create();
+      std::make_unique<SVGPathByteStream>();
   SVGPathByteStreamBuilder builder(*result_stream);
   SVGPathByteStreamSource from_source(from_stream);
   SVGPathByteStreamSource to_source(to_stream);
@@ -57,7 +57,7 @@
     const SVGPathByteStream& by_stream,
     unsigned repeat_count = 1) {
   std::unique_ptr<SVGPathByteStream> result_stream =
-      SVGPathByteStream::Create();
+      std::make_unique<SVGPathByteStream>();
   SVGPathByteStreamBuilder builder(*result_stream);
   SVGPathByteStreamSource from_source(from_stream);
   SVGPathByteStreamSource by_source(by_stream);
@@ -94,7 +94,8 @@
 }
 
 SVGParsingError SVGPath::SetValueAsString(const String& string) {
-  std::unique_ptr<SVGPathByteStream> byte_stream = SVGPathByteStream::Create();
+  std::unique_ptr<SVGPathByteStream> byte_stream =
+      std::make_unique<SVGPathByteStream>();
   SVGParsingError parse_status =
       BuildByteStreamFromString(string, *byte_stream);
   path_value_ = CSSPathValue::Create(std::move(byte_stream));
@@ -102,7 +103,8 @@
 }
 
 SVGPropertyBase* SVGPath::CloneForAnimation(const String& value) const {
-  std::unique_ptr<SVGPathByteStream> byte_stream = SVGPathByteStream::Create();
+  std::unique_ptr<SVGPathByteStream> byte_stream =
+      std::make_unique<SVGPathByteStream>();
   BuildByteStreamFromString(value, *byte_stream);
   return SVGPath::Create(CSSPathValue::Create(std::move(byte_stream)));
 }
diff --git a/third_party/blink/renderer/core/svg/svg_path_byte_stream.h b/third_party/blink/renderer/core/svg/svg_path_byte_stream.h
index f44438135..f14b2c4 100644
--- a/third_party/blink/renderer/core/svg/svg_path_byte_stream.h
+++ b/third_party/blink/renderer/core/svg/svg_path_byte_stream.h
@@ -37,9 +37,7 @@
   USING_FAST_MALLOC(SVGPathByteStream);
 
  public:
-  static std::unique_ptr<SVGPathByteStream> Create() {
-    return base::WrapUnique(new SVGPathByteStream);
-  }
+  SVGPathByteStream() = default;
 
   std::unique_ptr<SVGPathByteStream> Clone() const {
     return base::WrapUnique(new SVGPathByteStream(data_));
@@ -66,7 +64,6 @@
   }
 
  private:
-  SVGPathByteStream() = default;
   SVGPathByteStream(const Data& data) : data_(data) {}
 
   Data data_;
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
index 6575793a..4282bde 100644
--- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
+++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
@@ -223,7 +223,7 @@
     return;
 
   if (!decoder_) {
-    decoder_ = TextResourceDecoder::Create(TextResourceDecoderOptions(
+    decoder_ = std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent,
         response_encoding_.IsEmpty() ? UTF8Encoding()
                                      : WTF::TextEncoding(response_encoding_)));
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.h b/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
index cdd176d..ea4b6be 100644
--- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
+++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
@@ -93,7 +93,7 @@
   bool Failed() const { return failed_; }
   bool Canceled() const { return canceled_; }
   unsigned long Identifier() const { return identifier_; }
-  long long AppCacheID() const { return app_cache_id_; }
+  int64_t AppCacheID() const { return app_cache_id_; }
 
   std::unique_ptr<Vector<uint8_t>> ReleaseCachedMetadata() {
     return std::move(cached_metadata_);
@@ -151,7 +151,7 @@
   bool is_top_level_script_ = false;
 
   unsigned long identifier_ = 0;
-  long long app_cache_id_ = 0;
+  int64_t app_cache_id_ = 0;
   std::unique_ptr<Vector<uint8_t>> cached_metadata_;
   Member<ContentSecurityPolicy> content_security_policy_;
   mojom::IPAddressSpace response_address_space_;
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test.cc b/third_party/blink/renderer/core/workers/worker_thread_test.cc
index f3d5abe..09e7128d 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -372,7 +372,7 @@
           CalculateHttpsState(security_origin_.get()), WorkerClients::Create(),
           mojom::IPAddressSpace::kLocal, nullptr /* originTrialToken */,
           base::UnguessableToken::Create(),
-          std::make_unique<WorkerSettings>(Settings::Create().get()),
+          std::make_unique<WorkerSettings>(std::make_unique<Settings>().get()),
           kV8CacheOptionsDefault, nullptr /* worklet_module_responses_map */);
 
   // Set wait_for_debugger so that the worker thread can pause
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index 04a6cc29..cab5f1e 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -106,7 +106,7 @@
         CalculateHttpsState(security_origin), worker_clients,
         mojom::IPAddressSpace::kLocal, nullptr,
         base::UnguessableToken::Create(),
-        std::make_unique<WorkerSettings>(Settings::Create().get()),
+        std::make_unique<WorkerSettings>(std::make_unique<Settings>().get()),
         kV8CacheOptionsDefault, nullptr /* worklet_module_responses_map */);
 
     Start(std::move(creation_params),
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 6e229da..d2934fc3 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -555,7 +555,7 @@
   return upload_;
 }
 
-void XMLHttpRequest::TrackProgress(long long length) {
+void XMLHttpRequest::TrackProgress(uint64_t length) {
   received_length_ += length;
 
   ChangeState(kLoading);
@@ -1173,8 +1173,8 @@
 
   // internalAbort() clears the response. Save the data needed for
   // dispatching ProgressEvents.
-  long long expected_length = response_.ExpectedContentLength();
-  long long received_length = received_length_;
+  int64_t expected_length = response_.ExpectedContentLength();
+  int64_t received_length = received_length_;
 
   if (!InternalAbort())
     return;
@@ -1298,8 +1298,8 @@
 }
 
 void XMLHttpRequest::DispatchProgressEvent(const AtomicString& type,
-                                           long long received_length,
-                                           long long expected_length) {
+                                           int64_t received_length,
+                                           int64_t expected_length) {
   bool length_computable =
       expected_length > 0 && received_length <= expected_length;
   uint64_t loaded =
@@ -1325,8 +1325,8 @@
   NETWORK_DVLOG(1) << this << " handleNetworkError()";
 
   // Response is cleared next, save needed progress event data.
-  long long expected_length = response_.ExpectedContentLength();
-  long long received_length = received_length_;
+  int64_t expected_length = response_.ExpectedContentLength();
+  int64_t received_length = received_length_;
 
   if (!InternalAbort())
     return;
@@ -1339,8 +1339,8 @@
   NETWORK_DVLOG(1) << this << " handleDidCancel()";
 
   // Response is cleared next, save needed progress event data.
-  long long expected_length = response_.ExpectedContentLength();
-  long long received_length = received_length_;
+  int64_t expected_length = response_.ExpectedContentLength();
+  int64_t received_length = received_length_;
 
   if (!InternalAbort())
     return;
@@ -1354,8 +1354,8 @@
 
 void XMLHttpRequest::HandleRequestError(DOMExceptionCode exception_code,
                                         const AtomicString& type,
-                                        long long received_length,
-                                        long long expected_length) {
+                                        int64_t received_length,
+                                        int64_t expected_length) {
   NETWORK_DVLOG(1) << this << " handleRequestError()";
 
   probe::DidFinishXHR(GetExecutionContext(), this);
@@ -1829,14 +1829,16 @@
 std::unique_ptr<TextResourceDecoder> XMLHttpRequest::CreateDecoder() const {
   const TextResourceDecoderOptions decoder_options_for_utf8_plain_text(
       TextResourceDecoderOptions::kPlainTextContent, UTF8Encoding());
-  if (response_type_code_ == kResponseTypeJSON)
-    return TextResourceDecoder::Create(decoder_options_for_utf8_plain_text);
+  if (response_type_code_ == kResponseTypeJSON) {
+    return std::make_unique<TextResourceDecoder>(
+        decoder_options_for_utf8_plain_text);
+  }
 
   WTF::TextEncoding final_response_charset = FinalResponseCharset();
   if (final_response_charset.IsValid()) {
     // If the final charset is given and valid, use the charset without
     // sniffing the content.
-    return TextResourceDecoder::Create(TextResourceDecoderOptions(
+    return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
         TextResourceDecoderOptions::kPlainTextContent, final_response_charset));
   }
 
@@ -1850,16 +1852,17 @@
   switch (response_type_code_) {
     case kResponseTypeDefault:
       if (ResponseIsXML())
-        return TextResourceDecoder::Create(decoder_options_for_xml);
+        return std::make_unique<TextResourceDecoder>(decoder_options_for_xml);
       FALLTHROUGH;
     case kResponseTypeText:
-      return TextResourceDecoder::Create(decoder_options_for_utf8_plain_text);
+      return std::make_unique<TextResourceDecoder>(
+          decoder_options_for_utf8_plain_text);
     case kResponseTypeDocument:
       if (ResponseIsHTML()) {
-        return TextResourceDecoder::Create(TextResourceDecoderOptions(
+        return std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
             TextResourceDecoderOptions::kHTMLContent, UTF8Encoding()));
       }
-      return TextResourceDecoder::Create(decoder_options_for_xml);
+      return std::make_unique<TextResourceDecoder>(decoder_options_for_xml);
     case kResponseTypeJSON:
     case kResponseTypeBlob:
     case kResponseTypeArrayBuffer:
@@ -1980,8 +1983,8 @@
   NETWORK_DVLOG(1) << this << " handleDidTimeout()";
 
   // Response is cleared next, save needed progress event data.
-  long long expected_length = response_.ExpectedContentLength();
-  long long received_length = received_length_;
+  int64_t expected_length = response_.ExpectedContentLength();
+  int64_t received_length = received_length_;
 
   if (!InternalAbort())
     return;
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
index e8e37bd..8eee5af4 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -244,7 +244,7 @@
   void SetRequestHeaderInternal(const AtomicString& name,
                                 const AtomicString& value);
 
-  void TrackProgress(long long data_length);
+  void TrackProgress(uint64_t data_length);
   // Changes m_state and dispatches a readyStateChange event if new m_state
   // value is different from last one.
   void ChangeState(State new_state);
@@ -261,7 +261,7 @@
   void CreateRequest(scoped_refptr<EncodedFormData>, ExceptionState&);
 
   // Dispatches a response ProgressEvent.
-  void DispatchProgressEvent(const AtomicString&, long long, long long);
+  void DispatchProgressEvent(const AtomicString&, int64_t, int64_t);
   // Dispatches a response ProgressEvent using values sampled from
   // m_receivedLength and m_response.
   void DispatchProgressEventFromSnapshot(const AtomicString&);
@@ -277,8 +277,8 @@
 
   void HandleRequestError(DOMExceptionCode,
                           const AtomicString&,
-                          long long,
-                          long long);
+                          int64_t,
+                          int64_t);
 
   void UpdateContentTypeAndCharset(const AtomicString& content_type,
                                    const String& charset);
@@ -325,13 +325,13 @@
 
   scoped_refptr<SharedBuffer> binary_response_builder_;
   size_t binary_response_builder_last_reported_size_ = 0;
-  long long length_downloaded_to_blob_ = 0;
-  long long length_downloaded_to_blob_last_reported_ = 0;
+  int64_t length_downloaded_to_blob_ = 0;
+  int64_t length_downloaded_to_blob_last_reported_ = 0;
 
   TraceWrapperMember<DOMArrayBuffer> response_array_buffer_;
 
   // Used for onprogress tracking
-  long long received_length_ = 0;
+  int64_t received_length_ = 0;
 
   // An exception to throw in synchronous mode. It's set when failure
   // notification is received from m_loader and thrown at the end of send() if
diff --git a/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js b/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
index 950b230..a5300e6 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
@@ -44,11 +44,11 @@
     this.registerRequiredCSS('ui/splitWidget.css');
 
     this.contentElement.classList.add('shadow-split-widget');
+    this._sidebarElement =
+        this.contentElement.createChild('div', 'shadow-split-widget-contents shadow-split-widget-sidebar vbox');
     this._mainElement =
         this.contentElement.createChild('div', 'shadow-split-widget-contents shadow-split-widget-main vbox');
     this._mainElement.createChild('slot').name = 'insertion-point-main';
-    this._sidebarElement =
-        this.contentElement.createChild('div', 'shadow-split-widget-contents shadow-split-widget-sidebar vbox');
     this._sidebarElement.createChild('slot').name = 'insertion-point-sidebar';
     this._resizerElement = this.contentElement.createChild('div', 'shadow-split-widget-resizer');
     this._resizerElementSize = null;
@@ -241,8 +241,23 @@
    * @param {boolean} secondIsSidebar
    */
   setSecondIsSidebar(secondIsSidebar) {
-    this.contentElement.classList.toggle('shadow-split-widget-first-is-sidebar', !secondIsSidebar);
+    if (secondIsSidebar === this._secondIsSidebar)
+      return;
     this._secondIsSidebar = secondIsSidebar;
+    if (!this._mainWidget || !this._mainWidget.shouldHideOnDetach()) {
+      if (secondIsSidebar)
+        this.contentElement.insertBefore(this._mainElement, this._sidebarElement);
+      else
+        this.contentElement.insertBefore(this._mainElement, this._resizerElement);
+    } else if (!this._sidebarWidget || !this._sidebarWidget.shouldHideOnDetach()) {
+      if (secondIsSidebar)
+        this.contentElement.insertBefore(this._sidebarElement, this._resizerElement);
+      else
+        this.contentElement.insertBefore(this._sidebarElement, this._mainElement);
+    } else {
+      console.error('Could not swap split widget side. Both children widgets contain iframes.');
+      this._secondIsSidebar = !secondIsSidebar;
+    }
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/ui/splitWidget.css b/third_party/blink/renderer/devtools/front_end/ui/splitWidget.css
index 1702593..b0171ca 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/splitWidget.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/splitWidget.css
@@ -66,14 +66,6 @@
     z-index: 500;
 }
 
-.shadow-split-widget.hbox.shadow-split-widget-first-is-sidebar {
-    flex-direction: row-reverse !important;
-}
-
-.shadow-split-widget.vbox.shadow-split-widget-first-is-sidebar {
-    flex-direction: column-reverse !important;
-}
-
 .shadow-split-widget-resizer-border {
     pointer-events: none;
 }
@@ -87,7 +79,7 @@
     border-top: 1px solid var(--divider-color);
 }
 
-.shadow-split-widget.vbox.shadow-split-widget-first-is-sidebar > .shadow-split-widget-sidebar:not(.maximized) {
+.shadow-split-widget.vbox > .shadow-split-widget-sidebar:first-child:not(.maximized) {
     border: 0;
     border-bottom: 1px solid var(--divider-color);
 }
@@ -97,7 +89,7 @@
     border-left: 1px solid var(--divider-color);
 }
 
-.shadow-split-widget.hbox.shadow-split-widget-first-is-sidebar > .shadow-split-widget-sidebar:not(.maximized) {
+.shadow-split-widget.hbox > .shadow-split-widget-sidebar:first-child:not(.maximized) {
     border: 0;
     border-right: 1px solid var(--divider-color);
 }
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index 7457572..314e12d9 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -515,7 +515,7 @@
     // TODO(horo): Use the charset in Content-type header of the response.
     // See crbug.com/743311.
     std::unique_ptr<TextResourceDecoder> text_decoder =
-        TextResourceDecoder::Create(
+        std::make_unique<TextResourceDecoder>(
             TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
 
     return V8CodeCache::GenerateFullCodeCache(
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
index 1f386d5..90fdf66 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
@@ -48,7 +48,7 @@
     if (GetDocument().IsSecureContext()) {
       UseCounter::Count(GetDocument(), WebFeature::kDeviceMotionSecureOrigin);
     } else {
-      Deprecation::CountDeprecation(frame,
+      Deprecation::CountDeprecation(GetDocument(),
                                     WebFeature::kDeviceMotionInsecureOrigin);
       HostsUsingFeatures::CountAnyWorld(
           GetDocument(),
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
index 9191d83..b00d2e7 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
@@ -46,7 +46,7 @@
                         WebFeature::kDeviceOrientationAbsoluteSecureOrigin);
     } else {
       Deprecation::CountDeprecation(
-          frame, WebFeature::kDeviceOrientationAbsoluteInsecureOrigin);
+          GetDocument(), WebFeature::kDeviceOrientationAbsoluteInsecureOrigin);
       // TODO: add rappor logging of insecure origins as in
       // DeviceOrientationController.
       if (frame->GetSettings()->GetStrictPowerfulFeatureRestrictions())
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
index 8cdf0f7..4f769b1 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -61,7 +61,7 @@
                         WebFeature::kDeviceOrientationSecureOrigin);
     } else {
       Deprecation::CountDeprecation(
-          frame, WebFeature::kDeviceOrientationInsecureOrigin);
+          GetDocument(), WebFeature::kDeviceOrientationInsecureOrigin);
       HostsUsingFeatures::CountAnyWorld(
           GetDocument(),
           HostsUsingFeatures::Feature::kDeviceOrientationInsecureHost);
diff --git a/third_party/blink/renderer/modules/mediastream/input_device_info.cc b/third_party/blink/renderer/modules/mediastream/input_device_info.cc
index a746278..c770b3a 100644
--- a/third_party/blink/renderer/modules/mediastream/input_device_info.cc
+++ b/third_party/blink/renderer/modules/mediastream/input_device_info.cc
@@ -6,9 +6,13 @@
 
 #include <algorithm>
 
+#include "build/build_config.h"
 #include "media/base/sample_format.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
 #include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/renderer/modules/mediastream/media_track_capabilities.h"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
 
 namespace blink {
 
@@ -75,6 +79,28 @@
   }
 }
 
+void InputDeviceInfo::SetAudioInputCapabilities(
+    mojom::blink::AudioInputDeviceCapabilitiesPtr audio_input_capabilities) {
+  DCHECK_EQ(deviceId(), audio_input_capabilities->device_id);
+
+  if (audio_input_capabilities->is_valid) {
+    platform_capabilities_.channel_count = {1,
+                                            audio_input_capabilities->channels};
+
+    platform_capabilities_.sample_rate = {
+        std::min(kAudioProcessingSampleRate,
+                 audio_input_capabilities->sample_rate),
+        std::max(kAudioProcessingSampleRate,
+                 audio_input_capabilities->sample_rate)};
+    double fallback_latency = kFallbackAudioLatencyMs / 1000;
+    platform_capabilities_.latency = {
+        std::min(fallback_latency,
+                 audio_input_capabilities->latency.InSecondsF()),
+        std::max(fallback_latency,
+                 audio_input_capabilities->latency.InSecondsF())};
+  }
+}
+
 MediaTrackCapabilities* InputDeviceInfo::getCapabilities() const {
   MediaTrackCapabilities* capabilities = MediaTrackCapabilities::Create();
 
@@ -97,6 +123,27 @@
     sample_size->setMax(
         media::SampleFormatToBitsPerChannel(media::kSampleFormatS16));
     capabilities->setSampleSize(sample_size);
+    // Channel count.
+    if (!platform_capabilities_.channel_count.empty()) {
+      LongRange* channel_count = LongRange::Create();
+      channel_count->setMin(platform_capabilities_.channel_count[0]);
+      channel_count->setMax(platform_capabilities_.channel_count[1]);
+      capabilities->setChannelCount(channel_count);
+    }
+    // Sample rate.
+    if (!platform_capabilities_.sample_rate.empty()) {
+      LongRange* sample_rate = LongRange::Create();
+      sample_rate->setMin(platform_capabilities_.sample_rate[0]);
+      sample_rate->setMax(platform_capabilities_.sample_rate[1]);
+      capabilities->setSampleRate(sample_rate);
+    }
+    // Latency.
+    if (!platform_capabilities_.latency.empty()) {
+      DoubleRange* latency = DoubleRange::Create();
+      latency->setMin(platform_capabilities_.latency[0]);
+      latency->setMax(platform_capabilities_.latency[1]);
+      capabilities->setLatency(latency);
+    }
   }
 
   if (DeviceType() == MediaDeviceType::MEDIA_VIDEO_INPUT) {
diff --git a/third_party/blink/renderer/modules/mediastream/input_device_info.h b/third_party/blink/renderer/modules/mediastream/input_device_info.h
index abd16df..f9131e80 100644
--- a/third_party/blink/renderer/modules/mediastream/input_device_info.h
+++ b/third_party/blink/renderer/modules/mediastream/input_device_info.h
@@ -27,6 +27,7 @@
                   MediaDeviceType);
 
   void SetVideoInputCapabilities(mojom::blink::VideoInputDeviceCapabilitiesPtr);
+  void SetAudioInputCapabilities(mojom::blink::AudioInputDeviceCapabilitiesPtr);
 
   MediaTrackCapabilities* getCapabilities() const;
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc
index 223370b..f6644c54 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -86,6 +86,7 @@
   GetDispatcherHost(frame)->EnumerateDevices(
       true /* audio input */, true /* video input */, true /* audio output */,
       true /* request_video_input_capabilities */,
+      true /* request_audio_input_capabilities */,
       WTF::Bind(&MediaDevices::DevicesEnumerated, WrapPersistent(this),
                 WrapPersistent(resolver)));
   return promise;
@@ -267,7 +268,9 @@
     ScriptPromiseResolver* resolver,
     Vector<Vector<mojom::blink::MediaDeviceInfoPtr>> enumeration,
     Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>
-        video_input_capabilities) {
+        video_input_capabilities,
+    Vector<mojom::blink::AudioInputDeviceCapabilitiesPtr>
+        audio_input_capabilities) {
   if (!requests_.Contains(resolver))
     return;
 
@@ -287,6 +290,12 @@
             .size(),
         video_input_capabilities.size());
   }
+  if (!audio_input_capabilities.IsEmpty()) {
+    DCHECK_EQ(
+        enumeration[static_cast<wtf_size_t>(MediaDeviceType::MEDIA_AUDIO_INPUT)]
+            .size(),
+        audio_input_capabilities.size());
+  }
 
   MediaDeviceInfoVector media_devices;
   for (wtf_size_t i = 0;
@@ -306,6 +315,11 @@
           input_device_info->SetVideoInputCapabilities(
               std::move(video_input_capabilities[j]));
         }
+        if (device_type == MediaDeviceType::MEDIA_AUDIO_INPUT &&
+            !audio_input_capabilities.IsEmpty()) {
+          input_device_info->SetAudioInputCapabilities(
+              std::move(audio_input_capabilities[j]));
+        }
         media_devices.push_back(input_device_info);
       } else {
         media_devices.push_back(
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.h b/third_party/blink/renderer/modules/mediastream/media_devices.h
index 4381afc..49de9b65 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices.h
+++ b/third_party/blink/renderer/modules/mediastream/media_devices.h
@@ -110,7 +110,8 @@
   void Dispose();
   void DevicesEnumerated(ScriptPromiseResolver*,
                          Vector<Vector<mojom::blink::MediaDeviceInfoPtr>>,
-                         Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>);
+                         Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>,
+                         Vector<mojom::blink::AudioInputDeviceCapabilitiesPtr>);
   void OnDispatcherHostConnectionError();
   const mojom::blink::MediaDevicesDispatcherHostPtr& GetDispatcherHost(
       LocalFrame*);
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index 99d530b..4e9b05c 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -41,11 +41,14 @@
                         bool request_video_input,
                         bool request_audio_output,
                         bool request_video_input_capabilities,
+                        bool request_audio_input_capabilities,
                         EnumerateDevicesCallback callback) override {
     Vector<Vector<MediaDeviceInfoPtr>> enumeration(
         static_cast<size_t>(MediaDeviceType::NUM_MEDIA_DEVICE_TYPES));
     Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>
         video_input_capabilities;
+    Vector<mojom::blink::AudioInputDeviceCapabilitiesPtr>
+        audio_input_capabilities;
     MediaDeviceInfoPtr device_info;
     if (request_audio_input) {
       device_info = mojom::blink::MediaDeviceInfo::New();
@@ -61,6 +64,9 @@
       device_info->group_id = "fake_group 2";
       enumeration[static_cast<size_t>(MediaDeviceType::MEDIA_AUDIO_INPUT)]
           .push_back(std::move(device_info));
+
+      // TODO(crbug.com/935960): add missing mocked capabilities and related
+      // tests when media::AudioParameters is visible in this context.
     }
     if (request_video_input) {
       device_info = mojom::blink::MediaDeviceInfo::New();
@@ -101,7 +107,8 @@
           .push_back(std::move(device_info));
     }
     std::move(callback).Run(std::move(enumeration),
-                            std::move(video_input_capabilities));
+                            std::move(video_input_capabilities),
+                            std::move(audio_input_capabilities));
   }
 
   void GetVideoInputCapabilities(GetVideoInputCapabilitiesCallback) override {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
index 9cc99c54..4c1c465 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -357,6 +357,27 @@
       sample_size->setMax(platform_capabilities.sample_size[1]);
       capabilities->setSampleSize(sample_size);
     }
+    // Channel count.
+    if (platform_capabilities.channel_count.size() == 2) {
+      LongRange* channel_count = LongRange::Create();
+      channel_count->setMin(platform_capabilities.channel_count[0]);
+      channel_count->setMax(platform_capabilities.channel_count[1]);
+      capabilities->setChannelCount(channel_count);
+    }
+    // Sample rate.
+    if (platform_capabilities.sample_rate.size() == 2) {
+      LongRange* sample_rate = LongRange::Create();
+      sample_rate->setMin(platform_capabilities.sample_rate[0]);
+      sample_rate->setMax(platform_capabilities.sample_rate[1]);
+      capabilities->setSampleRate(sample_rate);
+    }
+    // Latency.
+    if (platform_capabilities.latency.size() == 2) {
+      DoubleRange* latency = DoubleRange::Create();
+      latency->setMin(platform_capabilities.latency[0]);
+      latency->setMax(platform_capabilities.latency[1]);
+      capabilities->setLatency(latency);
+    }
   }
 
   if (component_->Source()->GetType() == MediaStreamSource::kTypeVideo) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_track_capabilities.idl b/third_party/blink/renderer/modules/mediastream/media_track_capabilities.idl
index deb815f..3cbe88a 100644
--- a/third_party/blink/renderer/modules/mediastream/media_track_capabilities.idl
+++ b/third_party/blink/renderer/modules/mediastream/media_track_capabilities.idl
@@ -15,6 +15,9 @@
     sequence<boolean> autoGainControl;
     sequence<boolean> noiseSuppression;
     LongRange sampleSize;
+    LongRange channelCount;
+    LongRange sampleRate;
+    DoubleRange latency;
     DOMString deviceId;
     DOMString groupId;
     // W3C Image Capture API
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
index 03400a12..a2aba69 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -529,7 +529,7 @@
 
   // While getUserMedia is blocked on insecure origins, we still want to
   // count attempts to use it.
-  Deprecation::CountDeprecation(document->GetFrame(),
+  Deprecation::CountDeprecation(document,
                                 WebFeature::kGetUserMediaInsecureOrigin);
   Deprecation::CountDeprecationCrossOriginIframe(
       *document, WebFeature::kGetUserMediaInsecureOriginIframe);
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
index 6fe738e..40b9252 100644
--- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
+++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -732,11 +732,13 @@
   // Remove the track.
   for (auto it = adapters_.begin(); it != adapters_.end(); ++it) {
     track_callbacks = (*it)->RemoveAndGetCallbacks(track);
+    if (track_callbacks.frame_callback.is_null())
+      continue;
     if ((*it)->IsEmpty()) {
       DCHECK(!track_callbacks.frame_callback.is_null());
       adapters_.erase(it);
-      break;
     }
+    break;
   }
 
   // If the track was found, re-add it with new settings.
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc
index 5bfaf63..ac53f40 100644
--- a/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -272,7 +272,8 @@
 void ModulesInitializer::ProvideModulesToPage(Page& page,
                                               WebViewClient* client) const {
   MediaKeysController::ProvideMediaKeysTo(page);
-  ::blink::ProvideContextFeaturesTo(page, ContextFeaturesClientImpl::Create());
+  ::blink::ProvideContextFeaturesTo(
+      page, std::make_unique<ContextFeaturesClientImpl>());
   ::blink::ProvideDatabaseClientTo(page,
                                    MakeGarbageCollected<DatabaseClient>());
   StorageNamespace::ProvideSessionStorageNamespaceTo(page, client);
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
index 96e9078..5ee60afe 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
@@ -277,7 +277,7 @@
 
   // This is from WorkerClassicScriptLoader::DidReceiveData.
   std::unique_ptr<TextResourceDecoder> decoder =
-      TextResourceDecoder::Create(TextResourceDecoderOptions(
+      std::make_unique<TextResourceDecoder>(TextResourceDecoderOptions(
           TextResourceDecoderOptions::kPlainTextContent,
           raw_script_data->Encoding().IsEmpty()
               ? UTF8Encoding()
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string.cc b/third_party/blink/renderer/platform/bindings/parkable_string.cc
index 94ba672..e1c38bd 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -166,7 +166,11 @@
 // - kParked:
 //   - Old: Parked, and not touched nor locked since then
 //   - Young: Lock() makes a string young but doesn't unpark it.
-enum class ParkableStringImpl::State { kUnparked, kParkingInProgress, kParked };
+enum class ParkableStringImpl::State : uint8_t {
+  kUnparked,
+  kParkingInProgress,
+  kParked
+};
 
 // Current "ownership" status of the underlying data.
 //
@@ -175,7 +179,7 @@
 // - kTooManyReferences: |string_| has multiple references pointing to it,
 //   cannot change it.
 // - kLocked: |this| is locked.
-enum class ParkableStringImpl::Status {
+enum class ParkableStringImpl::Status : uint8_t {
   kUnreferencedExternally,
   kTooManyReferences,
   kLocked
@@ -191,7 +195,8 @@
       is_young_(true),
       may_be_parked_(parkable == ParkableState::kParkable),
       is_8bit_(string_.Is8Bit()),
-      length_(string_.length())
+      length_(string_.length()),
+      hash_(string_.Impl()->GetHash())
 #if DCHECK_IS_ON()
       ,
       owning_thread_(CurrentThread())
@@ -213,7 +218,8 @@
 #endif
   AsanUnpoisonString(string_);
   DCHECK(state_ == State::kParked || state_ == State::kUnparked);
-  ParkableStringManager::Instance().Remove(this, string_.Impl());
+
+  ParkableStringManager::Instance().Remove(this);
 }
 
 void ParkableStringImpl::Lock() {
@@ -269,6 +275,55 @@
     compressed_ = nullptr;
 }
 
+bool ParkableStringImpl::Equal(const ParkableStringImpl& rhs) const {
+  // This is called when two strings share the same bucket. Either string can
+  // be parked.
+  //
+  // As a consequence, for a hash collision or true equality, a string can be
+  // unparked in this function, making it expensive (see below).
+  AssertOnValidThread();
+
+  if (this == &rhs)
+    return true;
+
+  // The hash is actually only 24 bits. If collisions become an issue, replace
+  // it either with a stronger one (murmur2 for instance), or switch to SHA256
+  // and don't check for equality.
+  if (GetHash() != rhs.GetHash() || length() != rhs.length())
+    return false;
+
+  // Can be expensive.
+  //
+  // Using the transient version because otherwise a lot of code in
+  // ParkableStringManager becomes more reentrant than it already is, and many
+  // parts of ParkableStringImpl would become mutable.
+  // For instance, ToString() can unpark a string, and that would call into
+  // ParkableStringManager::OnUnparked(), from ParkableStringManager::Add().
+  //
+  // Note that we only get here in two cases:
+  // - Hash collision
+  // - True equality
+  //
+  // Assuming that collisions are rare, unparking for true equality is not too
+  // bad, as the obvious alternative is to compare a cryptographic hash. On
+  // low-end ARM devices, unparking is roughly as expensive as SHA256, but we
+  // only do it for one of the two strings, so this is still expected to be
+  // faster than SHA256, at the cost of more memory (since both strings are held
+  // in memory temporarily).
+  return ToStringTransient() == rhs.ToStringTransient();
+}
+
+bool ParkableStringImpl::Equal(scoped_refptr<StringImpl> string) const {
+  // See above for comments about cost of this function. This is called from
+  // ParkableStringManager::Add() through ParkableStringImplTranslator.
+  AssertOnValidThread();
+
+  if (GetHash() != string->GetHash() || length() != string->length())
+    return false;
+
+  return ToStringTransient() == String(string);
+}
+
 void ParkableStringImpl::MakeYoung() {
   mutex_.AssertAcquired();
   is_young_ = true;
@@ -286,6 +341,16 @@
   return string_;
 }
 
+String ParkableStringImpl::ToStringTransient() const {
+  AssertOnValidThread();
+  if (!is_parked()) {
+    AsanUnpoisonString(string_);
+    return string_;
+  }
+
+  return UnparkInternal();
+}
+
 unsigned ParkableStringImpl::CharactersSizeInBytes() const {
   AssertOnValidThread();
   return length_ * (is_8bit() ? sizeof(LChar) : sizeof(UChar));
@@ -346,7 +411,7 @@
   if (has_compressed_data()) {
     RecordParkingAction(ParkingAction::kParkedInBackground);
     state_ = State::kParked;
-    ParkableStringManager::Instance().OnParked(this, string_.Impl());
+    ParkableStringManager::Instance().OnParked(this);
 
     // Must unpoison the memory before releasing it.
     AsanUnpoisonString(string_);
@@ -398,47 +463,58 @@
   TRACE_EVENT1("blink", "ParkableStringImpl::Unpark", "size",
                CharactersSizeInBytes());
   DCHECK(compressed_);
-  base::ElapsedTimer timer;
-  {
-    base::StringPiece compressed_string_piece(
-        reinterpret_cast<const char*>(compressed_->data()),
-        compressed_->size() * sizeof(uint8_t));
-    String uncompressed;
-    base::StringPiece uncompressed_string_piece;
-    size_t size = CharactersSizeInBytes();
-    if (is_8bit()) {
-      LChar* data;
-      uncompressed = String::CreateUninitialized(length(), data);
-      uncompressed_string_piece =
-          base::StringPiece(reinterpret_cast<const char*>(data), size);
-    } else {
-      UChar* data;
-      uncompressed = String::CreateUninitialized(length(), data);
-      uncompressed_string_piece =
-          base::StringPiece(reinterpret_cast<const char*>(data), size);
-    }
+  string_ = UnparkInternal();
+  state_ = State::kUnparked;
+  ParkableStringManager::Instance().OnUnparked(this);
+}
 
-    // If decompression fails, this is either because:
-    // 1. The output buffer is too small
-    // 2. Compressed data is corrupted
-    // 3. Cannot allocate memory in zlib
-    //
-    // (1-2) are data corruption, and (3) is OOM. In all cases, we cannot
-    // recover the string we need, nothing else to do than to abort.
-    CHECK(compression::GzipUncompress(compressed_string_piece,
-                                      uncompressed_string_piece));
-    string_ = uncompressed;
-    state_ = State::kUnparked;
+String ParkableStringImpl::UnparkInternal() const {
+  AssertOnValidThread();
+  DCHECK(is_parked());
+  // Note: No need for |mutex_| to be held, this doesn't touch any member
+  // variable protected by it.
+
+  base::ElapsedTimer timer;
+  base::StringPiece compressed_string_piece(
+      reinterpret_cast<const char*>(compressed_->data()),
+      compressed_->size() * sizeof(uint8_t));
+  String uncompressed;
+  base::StringPiece uncompressed_string_piece;
+  size_t size = CharactersSizeInBytes();
+  if (is_8bit()) {
+    LChar* data;
+    uncompressed = String::CreateUninitialized(length(), data);
+    uncompressed_string_piece =
+        base::StringPiece(reinterpret_cast<const char*>(data), size);
+  } else {
+    UChar* data;
+    uncompressed = String::CreateUninitialized(length(), data);
+    uncompressed_string_piece =
+        base::StringPiece(reinterpret_cast<const char*>(data), size);
   }
-  base::TimeDelta elapsed = timer.Elapsed();
-  ParkableStringManager::Instance().OnUnparked(this, string_.Impl(), elapsed);
+
+  // If decompression fails, this is either because:
+  // 1. The output buffer is too small
+  // 2. Compressed data is corrupted
+  // 3. Cannot allocate memory in zlib
+  //
+  // (1-2) are data corruption, and (3) is OOM. In all cases, we cannot
+  // recover the string we need, nothing else to do than to abort.
+  //
+  // Stability sheriffs: If you see this, this is likely an OOM.
+  CHECK(compression::GzipUncompress(compressed_string_piece,
+                                    uncompressed_string_piece));
 
   bool backgrounded =
       ParkableStringManager::Instance().IsRendererBackgrounded();
   auto action = backgrounded ? ParkingAction::kUnparkedInBackground
                              : ParkingAction::kUnparkedInForeground;
   RecordParkingAction(action);
+  base::TimeDelta elapsed = timer.Elapsed();
+  ParkableStringManager::Instance().RecordUnparkingTime(elapsed);
   RecordStatistics(CharactersSizeInBytes(), elapsed, action);
+
+  return uncompressed;
 }
 
 void ParkableStringImpl::OnParkingCompleteOnMainThread(
@@ -463,7 +539,7 @@
   if (CanParkNow() && compressed_) {
     RecordParkingAction(ParkingAction::kParkedInBackground);
     state_ = State::kParked;
-    ParkableStringManager::Instance().OnParked(this, string_.Impl());
+    ParkableStringManager::Instance().OnParked(this);
 
     // Must unpoison the memory before releasing it.
     AsanUnpoisonString(string_);
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string.h b/third_party/blink/renderer/platform/bindings/parkable_string.h
index 0fd71c8..05f8e2b 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string.h
+++ b/third_party/blink/renderer/platform/bindings/parkable_string.h
@@ -123,8 +123,15 @@
   bool is_young() const { return is_young_; }
 
  private:
-  enum class State;
-  enum class Status;
+  enum class State : uint8_t;
+  enum class Status : uint8_t;
+  friend class ParkableStringManager;
+
+  unsigned GetHash() const { return hash_; }
+
+  // Both functions below can be expensive (i.e. trigger unparking).
+  bool Equal(const ParkableStringImpl& rhs) const;
+  bool Equal(const scoped_refptr<StringImpl> rhs) const;
 
 #if defined(ADDRESS_SANITIZER)
   // See |CompressInBackground()|. Doesn't make the string young.
@@ -139,6 +146,8 @@
   bool CanParkNow() const;
   void ParkInternal(ParkingMode mode);
   void Unpark();
+  String UnparkInternal() const;
+  String ToStringTransient() const;
   // Called on the main thread after compression is done.
   // |params| is the same as the one passed to |CompressInBackground()|,
   // |compressed| is the compressed data, nullptr if compression failed.
@@ -161,6 +170,7 @@
   const bool may_be_parked_ : 1;
   const bool is_8bit_ : 1;
   const unsigned length_;
+  const wtf_size_t hash_;
 
 #if DCHECK_IS_ON()
   const base::PlatformThreadId owning_thread_;
@@ -174,6 +184,8 @@
 
   FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockUnlock);
   FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, LockParkedString);
+  FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, Equality);
+  FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, EqualityNoUnparking);
   DISALLOW_COPY_AND_ASSIGN(ParkableStringImpl);
 };
 
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index d524a6b..846499a 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -25,6 +25,17 @@
 
 namespace blink {
 
+struct ParkableStringManager::Statistics {
+  size_t original_size;
+  size_t uncompressed_size;
+  size_t compressed_original_size;
+  size_t compressed_size;
+  size_t metadata_size;
+  size_t overhead_size;
+  size_t total_size;
+  int64_t savings_size;
+};
+
 namespace {
 
 enum class CompressionMode { kDisabled, kBackground, kForeground };
@@ -51,64 +62,7 @@
   }
 };
 
-using UnparkedMap =
-    HashMap<StringImpl*, ParkableStringImpl*, PtrHash<StringImpl>>;
-using ParkedSet = HashSet<ParkableStringImpl*, PtrHash<ParkableStringImpl>>;
-
-Vector<ParkableStringImpl*> GetUnparkedStrings(
-    const UnparkedMap& unparked_strings) {
-  WTF::Vector<ParkableStringImpl*> unparked;
-  unparked.ReserveCapacity(unparked_strings.size());
-  for (ParkableStringImpl* str : unparked_strings.Values())
-    unparked.push_back(str);
-
-  return unparked;
-}
-
-struct Statistics {
-  size_t original_size;
-  size_t uncompressed_size;
-  size_t compressed_original_size;
-  size_t compressed_size;
-  size_t metadata_size;
-  size_t overhead_size;
-  size_t total_size;
-  int64_t savings_size;
-};
-
-Statistics ComputeStatistics(const UnparkedMap& unparked,
-                             const ParkedSet& parked) {
-  Statistics stats = {};
-
-  for (ParkableStringImpl* str : unparked.Values()) {
-    size_t size = str->CharactersSizeInBytes();
-    stats.original_size += size;
-    stats.uncompressed_size += size;
-    stats.metadata_size += sizeof(ParkableStringImpl);
-
-    if (str->has_compressed_data())
-      stats.overhead_size += str->compressed_size();
-  }
-
-  for (ParkableStringImpl* str : parked) {
-    size_t size = str->CharactersSizeInBytes();
-    stats.compressed_original_size += size;
-    stats.original_size += size;
-    stats.compressed_size += str->compressed_size();
-    stats.metadata_size += sizeof(ParkableStringImpl);
-  }
-
-  stats.total_size = stats.uncompressed_size + stats.compressed_size +
-                     stats.metadata_size + stats.overhead_size;
-  size_t memory_footprint = stats.compressed_size + stats.uncompressed_size +
-                            stats.metadata_size + stats.overhead_size;
-  stats.savings_size =
-      stats.original_size - static_cast<int64_t>(memory_footprint);
-
-  return stats;
-}
-
-void RecordMemoryStatistics(const Statistics& stats,
+void RecordMemoryStatistics(const ParkableStringManager::Statistics& stats,
                             const std::string& suffix) {
   base::UmaHistogramCounts100000("Memory.ParkableString.TotalSizeKb" + suffix,
                                  stats.original_size / 1000);
@@ -129,6 +83,40 @@
 
 }  // namespace
 
+struct ParkableStringManager::ParkableStringImplHash {
+  STATIC_ONLY(ParkableStringImplHash);
+
+  static unsigned GetHash(ParkableStringImpl* key) { return key->GetHash(); }
+
+  static inline bool Equal(const ParkableStringImpl* a,
+                           const ParkableStringImpl* b) {
+    return a->Equal(*b);
+  }
+
+  static constexpr bool safe_to_compare_to_empty_or_deleted = false;
+};
+
+struct ParkableStringManager::ParkableStringImplTranslator {
+  STATIC_ONLY(ParkableStringImplTranslator);
+
+  static unsigned GetHash(const scoped_refptr<StringImpl>& string) {
+    return string->GetHash();
+  }
+
+  static bool Equal(const ParkableStringImpl* parkable,
+                    const scoped_refptr<StringImpl>& string) {
+    return parkable->Equal(string);
+  }
+
+  static void Translate(ParkableStringImpl*& new_parkable,
+                        scoped_refptr<StringImpl>&& string,
+                        unsigned hash) {
+    new_parkable = new ParkableStringImpl(
+        std::move(string), ParkableStringImpl::ParkableState::kParkable);
+    DCHECK_EQ(hash, new_parkable->GetHash());
+  }
+};
+
 // static
 ParkableStringManagerDumpProvider*
 ParkableStringManagerDumpProvider::Instance() {
@@ -213,7 +201,7 @@
   base::trace_event::MemoryAllocatorDump* dump =
       pmd->CreateAllocatorDump("parkable_strings");
 
-  Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
+  Statistics stats = ComputeStatistics();
 
   dump->AddScalar("size", "bytes", stats.total_size);
   dump->AddScalar("original_size", "bytes", stats.original_size);
@@ -242,16 +230,37 @@
 scoped_refptr<ParkableStringImpl> ParkableStringManager::Add(
     scoped_refptr<StringImpl>&& string) {
   DCHECK(IsMainThread());
-  StringImpl* raw_ptr = string.get();
-  auto it = unparked_strings_.find(raw_ptr);
-  if (it != unparked_strings_.end())
-    return it->value;
 
-  auto new_parkable_string = base::MakeRefCounted<ParkableStringImpl>(
-      std::move(string), ParkableStringImpl::ParkableState::kParkable);
-  unparked_strings_.insert(raw_ptr, new_parkable_string.get());
   ScheduleAgingTaskIfNeeded();
 
+  scoped_refptr<StringImpl> string_ptr(string);
+  // Hit in either the unparked or parked strings.
+  auto it = unparked_strings_
+                .Find<ParkableStringImplTranslator, scoped_refptr<StringImpl>>(
+                    string_ptr);
+  if (it != unparked_strings_.end())
+    return *it;
+
+  // This is an "expensive hit", as we unparked then discarded the unparked
+  // representation of a string.
+  //
+  // If this is problematic, we can unpark the string for "free" (since the
+  // incoming) string is unparked and has the same content, or change the
+  // interface. Note that at the same time the hit means that we avoided an
+  // expensive compression task.
+  it = parked_strings_
+           .Find<ParkableStringImplTranslator, scoped_refptr<StringImpl>>(
+               string_ptr);
+  if (it != parked_strings_.end())
+    return *it;
+
+  // No hit, new unparked string.
+  auto add_result =
+      unparked_strings_.AddWithTranslator<ParkableStringImplTranslator,
+                                          scoped_refptr<StringImpl>>(
+          std::move(string_ptr));
+  DCHECK(add_result.is_new_entry);
+
   // Lazy registration because registering too early can cause crashes on Linux,
   // see crbug.com/930117, and registering without any strings is pointless
   // anyway.
@@ -276,11 +285,10 @@
     has_posted_unparking_time_accounting_task_ = true;
   }
 
-  return new_parkable_string;
+  return base::AdoptRef(*add_result.stored_value);
 }
 
-void ParkableStringManager::Remove(ParkableStringImpl* string,
-                                   StringImpl* maybe_unparked_string) {
+void ParkableStringManager::Remove(ParkableStringImpl* string) {
   DCHECK(IsMainThread());
   DCHECK(string->may_be_parked());
   if (string->is_parked()) {
@@ -288,38 +296,40 @@
     DCHECK(it != parked_strings_.end());
     parked_strings_.erase(it);
   } else {
-    DCHECK(maybe_unparked_string);
-    auto it = unparked_strings_.find(maybe_unparked_string);
+    auto it = unparked_strings_.find(string);
     DCHECK(it != unparked_strings_.end());
     unparked_strings_.erase(it);
   }
 }
 
-void ParkableStringManager::OnParked(ParkableStringImpl* newly_parked_string,
-                                     StringImpl* previous_unparked_string) {
+void ParkableStringManager::OnParked(ParkableStringImpl* newly_parked_string) {
   DCHECK(IsMainThread());
   DCHECK(newly_parked_string->may_be_parked());
   DCHECK(newly_parked_string->is_parked());
-  auto it = unparked_strings_.find(previous_unparked_string);
+  auto it = unparked_strings_.find(newly_parked_string);
   DCHECK(it != unparked_strings_.end());
+  DCHECK_EQ(*it, newly_parked_string);
   unparked_strings_.erase(it);
   parked_strings_.insert(newly_parked_string);
 }
 
-void ParkableStringManager::OnUnparked(ParkableStringImpl* was_parked_string,
-                                       StringImpl* new_unparked_string,
-                                       base::TimeDelta unparking_time) {
+void ParkableStringManager::OnUnparked(ParkableStringImpl* was_parked_string) {
   DCHECK(IsMainThread());
   DCHECK(was_parked_string->may_be_parked());
   DCHECK(!was_parked_string->is_parked());
   auto it = parked_strings_.find(was_parked_string);
   DCHECK(it != parked_strings_.end());
+  DCHECK_EQ(*it, was_parked_string);
   parked_strings_.erase(it);
-  unparked_strings_.insert(new_unparked_string, was_parked_string);
-  total_unparking_time_ += unparking_time;
+  unparked_strings_.insert(was_parked_string);
   ScheduleAgingTaskIfNeeded();
 }
 
+void ParkableStringManager::RecordUnparkingTime(
+    base::TimeDelta unparking_time) {
+  total_unparking_time_ += unparking_time;
+}
+
 void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
   DCHECK(IsMainThread());
   DCHECK_NE(CompressionMode::kDisabled, GetCompressionMode());
@@ -337,8 +347,7 @@
   // and |unparked_strings_| can contain a few 10s of strings (and we will
   // trigger expensive compression), or this is a subsequent one, and
   // |unparked_strings_| will have few entries.
-  WTF::Vector<ParkableStringImpl*> unparked =
-      GetUnparkedStrings(unparked_strings_);
+  WTF::Vector<ParkableStringImpl*> unparked = GetUnparkedStrings();
 
   for (ParkableStringImpl* str : unparked) {
     str->Park(mode);
@@ -383,14 +392,14 @@
   ParkAllIfRendererBackgrounded(
       ParkableStringImpl::ParkingMode::kIfCompressedDataExists);
 
-  Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
+  Statistics stats = ComputeStatistics();
   RecordMemoryStatistics(stats, "");
 }
 
 void ParkableStringManager::RecordStatisticsAfter5Minutes() const {
   base::UmaHistogramTimes("Memory.ParkableString.MainThreadTime.5min",
                           total_unparking_time_);
-  Statistics stats = ComputeStatistics(unparked_strings_, parked_strings_);
+  Statistics stats = ComputeStatistics();
   RecordMemoryStatistics(stats, ".5min");
 }
 
@@ -401,9 +410,7 @@
   TRACE_EVENT0("blink", "ParkableStringManager::AgeStringsAndPark");
   has_pending_aging_task_ = false;
 
-  WTF::Vector<ParkableStringImpl*> unparked =
-      GetUnparkedStrings(unparked_strings_);
-
+  WTF::Vector<ParkableStringImpl*> unparked = GetUnparkedStrings();
   bool can_make_progress = false;
   for (ParkableStringImpl* str : unparked) {
     if (str->MaybeAgeOrParkString() ==
@@ -454,11 +461,52 @@
   // synchronously (and no longer in |unparked_strings_|), or being parked and
   // purging is a no-op.
   if (!IsRendererBackgrounded()) {
-    for (ParkableStringImpl* str : unparked_strings_.Values())
+    for (ParkableStringImpl* str : unparked_strings_)
       str->PurgeMemory();
   }
 }
 
+Vector<ParkableStringImpl*> ParkableStringManager::GetUnparkedStrings() const {
+  WTF::Vector<ParkableStringImpl*> unparked;
+  unparked.ReserveCapacity(unparked_strings_.size());
+  for (ParkableStringImpl* str : unparked_strings_)
+    unparked.push_back(str);
+
+  return unparked;
+}
+
+ParkableStringManager::Statistics ParkableStringManager::ComputeStatistics()
+    const {
+  ParkableStringManager::Statistics stats = {};
+
+  for (ParkableStringImpl* str : unparked_strings_) {
+    size_t size = str->CharactersSizeInBytes();
+    stats.original_size += size;
+    stats.uncompressed_size += size;
+    stats.metadata_size += sizeof(ParkableStringImpl);
+
+    if (str->has_compressed_data())
+      stats.overhead_size += str->compressed_size();
+  }
+
+  for (ParkableStringImpl* str : parked_strings_) {
+    size_t size = str->CharactersSizeInBytes();
+    stats.compressed_original_size += size;
+    stats.original_size += size;
+    stats.compressed_size += str->compressed_size();
+    stats.metadata_size += sizeof(ParkableStringImpl);
+  }
+
+  stats.total_size = stats.uncompressed_size + stats.compressed_size +
+                     stats.metadata_size + stats.overhead_size;
+  size_t memory_footprint = stats.compressed_size + stats.uncompressed_size +
+                            stats.metadata_size + stats.overhead_size;
+  stats.savings_size =
+      stats.original_size - static_cast<int64_t>(memory_footprint);
+
+  return stats;
+}
+
 void ParkableStringManager::ResetForTesting() {
   backgrounded_ = false;
   waiting_to_record_stats_ = false;
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index b4ba153..6191c39 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -51,6 +51,8 @@
   USING_FAST_MALLOC(ParkableStringManager);
 
  public:
+  struct Statistics;
+
   static ParkableStringManager& Instance();
   ~ParkableStringManager();
 
@@ -73,12 +75,14 @@
  private:
   friend class ParkableString;
   friend class ParkableStringImpl;
+  struct ParkableStringImplHash;
+  struct ParkableStringImplTranslator;
 
   scoped_refptr<ParkableStringImpl> Add(scoped_refptr<StringImpl>&&);
-  void Remove(ParkableStringImpl*, StringImpl*);
+  void Remove(ParkableStringImpl*);
 
-  void OnParked(ParkableStringImpl*, StringImpl*);
-  void OnUnparked(ParkableStringImpl*, StringImpl*, base::TimeDelta);
+  void OnParked(ParkableStringImpl*);
+  void OnUnparked(ParkableStringImpl*);
 
   void ParkAll(ParkableStringImpl::ParkingMode mode);
   void ParkAllIfRendererBackgrounded(ParkableStringImpl::ParkingMode mode);
@@ -86,6 +90,9 @@
   void RecordStatisticsAfter5Minutes() const;
   void AgeStringsAndPark();
   void ScheduleAgingTaskIfNeeded();
+  void RecordUnparkingTime(base::TimeDelta);
+  Vector<ParkableStringImpl*> GetUnparkedStrings() const;
+  Statistics ComputeStatistics() const;
 
   void ResetForTesting();
 
@@ -98,9 +105,9 @@
   bool has_posted_unparking_time_accounting_task_;
   bool did_register_memory_pressure_listener_;
   base::TimeDelta total_unparking_time_;
-  HashMap<StringImpl*, ParkableStringImpl*, PtrHash<StringImpl>>
-      unparked_strings_;
-  HashSet<ParkableStringImpl*, PtrHash<ParkableStringImpl>> parked_strings_;
+
+  WTF::HashSet<ParkableStringImpl*, ParkableStringImplHash> unparked_strings_;
+  WTF::HashSet<ParkableStringImpl*, ParkableStringImplHash> parked_strings_;
 
   friend class ParkableStringTestBase;
   FRIEND_TEST_ALL_PREFIXES(ParkableStringTest, SynchronousCompression);
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index 6bc9a1f..9ab6b3f 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -29,8 +29,8 @@
 // Update if the assertion in the |CheckCompressedSize()| test fails.
 constexpr size_t kCompressedSize = 55;
 
-String MakeLargeString() {
-  std::vector<char> data(kSizeKb * 1000, 'a');
+String MakeLargeString(char c = 'a') {
+  std::vector<char> data(kSizeKb * 1000, c);
   return String(data.data(), data.size()).ReleaseImpl();
 }
 
@@ -100,7 +100,7 @@
     // Checking that there are no other strings, to make sure this doesn't
     // cause side-effects.
     CHECK_EQ(0u, manager.Size());
-    ParkableString parkable(MakeLargeString().ReleaseImpl());
+    ParkableString parkable(MakeLargeString('a').ReleaseImpl());
     manager.SetRendererBackgrounded(true);
     EXPECT_FALSE(parkable.Impl()->is_parked());
     WaitForDelayedParking();
@@ -166,18 +166,34 @@
   EXPECT_EQ(copy.Impl(), parkable_abc.Impl());
 }
 
+TEST_F(ParkableStringTest, Equality) {
+  ParkableString abc(String("abc").ReleaseImpl());
+  ParkableString abc2(String("abc").ReleaseImpl());
+
+  EXPECT_NE(abc.ToString().Impl(), abc2.ToString().Impl());
+  EXPECT_TRUE(abc.Impl()->Equal(*abc2.Impl()));
+
+  // Should not crash. Unlocking poisons the string with ASAN, checks that we
+  // unpoison it correctly when calling Equal().
+  ParkableString parkable(MakeLargeString('a').ReleaseImpl());
+  parkable.Lock();
+  parkable.Unlock();
+  ParkableString parkable2(MakeLargeString('a').ReleaseImpl());
+  EXPECT_EQ(parkable.Impl(), parkable2.Impl());
+}
+
 TEST_F(ParkableStringTest, Park) {
   base::HistogramTester histogram_tester;
 
   {
-    ParkableString parkable(MakeLargeString().ReleaseImpl());
+    ParkableString parkable(MakeLargeString('a').ReleaseImpl());
     EXPECT_TRUE(parkable.may_be_parked());
     EXPECT_FALSE(parkable.Impl()->is_parked());
     EXPECT_TRUE(ParkAndWait(parkable));
     EXPECT_TRUE(parkable.Impl()->is_parked());
   }
 
-  String large_string = MakeLargeString();
+  String large_string = MakeLargeString('b');
   ParkableString parkable(large_string.Impl());
   EXPECT_TRUE(parkable.may_be_parked());
   // Not the only one to have a reference to the string.
@@ -191,7 +207,7 @@
   histogram_tester.ExpectTotalCount("Memory.MovableStringParkingAction", 2);
 
   {
-    ParkableString parkable(MakeLargeString().ReleaseImpl());
+    ParkableString parkable(MakeLargeString('c').ReleaseImpl());
     EXPECT_TRUE(parkable.may_be_parked());
     EXPECT_FALSE(parkable.Impl()->is_parked());
     EXPECT_TRUE(
@@ -204,6 +220,28 @@
   }
 }
 
+TEST_F(ParkableStringTest, EqualityNoUnparking) {
+  String large_string = MakeLargeString();
+  String copy = large_string.IsolatedCopy();
+  EXPECT_NE(large_string.Impl(), copy.Impl());
+
+  ParkableString parkable(large_string.Impl());
+  large_string = String();
+
+  EXPECT_TRUE(parkable.may_be_parked());
+  EXPECT_FALSE(parkable.Impl()->is_parked());
+  EXPECT_TRUE(ParkAndWait(parkable));
+  EXPECT_TRUE(parkable.Impl()->is_parked());
+
+  ParkableString parkable_copy(copy.Impl());
+  EXPECT_EQ(parkable_copy.Impl(), parkable.Impl());  // De-duplicated.
+  EXPECT_TRUE(parkable_copy.Impl()->Equal(*parkable.Impl()));
+  EXPECT_TRUE(parkable.Impl()->is_parked());
+  EXPECT_TRUE(parkable_copy.Impl()->is_parked());
+
+  EXPECT_EQ(1u, ParkableStringManager::Instance().Size());
+}
+
 TEST_F(ParkableStringTest, AbortParking) {
   {
     ParkableString parkable(MakeLargeString().ReleaseImpl());
@@ -420,8 +458,8 @@
 TEST_F(ParkableStringTest, ManagerMultipleStrings) {
   base::HistogramTester histogram_tester;
 
-  ParkableString parkable(MakeLargeString().Impl());
-  ParkableString parkable2(MakeLargeString().Impl());
+  ParkableString parkable(MakeLargeString('a').Impl());
+  ParkableString parkable2(MakeLargeString('b').Impl());
 
   auto& manager = ParkableStringManager::Instance();
   EXPECT_EQ(2u, manager.Size());
@@ -435,19 +473,27 @@
   copy = ParkableString();
   EXPECT_EQ(0u, manager.Size());
 
-  String str = MakeLargeString();
+  String str = MakeLargeString('c');
   ParkableString parkable3(str.Impl());
   EXPECT_EQ(1u, manager.Size());
-  // De-duplicated.
+  // De-duplicated with the same underlying StringImpl.
   ParkableString other_parkable3(str.Impl());
   EXPECT_EQ(1u, manager.Size());
   EXPECT_EQ(parkable3.Impl(), other_parkable3.Impl());
 
+  {
+    // De-duplicated with a different StringImpl but the same content.
+    ParkableString other_parkable3_different_string(
+        MakeLargeString('c').ReleaseImpl());
+    EXPECT_EQ(1u, manager.Size());
+    EXPECT_EQ(parkable3.Impl(), other_parkable3_different_string.Impl());
+  }
+
   // If all the references to a string are internal, park it.
   str = String();
   // This string is not parkable, bur should still be in size and count
   // histograms.
-  ParkableString parkable4(MakeLargeString().Impl());
+  ParkableString parkable4(MakeLargeString('d').Impl());
   String parkable4_content = parkable4.ToString();
 
   int parking_count = 0;
@@ -642,7 +688,7 @@
 
 TEST_F(ParkableStringTest, OnPurgeMemoryInForeground) {
   ParkableString parkable1 = CreateAndParkAll();
-  ParkableString parkable2(MakeLargeString().ReleaseImpl());
+  ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
 
   // Park everything.
   ParkableStringManager::Instance().SetRendererBackgrounded(true);
@@ -675,8 +721,8 @@
   using testing::Eq;
 
   auto& manager = ParkableStringManager::Instance();
-  ParkableString parkable1(MakeLargeString().ReleaseImpl());
-  ParkableString parkable2(MakeLargeString().ReleaseImpl());
+  ParkableString parkable1(MakeLargeString('a').ReleaseImpl());
+  ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
   // Not reported in stats below.
   ParkableString parkable3(String("short string, not parkable").ReleaseImpl());
 
@@ -838,7 +884,7 @@
 }
 
 TEST_F(ParkableStringForegroundParkingTest, AgingTicksStopsWithNoProgress) {
-  ParkableString parkable(MakeLargeString().ReleaseImpl());
+  ParkableString parkable(MakeLargeString('a').ReleaseImpl());
   String retained = parkable.ToString();
 
   EXPECT_GT(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
@@ -846,7 +892,7 @@
   // The only string is referenced externally, nothing aging can change.
   CheckOnlyCpuCostTaskRemains();
 
-  ParkableString parkable2(MakeLargeString().ReleaseImpl());
+  ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
   WaitForAging();
   EXPECT_GT(scoped_task_environment_.GetPendingMainThreadTaskCount(), 0u);
   WaitForAging();
@@ -860,8 +906,8 @@
 }
 
 TEST_F(ParkableStringForegroundParkingTest, OnlyOneAgingTask) {
-  ParkableString parkable1(MakeLargeString().ReleaseImpl());
-  ParkableString parkable2(MakeLargeString().ReleaseImpl());
+  ParkableString parkable1(MakeLargeString('a').ReleaseImpl());
+  ParkableString parkable2(MakeLargeString('b').ReleaseImpl());
 
   // Park both, and wait for the tick to stop.
   WaitForAging();
@@ -924,8 +970,10 @@
   ParkAndWait(parkable);
   for (int i = 0; i < 10; ++i) {
     parkable.ToString();
+    ASSERT_FALSE(parkable.Impl()->is_parked());
     WaitForAging();
     WaitForAging();
+    ASSERT_TRUE(parkable.Impl()->is_parked());
     CheckOnlyCpuCostTaskRemains();
   }
   const size_t compressed_size = parkable.Impl()->compressed_size();
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc
index dc13e387..c80fcaa 100644
--- a/third_party/blink/renderer/platform/exported/web_url_response.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -120,12 +120,11 @@
   resource_response_->SetMimeType(mime_type);
 }
 
-long long WebURLResponse::ExpectedContentLength() const {
+int64_t WebURLResponse::ExpectedContentLength() const {
   return resource_response_->ExpectedContentLength();
 }
 
-void WebURLResponse::SetExpectedContentLength(
-    long long expected_content_length) {
+void WebURLResponse::SetExpectedContentLength(int64_t expected_content_length) {
   resource_response_->SetExpectedContentLength(expected_content_length);
 }
 
@@ -162,8 +161,8 @@
   return resource_response_->HttpStatusText();
 }
 
-void WebURLResponse::SetHTTPStatusText(const WebString& http_status_text) {
-  resource_response_->SetHTTPStatusText(http_status_text);
+void WebURLResponse::SetHttpStatusText(const WebString& http_status_text) {
+  resource_response_->SetHttpStatusText(http_status_text);
 }
 
 WebString WebURLResponse::HttpHeaderField(const WebString& name) const {
@@ -194,11 +193,11 @@
     visitor->VisitHeader(it->key, it->value);
 }
 
-long long WebURLResponse::AppCacheID() const {
+int64_t WebURLResponse::AppCacheID() const {
   return resource_response_->AppCacheID();
 }
 
-void WebURLResponse::SetAppCacheID(long long app_cache_id) {
+void WebURLResponse::SetAppCacheID(int64_t app_cache_id) {
   resource_response_->SetAppCacheID(app_cache_id);
 }
 
@@ -376,7 +375,7 @@
   resource_response_->SetRemotePort(remote_port);
 }
 
-void WebURLResponse::SetEncodedDataLength(long long length) {
+void WebURLResponse::SetEncodedDataLength(int64_t length) {
   resource_response_->SetEncodedDataLength(length);
 }
 
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 04a895c..6d1e7e8 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
@@ -77,7 +77,7 @@
 
 constexpr char kTestResourceFilename[] = "white-1x1.png";
 constexpr char kTestResourceMimeType[] = "image/png";
-constexpr int kTestResourceSize = 103;  // size of white-1x1.png
+constexpr uint32_t kTestResourceSize = 103;  // size of white-1x1.png
 
 void RegisterMockedURLLoadWithCustomResponse(const KURL& url,
                                              const ResourceResponse& response) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index f41f3bf..b954c46f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -182,7 +182,7 @@
   return http_status_text_;
 }
 
-void ResourceResponse::SetHTTPStatusText(const AtomicString& status_text) {
+void ResourceResponse::SetHttpStatusText(const AtomicString& status_text) {
   http_status_text_ = status_text;
 }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index c082dcc..c795043 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -202,7 +202,7 @@
   void SetHttpStatusCode(int);
 
   const AtomicString& HttpStatusText() const;
-  void SetHTTPStatusText(const AtomicString&);
+  void SetHttpStatusText(const AtomicString&);
 
   const AtomicString& HttpHeaderField(const AtomicString& name) const;
   void SetHTTPHeaderField(const AtomicString& name, const AtomicString& value);
@@ -423,7 +423,7 @@
 
   KURL current_request_url_;
   AtomicString mime_type_;
-  long long expected_content_length_ = 0;
+  int64_t expected_content_length_ = 0;
   AtomicString text_encoding_name_;
 
   unsigned connection_id_ = 0;
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index e2c4e8df..de4c5ba 100644
--- a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -29,7 +29,7 @@
   MockFetchContext() = default;
   ~MockFetchContext() override = default;
 
-  long long GetTransferSize() const { return transfer_size_; }
+  uint64_t GetTransferSize() const { return transfer_size_; }
 
   void CountUsage(mojom::WebFeature) const override {}
   void CountDeprecation(mojom::WebFeature) const override {}
@@ -74,7 +74,7 @@
   }
 
  private:
-  long long transfer_size_ = -1;
+  uint64_t transfer_size_ = 0;
   base::Optional<ResourceRequest> will_send_request_;
 };
 
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index 4c17940..ea6a911a 100644
--- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -22,6 +22,7 @@
   "//third_party/blink/renderer/platform/mojo/security_origin.typemap",
   "//third_party/blink/renderer/platform/mojo/string.typemap",
   "//third_party/blink/renderer/platform/mojo/time.typemap",
+  "//third_party/blink/renderer/platform/network/encoded_form_data.typemap",
   "//third_party/blink/renderer/platform/network/http_request_headers.typemap",
   "//third_party/blink/public/platform/modules/bluetooth/bluetooth.typemap",
   "//third_party/blink/public/common/manifest/display_mode.typemap",
diff --git a/third_party/blink/renderer/platform/network/BUILD.gn b/third_party/blink/renderer/platform/network/BUILD.gn
index 27e11b8..d895fca 100644
--- a/third_party/blink/renderer/platform/network/BUILD.gn
+++ b/third_party/blink/renderer/platform/network/BUILD.gn
@@ -31,6 +31,8 @@
     "content_security_policy_response_headers.h",
     "encoded_form_data.cc",
     "encoded_form_data.h",
+    "encoded_form_data_mojom_traits.cc",
+    "encoded_form_data_mojom_traits.h",
     "form_data_encoder.cc",
     "form_data_encoder.h",
     "header_field_tokenizer.cc",
@@ -88,6 +90,8 @@
 
   deps = [
     "//testing/gtest",
+  ]
+  public_deps = [
     "//third_party/blink/renderer/platform:platform",
   ]
 }
diff --git a/third_party/blink/renderer/platform/network/DEPS b/third_party/blink/renderer/platform/network/DEPS
index 17d7eb3..b2afd512 100644
--- a/third_party/blink/renderer/platform/network/DEPS
+++ b/third_party/blink/renderer/platform/network/DEPS
@@ -16,6 +16,7 @@
     # For URLRequestDataJob::BuildResponse().
     "+net/url_request/url_request_data_job.h",
 
+    "+services/network/public/cpp/features.h",
     "+third_party/blink/renderer/platform/blob/blob_data.h",
     "+third_party/blink/renderer/platform/cross_thread_copier.h",
     "+third_party/blink/renderer/platform/cross_thread_functional.h",
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data.typemap b/third_party/blink/renderer/platform/network/encoded_form_data.typemap
new file mode 100644
index 0000000..8e0e849
--- /dev/null
+++ b/third_party/blink/renderer/platform/network/encoded_form_data.typemap
@@ -0,0 +1,10 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//services/network/public/mojom/url_loader.mojom"
+public_headers =
+    [ "//third_party/blink/renderer/platform/network/encoded_form_data.h" ]
+traits_headers = [ "//third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h" ]
+type_mappings =
+    [ "network.mojom.DataElement = blink::FormDataElement[move_only]" ]
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc
new file mode 100644
index 0000000..f66e122
--- /dev/null
+++ b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.cc
@@ -0,0 +1,166 @@
+// 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 <utility>
+
+#include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h"
+
+#include "mojo/public/cpp/base/file_mojom_traits.h"
+#include "mojo/public/cpp/base/file_path_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
+#include "mojo/public/cpp/bindings/string_traits_wtf.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
+#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/platform/platform.h"
+
+namespace mojo {
+
+// static
+network::mojom::DataElementType
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::type(
+    const blink::FormDataElement& data) {
+  switch (data.type_) {
+    case blink::FormDataElement::kData:
+      return network::mojom::DataElementType::kBytes;
+    case blink::FormDataElement::kEncodedFile:
+      return network::mojom::DataElementType::kFile;
+    case blink::FormDataElement::kEncodedBlob: {
+      if (data.optional_blob_data_handle_)
+        return network::mojom::DataElementType::kDataPipe;
+      return network::mojom::DataElementType::kBlob;
+    }
+    case blink::FormDataElement::kDataPipe:
+      return network::mojom::DataElementType::kDataPipe;
+  }
+  NOTREACHED();
+  return network::mojom::DataElementType::kUnknown;
+}
+
+// static
+base::span<const uint8_t>
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::buf(
+    const blink::FormDataElement& data) {
+  return base::make_span(reinterpret_cast<const uint8_t*>(data.data_.data()),
+                         data.data_.size());
+}
+
+// static
+base::File
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::file(
+    const blink::FormDataElement& data) {
+  return base::File();
+}
+
+// static
+base::FilePath
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::path(
+    const blink::FormDataElement& data) {
+  return base::FilePath::FromUTF8Unsafe(
+      std::string(data.filename_.Utf8().data()));
+}
+
+// static
+network::mojom::blink::DataPipeGetterPtrInfo
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
+    data_pipe_getter(const blink::FormDataElement& data) {
+  if (data.type_ == blink::FormDataElement::kDataPipe) {
+    if (!data.data_pipe_getter_)
+      return nullptr;
+    network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
+    (*data.data_pipe_getter_->GetPtr())
+        ->Clone(mojo::MakeRequest(&data_pipe_getter));
+    return data_pipe_getter.PassInterface();
+  }
+  if (data.type_ == blink::FormDataElement::kEncodedBlob) {
+    if (data.optional_blob_data_handle_) {
+      blink::mojom::blink::BlobPtr blob_ptr(blink::mojom::blink::BlobPtrInfo(
+          data.optional_blob_data_handle_->CloneBlobPtr()
+              .PassInterface()
+              .PassHandle(),
+          blink::mojom::blink::Blob::Version_));
+      network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr;
+      blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr));
+      return data_pipe_getter_ptr.PassInterface();
+    }
+  }
+  return nullptr;
+}
+
+// static
+base::Time
+StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
+    expected_modification_time(const blink::FormDataElement& data) {
+  if (data.type_ == blink::FormDataElement::kEncodedFile)
+    return base::Time::FromDoubleT(data.expected_file_modification_time_);
+  return base::Time();
+}
+
+// static
+bool StructTraits<network::mojom::DataElementDataView, blink::FormDataElement>::
+    Read(network::mojom::DataElementDataView data,
+         blink::FormDataElement* out) {
+  network::mojom::DataElementType data_type;
+  if (!data.ReadType(&data_type)) {
+    return false;
+  }
+  out->file_start_ = data.offset();
+  out->file_length_ = data.length();
+
+  switch (data_type) {
+    case network::mojom::DataElementType::kBytes: {
+      out->type_ = blink::FormDataElement::kData;
+      // TODO:(richard.li) Delete this workaround when type of
+      // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t>
+      WTF::Vector<uint8_t> buf;
+      if (!data.ReadBuf(&buf)) {
+        return false;
+      }
+      out->data_.AppendRange(buf.begin(), buf.end());
+      break;
+    }
+    case network::mojom::DataElementType::kFile: {
+      out->type_ = blink::FormDataElement::kEncodedFile;
+      base::FilePath file_path;
+      base::Time expected_time;
+      if (!data.ReadPath(&file_path) ||
+          !data.ReadExpectedModificationTime(&expected_time)) {
+        return false;
+      }
+      out->expected_file_modification_time_ = expected_time.ToDoubleT();
+      out->filename_ =
+          WTF::String(file_path.value().data(), file_path.value().size());
+      break;
+    }
+    case network::mojom::DataElementType::kBlob: {
+      out->type_ = blink::FormDataElement::kEncodedBlob;
+      if (!data.ReadBlobUuid(&out->blob_uuid_)) {
+        return false;
+      }
+      break;
+    }
+    case network::mojom::DataElementType::kDataPipe: {
+      out->type_ = blink::FormDataElement::kDataPipe;
+      auto data_pipe_ptr_info = data.TakeDataPipeGetter<
+          network::mojom::blink::DataPipeGetterPtrInfo>();
+      DCHECK(data_pipe_ptr_info.is_valid());
+
+      network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
+      data_pipe_getter.Bind(std::move(data_pipe_ptr_info));
+      out->data_pipe_getter_ =
+          base::MakeRefCounted<blink::WrappedDataPipeGetter>(
+              std::move(data_pipe_getter));
+      break;
+    }
+    case network::mojom::DataElementType::kUnknown:
+    case network::mojom::DataElementType::kChunkedDataPipe:
+    case network::mojom::DataElementType::kRawFile:
+      NOTREACHED();
+      return false;
+  }
+  return true;
+}
+
+}  // namespace mojo
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
new file mode 100644
index 0000000..313a8d43
--- /dev/null
+++ b/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
+
+#include <string>
+
+#include "services/network/public/mojom/url_loader.mojom-blink.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+
+namespace mojo {
+
+template <>
+struct PLATFORM_EXPORT
+    StructTraits<network::mojom::DataElementDataView, blink::FormDataElement> {
+  static network::mojom::DataElementType type(
+      const blink::FormDataElement& data);
+
+  static base::span<const uint8_t> buf(const blink::FormDataElement& data);
+
+  static base::File file(const blink::FormDataElement& data);
+
+  static base::FilePath path(const blink::FormDataElement& data);
+
+  static const WTF::String& blob_uuid(const blink::FormDataElement& data) {
+    return data.blob_uuid_;
+  }
+
+  static network::mojom::blink::DataPipeGetterPtrInfo data_pipe_getter(
+      const blink::FormDataElement& data);
+
+  static network::mojom::blink::ChunkedDataPipeGetterPtrInfo
+  chunked_data_pipe_getter(const blink::FormDataElement& data) {
+    return nullptr;
+  }
+
+  static uint64_t offset(const blink::FormDataElement& data) {
+    return data.file_start_;
+  }
+
+  static uint64_t length(const blink::FormDataElement& data) {
+    if (data.type_ == blink::FormDataElement::kEncodedBlob &&
+        data.optional_blob_data_handle_) {
+      return data.optional_blob_data_handle_->size();
+    }
+    return data.file_length_;
+  }
+
+  static base::Time expected_modification_time(
+      const blink::FormDataElement& data);
+
+  static bool Read(network::mojom::DataElementDataView data,
+                   blink::FormDataElement* out);
+};
+
+}  // namespace mojo
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
index 3349b1cb..5619caa 100644
--- a/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
+++ b/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
@@ -2,6 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h"
+
+#include "base/sequenced_task_runner.h"
+#include "base/test/scoped_task_environment.h"
+#include "mojo/public/cpp/base/file_mojom_traits.h"
+#include "mojo/public/cpp/base/file_path_mojom_traits.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/bindings/string_traits_wtf.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "services/network/public/mojom/url_loader.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -94,6 +105,62 @@
   }
 }
 
-}  // namespace
+TEST(EncodedFormDataMojomTraitsTest, Roundtrips_FormDataElement) {
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
+  FormDataElement original1;
+  original1.type_ = blink::FormDataElement::kData;
+  original1.data_ = {'a', 'b', 'c', 'd'};
+  FormDataElement copied1;
+  EXPECT_TRUE(
+      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
+          &original1, &copied1));
+  EXPECT_EQ(original1.type_, copied1.type_);
+  EXPECT_EQ(original1.data_, copied1.data_);
+
+  FormDataElement original2;
+  original2.type_ = blink::FormDataElement::kEncodedFile;
+  original2.file_start_ = 0;
+  original2.file_length_ = 4;
+  original2.filename_ = "file.name";
+  original2.expected_file_modification_time_ = base::Time::Now().ToDoubleT();
+  FormDataElement copied2;
+  EXPECT_TRUE(
+      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
+          &original2, &copied2));
+  EXPECT_EQ(original2.type_, copied2.type_);
+  EXPECT_EQ(original2.file_start_, copied2.file_start_);
+  EXPECT_EQ(original2.file_length_, copied2.file_length_);
+  EXPECT_EQ(original2.filename_, copied2.filename_);
+  EXPECT_EQ(original2.expected_file_modification_time_,
+            copied2.expected_file_modification_time_);
+
+  FormDataElement original3;
+  original3.type_ = blink::FormDataElement::kEncodedBlob;
+  original3.blob_uuid_ = "uuid-test";
+  mojo::MessagePipe pipe;
+  original3.optional_blob_data_handle_ = BlobDataHandle::Create(
+      original3.blob_uuid_, "type-test", 100,
+      mojom::blink::BlobPtrInfo(std::move(pipe.handle0), 0));
+  FormDataElement copied3;
+  EXPECT_TRUE(
+      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
+          &original3, &copied3));
+  EXPECT_EQ(copied3.type_, blink::FormDataElement::kDataPipe);
+
+  FormDataElement original4;
+  original4.type_ = blink::FormDataElement::kDataPipe;
+  network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
+  auto request = mojo::MakeRequest(&data_pipe_getter);
+  original4.data_pipe_getter_ =
+      base::MakeRefCounted<blink::WrappedDataPipeGetter>(
+          std::move(data_pipe_getter));
+  FormDataElement copied4;
+  EXPECT_TRUE(
+      mojo::test::SerializeAndDeserialize<network::mojom::blink::DataElement>(
+          &original4, &copied4));
+  EXPECT_TRUE(copied4.data_pipe_getter_);
+}
+
+}  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/network/network_utils.cc b/third_party/blink/renderer/platform/network/network_utils.cc
index 19ea819..f5b9f8b 100644
--- a/third_party/blink/renderer/platform/network/network_utils.cc
+++ b/third_party/blink/renderer/platform/network/network_utils.cc
@@ -84,7 +84,7 @@
   auto buffer = SharedBuffer::Create(data_string.data(), data_string.size());
   ResourceResponse response;
   response.SetHttpStatusCode(200);
-  response.SetHTTPStatusText("OK");
+  response.SetHttpStatusText("OK");
   response.SetCurrentRequestUrl(url);
   response.SetMimeType(WebString::FromUTF8(utf8_mime_type));
   response.SetExpectedContentLength(buffer->size());
diff --git a/third_party/blink/renderer/platform/testing/weburl_loader_mock.h b/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
index 88e6049..8b031ca 100644
--- a/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
+++ b/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
@@ -21,7 +21,7 @@
 class WebURLRequest;
 class WebURLResponse;
 
-const int kRedirectResponseOverheadBytes = 300;
+const uint32_t kRedirectResponseOverheadBytes = 300;
 
 // A simple class for mocking WebURLLoader.
 // If the WebURLLoaderMockFactory it is associated with has been configured to
diff --git a/third_party/blink/renderer/platform/wtf/hash_functions.h b/third_party/blink/renderer/platform/wtf/hash_functions.h
index dd444c4c..9b9ec92a 100644
--- a/third_party/blink/renderer/platform/wtf/hash_functions.h
+++ b/third_party/blink/renderer/platform/wtf/hash_functions.h
@@ -200,7 +200,7 @@
 
 template <typename T>
 struct DefaultHashImpl<T, true> {
-  using Hash = IntHash<typename std::make_unsigned<T>::type>;
+  using Hash = IntHash<T>;
 };
 
 // Canonical implementation of DefaultHash.
diff --git a/third_party/blink/renderer/platform/wtf/hash_set_test.cc b/third_party/blink/renderer/platform/wtf/hash_set_test.cc
index c206627..5102146 100644
--- a/third_party/blink/renderer/platform/wtf/hash_set_test.cc
+++ b/third_party/blink/renderer/platform/wtf/hash_set_test.cc
@@ -405,8 +405,11 @@
 TEST(HashSetTest, HasTraitsForEnum) {
   // Ensure that enum hash keys are buildable.
   HashSet<TestEnum> set1;
+  set1.insert(TestEnum::kItem0);
   HashSet<TestEnumClass> set2;
+  set2.insert(TestEnumClass::kItem0);
   HashSet<std::pair<TestEnum, TestEnumClass>> set3;
+  set3.insert(std::make_pair(TestEnum::kItem0, TestEnumClass::kItem0));
 }
 
 static_assert(!IsTraceable<HashSet<int>>::value,
diff --git a/third_party/blink/tools/blinkpy/style/checkers/cpp.py b/third_party/blink/tools/blinkpy/style/checkers/cpp.py
index 7d3936c..90c55040 100644
--- a/third_party/blink/tools/blinkpy/style/checkers/cpp.py
+++ b/third_party/blink/tools/blinkpy/style/checkers/cpp.py
@@ -1866,7 +1866,7 @@
     # FIXME: figure out if they're using default arguments in fn proto.
 
     # Check if they're using a precise-width integer type.
-    matched = search(r'\b((un)?signed\s+)?short\b', line)
+    matched = search(r'\b((un)?signed\s+)?(short|long\s+long)\b', line)
     if matched:
         error(line_number, 'runtime/int', 1,
               'Use a precise-width integer type from <stdint.h> or <cstdint>'
diff --git a/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py b/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
index 36d83532..1e16baa 100644
--- a/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
+++ b/third_party/blink/tools/blinkpy/style/checkers/cpp_unittest.py
@@ -463,6 +463,10 @@
         self.assert_lint('uint16_t unsignedshort = 1', '')
         self.assert_lint('signed  short a = 1', errmsg % 'signed  short  [runtime/int] [1]')
         self.assert_lint('short a = 1', errmsg % 'short  [runtime/int] [1]')
+        self.assert_lint('unsigned   long long a = 1', errmsg % 'unsigned   long long  [runtime/int] [1]')
+        self.assert_lint('signed long   long a = 1', errmsg % 'signed long   long  [runtime/int] [1]')
+        self.assert_lint('long long a = 1', errmsg % 'long long  [runtime/int] [1]')
+        self.assert_lint('uint64_t longlong = 1', '')
 
     # Test C-style cast cases.
     def test_cstyle_cast(self):
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 467cbc9..51b38dc 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2445,8 +2445,6 @@
 crbug.com/807152 vr/VRDisplay_rAF_fires_with_window_rAF.html [ Pass Failure ]
 crbug.com/813697 vr/getFrameData_oneframeupdate.html [ Pass Failure ]
 
-crbug.com/806357 [ Win Debug ] virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure ]
-
 crbug.com/346473  fast/events/drag-on-mouse-move-cancelled.html [ Failure ]
 crbug.com/346473  virtual/mouseevent_fractional/fast/events/drag-on-mouse-move-cancelled.html [ Failure ]
 crbug.com/346473  virtual/user-activation-v2/fast/events/drag-on-mouse-move-cancelled.html [ Failure ]
@@ -5596,7 +5594,6 @@
 crbug.com/891510 [ Win7 ] fast/dom/inline-event-attributes-release.html [ Failure Pass ]
 
 # Sheriff 2018-10-09
-crbug.com/806357 [ Linux ] virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure ]
 crbug.com/893869 [ Linux ] css3/masking/mask-repeat-space-padding.html [ Failure Pass ]
 crbug.com/893869 [ Mac ] css3/masking/mask-repeat-space-padding.html [ Failure Pass ]
 
@@ -6073,6 +6070,13 @@
 crbug.com/940136 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth.html [ Pass Failure ]
 
 # Test was blocking WPT importer
-crbug.com/941471 external/wpt/css/css-transforms/transform-flattening-001.html [ Pass Failure ]
+crbug.com/941471 external/wpt/css/css-transforms/transform-flattening-001.html [ Pass Failure Crash ]
 
 crbug.com/940829 external/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ Timeout Pass ]
+
+# Sheriff 2019-03-14
+crbug.com/836242 [ Linux ] fast/loader/reload-zero-byte-plugin.html [ Pass Failure ]
+crbug.com/836242 [ Mac ] fast/loader/reload-zero-byte-plugin.html [ Pass Failure ]
+crbug.com/836242 [ Win ] fast/loader/reload-zero-byte-plugin.html [ Pass Failure ]
+crbug.com/806357 [ Linux Win ] virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure ]
+crbug.com/941931 [ Linux Win ] http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor-expected.html
new file mode 100644
index 0000000..87d517d
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor-expected.html
@@ -0,0 +1,23 @@
+<!doctype HTML>
+
+<!--
+Commit a locked element that was previously under a display:none tree.
+-->
+
+<style>
+#container {
+  width: 200px;
+  height: 200px;
+  background: green;
+}
+
+#locked {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container""><div id="locked"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor.html b/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor.html
new file mode 100644
index 0000000..58cf20aa
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/display-none-ancestor.html
@@ -0,0 +1,55 @@
+<!doctype HTML>
+
+<!--
+Commit a locked element that was previously under a display:none tree.
+-->
+
+<style>
+#container {
+  width: 200px;
+  height: 200px;
+  background: green;
+}
+
+#locked {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+</style>
+
+<div id="log"></div>
+<div id="container" style="display:none;"></div>
+
+<script>
+// TODO(rakina): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let locked = document.createElement("div");
+  locked.id = "locked";
+  locked.displayLock.acquire({ timeout: Infinity }).then(() => {
+    container.appendChild(locked);
+    locked.displayLock.update().then(() => {
+      // Make container visible & force style + layout.
+      container.style = "display:block";
+      container.offsetTop;
+
+      locked.displayLock.commit().then(
+        () => { finishTest("PASS"); },
+        (e) => { finishTest("FAIL " + e.message); });
+      });
+    });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https-expected.txt b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https-expected.txt
index c245e7e..e7f474c 100644
--- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 112 tests; 96 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 112 tests; 108 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Setup audio MediaStreamTrack getCapabilities() test for volume
 PASS Setup audio MediaStreamTrack getCapabilities() test for sampleRate
 PASS Setup audio MediaStreamTrack getCapabilities() test for sampleSize
@@ -38,8 +38,8 @@
 PASS Setup video InputDeviceInfo getCapabilities() test for groupId
 FAIL Audio track getCapabilities() volume property present. assert_true: expected true got false
 FAIL Audio track getCapabilities() volume properly supported. assert_equals: expected "object" but got "undefined"
-FAIL Audio track getCapabilities() sampleRate property present. assert_true: expected true got false
-FAIL Audio track getCapabilities() sampleRate properly supported. assert_equals: expected "object" but got "undefined"
+PASS Audio track getCapabilities() sampleRate property present.
+PASS Audio track getCapabilities() sampleRate properly supported.
 PASS Audio track getCapabilities() sampleSize property present.
 PASS Audio track getCapabilities() sampleSize properly supported.
 PASS Audio track getCapabilities() echoCancellation property present.
@@ -48,10 +48,10 @@
 PASS Audio track getCapabilities() autoGainControl properly supported.
 PASS Audio track getCapabilities() noiseSuppression property present.
 PASS Audio track getCapabilities() noiseSuppression properly supported.
-FAIL Audio track getCapabilities() latency property present. assert_true: expected true got false
-FAIL Audio track getCapabilities() latency properly supported. assert_equals: expected "object" but got "undefined"
-FAIL Audio track getCapabilities() channelCount property present. assert_true: expected true got false
-FAIL Audio track getCapabilities() channelCount properly supported. assert_equals: expected "object" but got "undefined"
+PASS Audio track getCapabilities() latency property present.
+PASS Audio track getCapabilities() latency properly supported.
+PASS Audio track getCapabilities() channelCount property present.
+PASS Audio track getCapabilities() channelCount properly supported.
 PASS Audio track getCapabilities() deviceId property present.
 PASS Audio track getCapabilities() deviceId properly supported.
 PASS Audio track getCapabilities() groupId property present.
@@ -76,8 +76,8 @@
 PASS Video track getCapabilities() groupId properly supported.
 FAIL Audio device getCapabilities() volume property present. assert_true: expected true got false
 FAIL Audio device getCapabilities() volume properly supported. assert_equals: expected "object" but got "undefined"
-FAIL Audio device getCapabilities() sampleRate property present. assert_true: expected true got false
-FAIL Audio device getCapabilities() sampleRate properly supported. assert_equals: expected "object" but got "undefined"
+PASS Audio device getCapabilities() sampleRate property present.
+PASS Audio device getCapabilities() sampleRate properly supported.
 PASS Audio device getCapabilities() sampleSize property present.
 PASS Audio device getCapabilities() sampleSize properly supported.
 PASS Audio device getCapabilities() echoCancellation property present.
@@ -86,10 +86,10 @@
 PASS Audio device getCapabilities() autoGainControl properly supported.
 PASS Audio device getCapabilities() noiseSuppression property present.
 PASS Audio device getCapabilities() noiseSuppression properly supported.
-FAIL Audio device getCapabilities() latency property present. assert_true: expected true got false
-FAIL Audio device getCapabilities() latency properly supported. assert_equals: expected "object" but got "undefined"
-FAIL Audio device getCapabilities() channelCount property present. assert_true: expected true got false
-FAIL Audio device getCapabilities() channelCount properly supported. assert_equals: expected "object" but got "undefined"
+PASS Audio device getCapabilities() latency property present.
+PASS Audio device getCapabilities() latency properly supported.
+PASS Audio device getCapabilities() channelCount property present.
+PASS Audio device getCapabilities() channelCount properly supported.
 PASS Audio device getCapabilities() deviceId property present.
 PASS Audio device getCapabilities() deviceId properly supported.
 PASS Audio device getCapabilities() groupId property present.
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/device.mojom.js b/third_party/blink/web_tests/external/wpt/resources/chromium/device.mojom.js
index 436d303..6488cbc 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/device.mojom.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/device.mojom.js
@@ -155,6 +155,62 @@
 
     return validator.validationError.UNKNOWN_ENUM_VALUE;
   };
+  var UsbSynchronizationType = {};
+  UsbSynchronizationType.NONE = 0;
+  UsbSynchronizationType.ASYNCHRONOUS = UsbSynchronizationType.NONE + 1;
+  UsbSynchronizationType.ADAPTIVE = UsbSynchronizationType.ASYNCHRONOUS + 1;
+  UsbSynchronizationType.SYNCHRONOUS = UsbSynchronizationType.ADAPTIVE + 1;
+  UsbSynchronizationType.MIN_VALUE = 0,
+  UsbSynchronizationType.MAX_VALUE = 3,
+
+  UsbSynchronizationType.isKnownEnumValue = function(value) {
+    switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    }
+    return false;
+  };
+
+  UsbSynchronizationType.validate = function(enumValue) {
+    var isExtensible = false;
+    if (isExtensible || this.isKnownEnumValue(enumValue))
+      return validator.validationError.NONE;
+
+    return validator.validationError.UNKNOWN_ENUM_VALUE;
+  };
+  var UsbUsageType = {};
+  UsbUsageType.DATA = 0;
+  UsbUsageType.FEEDBACK = UsbUsageType.DATA + 1;
+  UsbUsageType.EXPLICIT_FEEDBACK = UsbUsageType.FEEDBACK + 1;
+  UsbUsageType.PERIODIC = UsbUsageType.EXPLICIT_FEEDBACK + 1;
+  UsbUsageType.NOTIFICATION = UsbUsageType.PERIODIC + 1;
+  UsbUsageType.RESERVED = UsbUsageType.NOTIFICATION + 1;
+  UsbUsageType.MIN_VALUE = 0,
+  UsbUsageType.MAX_VALUE = 5,
+
+  UsbUsageType.isKnownEnumValue = function(value) {
+    switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    }
+    return false;
+  };
+
+  UsbUsageType.validate = function(enumValue) {
+    var isExtensible = false;
+    if (isExtensible || this.isKnownEnumValue(enumValue))
+      return validator.validationError.NONE;
+
+    return validator.validationError.UNKNOWN_ENUM_VALUE;
+  };
   var UsbTransferStatus = {};
   UsbTransferStatus.COMPLETED = 0;
   UsbTransferStatus.TRANSFER_ERROR = UsbTransferStatus.COMPLETED + 1;
@@ -200,9 +256,13 @@
 
   UsbEndpointInfo.prototype.initDefaults_ = function() {
     this.endpointNumber = 0;
+    this.pollingInterval = 0;
     this.direction = 0;
     this.type = 0;
     this.packetSize = 0;
+    this.synchronizationType = 0;
+    this.usageType = 0;
+    this.extraData = null;
   };
   UsbEndpointInfo.prototype.initFields_ = function(fields) {
     for(var field in fields) {
@@ -218,7 +278,7 @@
         return err;
 
     var kVersionSizes = [
-      {version: 0, numBytes: 24}
+      {version: 0, numBytes: 40}
     ];
     err = messageValidator.validateStructVersion(offset, kVersionSizes);
     if (err !== validator.validationError.NONE)
@@ -238,10 +298,29 @@
         return err;
 
 
+
+    // validate UsbEndpointInfo.synchronizationType
+    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, UsbSynchronizationType);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate UsbEndpointInfo.usageType
+    err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 20, UsbUsageType);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+
+    // validate UsbEndpointInfo.extraData
+    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 1, codec.Uint8, false, [0], 0);
+    if (err !== validator.validationError.NONE)
+        return err;
+
     return validator.validationError.NONE;
   };
 
-  UsbEndpointInfo.encodedSize = codec.kStructHeaderSize + 16;
+  UsbEndpointInfo.encodedSize = codec.kStructHeaderSize + 32;
 
   UsbEndpointInfo.decode = function(decoder) {
     var packed;
@@ -249,12 +328,15 @@
     var numberOfBytes = decoder.readUint32();
     var version = decoder.readUint32();
     val.endpointNumber = decoder.decodeStruct(codec.Uint8);
-    decoder.skip(1);
+    val.pollingInterval = decoder.decodeStruct(codec.Uint8);
     decoder.skip(1);
     decoder.skip(1);
     val.direction = decoder.decodeStruct(codec.Int32);
     val.type = decoder.decodeStruct(codec.Int32);
     val.packetSize = decoder.decodeStruct(codec.Uint32);
+    val.synchronizationType = decoder.decodeStruct(codec.Int32);
+    val.usageType = decoder.decodeStruct(codec.Int32);
+    val.extraData = decoder.decodeArrayPointer(codec.Uint8);
     return val;
   };
 
@@ -263,12 +345,15 @@
     encoder.writeUint32(UsbEndpointInfo.encodedSize);
     encoder.writeUint32(0);
     encoder.encodeStruct(codec.Uint8, val.endpointNumber);
-    encoder.skip(1);
+    encoder.encodeStruct(codec.Uint8, val.pollingInterval);
     encoder.skip(1);
     encoder.skip(1);
     encoder.encodeStruct(codec.Int32, val.direction);
     encoder.encodeStruct(codec.Int32, val.type);
     encoder.encodeStruct(codec.Uint32, val.packetSize);
+    encoder.encodeStruct(codec.Int32, val.synchronizationType);
+    encoder.encodeStruct(codec.Int32, val.usageType);
+    encoder.encodeArrayPointer(codec.Uint8, val.extraData);
   };
   function UsbAlternateInterfaceInfo(values) {
     this.initDefaults_();
@@ -283,6 +368,7 @@
     this.protocolCode = 0;
     this.interfaceName = null;
     this.endpoints = null;
+    this.extraData = null;
   };
   UsbAlternateInterfaceInfo.prototype.initFields_ = function(fields) {
     for(var field in fields) {
@@ -298,7 +384,7 @@
         return err;
 
     var kVersionSizes = [
-      {version: 0, numBytes: 32}
+      {version: 0, numBytes: 40}
     ];
     err = messageValidator.validateStructVersion(offset, kVersionSizes);
     if (err !== validator.validationError.NONE)
@@ -320,10 +406,16 @@
     if (err !== validator.validationError.NONE)
         return err;
 
+
+    // validate UsbAlternateInterfaceInfo.extraData
+    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 1, codec.Uint8, false, [0], 0);
+    if (err !== validator.validationError.NONE)
+        return err;
+
     return validator.validationError.NONE;
   };
 
-  UsbAlternateInterfaceInfo.encodedSize = codec.kStructHeaderSize + 24;
+  UsbAlternateInterfaceInfo.encodedSize = codec.kStructHeaderSize + 32;
 
   UsbAlternateInterfaceInfo.decode = function(decoder) {
     var packed;
@@ -340,6 +432,7 @@
     decoder.skip(1);
     val.interfaceName = decoder.decodeStructPointer(string16$.String16);
     val.endpoints = decoder.decodeArrayPointer(new codec.PointerTo(UsbEndpointInfo));
+    val.extraData = decoder.decodeArrayPointer(codec.Uint8);
     return val;
   };
 
@@ -357,6 +450,7 @@
     encoder.skip(1);
     encoder.encodeStructPointer(string16$.String16, val.interfaceName);
     encoder.encodeArrayPointer(new codec.PointerTo(UsbEndpointInfo), val.endpoints);
+    encoder.encodeArrayPointer(codec.Uint8, val.extraData);
   };
   function UsbInterfaceInfo(values) {
     this.initDefaults_();
@@ -439,8 +533,12 @@
 
   UsbConfigurationInfo.prototype.initDefaults_ = function() {
     this.configurationValue = 0;
+    this.selfPowered = false;
+    this.remoteWakeup = false;
+    this.maximumPower = 0;
     this.configurationName = null;
     this.interfaces = null;
+    this.extraData = null;
   };
   UsbConfigurationInfo.prototype.initFields_ = function(fields) {
     for(var field in fields) {
@@ -456,7 +554,7 @@
         return err;
 
     var kVersionSizes = [
-      {version: 0, numBytes: 32}
+      {version: 0, numBytes: 40}
     ];
     err = messageValidator.validateStructVersion(offset, kVersionSizes);
     if (err !== validator.validationError.NONE)
@@ -470,15 +568,24 @@
         return err;
 
 
+
+
+
     // validate UsbConfigurationInfo.interfaces
     err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 8, new codec.PointerTo(UsbInterfaceInfo), false, [0], 0);
     if (err !== validator.validationError.NONE)
         return err;
 
+
+    // validate UsbConfigurationInfo.extraData
+    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 1, codec.Uint8, false, [0], 0);
+    if (err !== validator.validationError.NONE)
+        return err;
+
     return validator.validationError.NONE;
   };
 
-  UsbConfigurationInfo.encodedSize = codec.kStructHeaderSize + 24;
+  UsbConfigurationInfo.encodedSize = codec.kStructHeaderSize + 32;
 
   UsbConfigurationInfo.decode = function(decoder) {
     var packed;
@@ -486,8 +593,10 @@
     var numberOfBytes = decoder.readUint32();
     var version = decoder.readUint32();
     val.configurationValue = decoder.decodeStruct(codec.Uint8);
-    decoder.skip(1);
-    decoder.skip(1);
+    packed = decoder.readUint8();
+    val.selfPowered = (packed >> 0) & 1 ? true : false;
+    val.remoteWakeup = (packed >> 1) & 1 ? true : false;
+    val.maximumPower = decoder.decodeStruct(codec.Uint8);
     decoder.skip(1);
     decoder.skip(1);
     decoder.skip(1);
@@ -495,6 +604,7 @@
     decoder.skip(1);
     val.configurationName = decoder.decodeStructPointer(string16$.String16);
     val.interfaces = decoder.decodeArrayPointer(new codec.PointerTo(UsbInterfaceInfo));
+    val.extraData = decoder.decodeArrayPointer(codec.Uint8);
     return val;
   };
 
@@ -503,8 +613,11 @@
     encoder.writeUint32(UsbConfigurationInfo.encodedSize);
     encoder.writeUint32(0);
     encoder.encodeStruct(codec.Uint8, val.configurationValue);
-    encoder.skip(1);
-    encoder.skip(1);
+    packed = 0;
+    packed |= (val.selfPowered & 1) << 0
+    packed |= (val.remoteWakeup & 1) << 1
+    encoder.writeUint8(packed);
+    encoder.encodeStruct(codec.Uint8, val.maximumPower);
     encoder.skip(1);
     encoder.skip(1);
     encoder.skip(1);
@@ -512,6 +625,7 @@
     encoder.skip(1);
     encoder.encodeStructPointer(string16$.String16, val.configurationName);
     encoder.encodeArrayPointer(new codec.PointerTo(UsbInterfaceInfo), val.interfaces);
+    encoder.encodeArrayPointer(codec.Uint8, val.extraData);
   };
   function UsbDeviceInfo(values) {
     this.initDefaults_();
@@ -3655,6 +3769,8 @@
   exports.UsbControlTransferType = UsbControlTransferType;
   exports.UsbControlTransferRecipient = UsbControlTransferRecipient;
   exports.UsbTransferType = UsbTransferType;
+  exports.UsbSynchronizationType = UsbSynchronizationType;
+  exports.UsbUsageType = UsbUsageType;
   exports.UsbTransferStatus = UsbTransferStatus;
   exports.UsbEndpointInfo = UsbEndpointInfo;
   exports.UsbAlternateInterfaceInfo = UsbAlternateInterfaceInfo;
@@ -3669,4 +3785,4 @@
   exports.UsbDeviceClient = UsbDeviceClient;
   exports.UsbDeviceClientPtr = UsbDeviceClientPtr;
   exports.UsbDeviceClientAssociatedPtr = UsbDeviceClientAssociatedPtr;
-})();
\ No newline at end of file
+})();
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/webusb-test.js b/third_party/blink/web_tests/external/wpt/resources/chromium/webusb-test.js
index 18ee824..c4d4e8f1 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/webusb-test.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/webusb-test.js
@@ -68,7 +68,11 @@
     var configInfo = {
       configurationValue: config.configurationValue,
       configurationName: stringToMojoString16(config.configurationName),
-      interfaces: []
+      selfPowered: false,
+      remoteWakeup: false,
+      maximumPower: 0,
+      interfaces: [],
+      extraData: new Uint8Array()
     };
     config.interfaces.forEach(iface => {
       var interfaceInfo = {
@@ -82,12 +86,17 @@
           subclassCode: alternate.interfaceSubclass,
           protocolCode: alternate.interfaceProtocol,
           interfaceName: stringToMojoString16(alternate.interfaceName),
-          endpoints: []
+          endpoints: [],
+          extraData: new Uint8Array()
         };
         alternate.endpoints.forEach(endpoint => {
           var endpointInfo = {
             endpointNumber: endpoint.endpointNumber,
             packetSize: endpoint.packetSize,
+            synchronizationType: device.mojom.UsbSynchronizationType.NONE,
+            usageType: device.mojom.UsbUsageType.DATA,
+            pollingInterval: 0,
+            extraData: new Uint8Array()
           };
           switch (endpoint.direction) {
           case "in":
diff --git a/third_party/blink/web_tests/fast/mediastream/MediaStreamTrack-getCapabilities.html b/third_party/blink/web_tests/fast/mediastream/MediaStreamTrack-getCapabilities.html
index 095082bc..6536ebde 100644
--- a/third_party/blink/web_tests/fast/mediastream/MediaStreamTrack-getCapabilities.html
+++ b/third_party/blink/web_tests/fast/mediastream/MediaStreamTrack-getCapabilities.html
@@ -6,10 +6,13 @@
   return navigator.mediaDevices.getUserMedia({audio: true})
       .then(function(stream) {
     var capabilities = stream.getAudioTracks()[0].getCapabilities();
-    assert_equals(Object.keys(capabilities).length, 7);
+    assert_equals(Object.keys(capabilities).length, 10);
     assert_true(capabilities.hasOwnProperty('deviceId'));
     assert_true(capabilities.hasOwnProperty('groupId'));
     assert_true(capabilities.hasOwnProperty('sampleSize'));
+    assert_true(capabilities.hasOwnProperty('channelCount'));
+    assert_true(capabilities.hasOwnProperty('sampleRate'));
+    assert_true(capabilities.hasOwnProperty('latency'));
     verifyAudioProcessingProperties(capabilities, true);
   });
 }, 'getCapabilities() support for getUserMedia() audio track.');
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
index 5f81318..187886a 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
index 393cd0f..08090cd 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
@@ -12,7 +12,7 @@
     Error: {"message":"Invalid reponse code: 404"}
     Error: {"message":"Failed to fetch the certificate.","signatureIndex":0,"errorField":"signatureCertUrl"}
 * https://127.0.0.1:8443/loading/sxg/resources/not_found_cert.pem.cbor
-  failed: false
+  failed: true
   statusCode: 404
   resourceType: other
 * https://127.0.0.1:8443/loading/sxg/resources/inner-url.html
diff --git a/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-anchor-point-expected.png
index 4509f81..54e2e162 100644
--- a/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-anchor-point-expected.png
+++ b/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png b/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
index 1df3bf1..22104a8c7 100644
--- a/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/blink/web_tests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/video-layer-crash-expected.png b/third_party/blink/web_tests/platform/linux/media/video-layer-crash-expected.png
index 25098b6..17b73d0 100644
--- a/third_party/blink/web_tests/platform/linux/media/video-layer-crash-expected.png
+++ b/third_party/blink/web_tests/platform/linux/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
index 4d47317..4b2bb86 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-creation-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-creation-expected.png
index fcb4f4b..f01e869 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-creation-expected.png
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/js-late-gradient-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/tabgroup-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/tabgroup-expected.txt
index abe8345..edf38c1 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/tabgroup-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/tabgroup-expected.txt
@@ -69,7 +69,7 @@
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 257, 50, 29],
+          "rect": [11, 257, 49, 29],
           "reason": "chunk appeared"
         },
         {
diff --git a/third_party/blink/web_tests/platform/linux/svg/batik/text/textEffect3-expected.png b/third_party/blink/web_tests/platform/linux/svg/batik/text/textEffect3-expected.png
index a111423..f629979 100644
--- a/third_party/blink/web_tests/platform/linux/svg/batik/text/textEffect3-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/batik/text/textEffect3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-expected.png
index 12dc8d9..6138106 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-on-path-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-on-path-expected.png
index 949f763..09e38fe0 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-on-path-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-on-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-zoomed-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
index 1209e2be..2f0c2051 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
index e51db85d..887f209 100644
--- a/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png
index 22ff4cca..147a31f 100644
--- a/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/transforms/text-with-pattern-with-svg-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-zoom-coords-expected.txt b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-zoom-coords-expected.txt
index e40d8d1..d8a8c7b 100644
--- a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-zoom-coords-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-zoom-coords-expected.txt
@@ -61,9 +61,9 @@
 PASS image1.bottom is 275.00
 PASS text1.left is 100.00
 PASS text1.top is 282.66
-FAIL text1.width should be 47.98. Was 49.1875.
+FAIL text1.width should be 47.98. Was 49.203128814697266.
 PASS text1.height is 6.16
-FAIL text1.right should be 147.98. Was 149.1875.
+FAIL text1.right should be 147.98. Was 149.20312881469727.
 PASS text1.bottom is 288.82
 
 
@@ -87,10 +87,10 @@
 PASS image2.bottom is 125.00
 PASS text2.left is 175.00
 PASS text2.top is 132.66
-FAIL text2.width should be 47.98. Was 47.85938262939453.
-FAIL text2.height should be 6.02. Was 5.921872138977051.
-FAIL text2.right should be 222.98. Was 222.85938262939453.
-FAIL text2.bottom should be 138.7. Was 138.58593463897705.
+FAIL text2.width should be 47.98. Was 47.875.
+FAIL text2.height should be 6.02. Was 5.937491416931152.
+FAIL text2.right should be 222.98. Was 222.875.
+FAIL text2.bottom should be 138.7. Was 138.60155391693115.
 
 
 PASS svg3.left is 900.00
@@ -113,9 +113,9 @@
 PASS image3.bottom is 550.00
 PASS text3.left is 1100.00
 PASS text3.top is 565.33
-FAIL text3.width should be 95.97. Was 98.3750228881836.
+FAIL text3.width should be 95.97. Was 98.40630340576172.
 PASS text3.height is 12.31
-FAIL text3.right should be 1195.97. Was 1198.3750228881836.
+FAIL text3.right should be 1195.97. Was 1198.4063034057617.
 PASS text3.bottom is 577.64
 
 
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/masks/mask-with-added-filters-expected.png
new file mode 100644
index 0000000..23f446e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/masks/mask-with-added-filters-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-anchor-point-expected.png
new file mode 100644
index 0000000..54e2e162
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-animated-expected.png b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-animated-expected.png
new file mode 100644
index 0000000..22104a8c7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
new file mode 100644
index 0000000..4b2bb86
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-creation-expected.png b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-creation-expected.png
new file mode 100644
index 0000000..f01e869
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/js-late-gradient-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/tabgroup-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/tabgroup-expected.txt
new file mode 100644
index 0000000..edf38c1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/tabgroup-expected.txt
@@ -0,0 +1,89 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [388, 37, 318, 83],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [261, 277, 305, 305],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [5, 255, 240, 162],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [5, 255, 240, 162],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [5, 255, 240, 162],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGPath path",
+          "rect": [5, 255, 240, 162],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g",
+          "rect": [505, 232, 240, 161],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "InlineTextBox 'This is a tabgroup with triangular tab corners'",
+          "rect": [15, 291, 211, 37],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGContainer g id='tabgroupRect'",
+          "rect": [37, 5, 161, 240],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [66, 257, 57, 29],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [11, 257, 49, 29],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [130, 257, 47, 29],
+          "reason": "chunk appeared"
+        },
+        {
+          "object": "LayoutSVGText text",
+          "rect": [183, 257, 32, 29],
+          "reason": "chunk appeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-layer-crash-expected.png b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-layer-crash-expected.png
index 25098b6..17b73d0 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-layer-crash-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect-expected.png
index acdc566..fbef8db 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect3-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect3-expected.png
index fd76b42..19e7e6a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect3-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/batik/text/textEffect3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-expected.png
index 7077e54..eb4a36e 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-on-path-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-on-path-expected.png
index 1ccd1f0..d825059 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-on-path-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-on-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-zoomed-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
index 0bdd87ca..4e51aae5 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
index 093a659..3e9b4da 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
+++ b/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png b/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
index 6cd228bd..c3a44c3 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/blink/web_tests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/video-layer-crash-expected.png b/third_party/blink/web_tests/platform/mac/media/video-layer-crash-expected.png
index dac906f..cf3ec775 100644
--- a/third_party/blink/web_tests/platform/mac/media/video-layer-crash-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
index ce2061c..5236728 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.png
index aa25effc..82d7547 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.png
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/js-late-gradient-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/tabgroup-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
index 6654bb0..70b3f02 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/tabgroup-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/animations/animate-text-nested-transforms-expected.txt b/third_party/blink/web_tests/platform/mac/svg/animations/animate-text-nested-transforms-expected.txt
similarity index 96%
rename from third_party/blink/web_tests/svg/animations/animate-text-nested-transforms-expected.txt
rename to third_party/blink/web_tests/platform/mac/svg/animations/animate-text-nested-transforms-expected.txt
index ae2d3ce..967c631 100644
--- a/third_party/blink/web_tests/svg/animations/animate-text-nested-transforms-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/svg/animations/animate-text-nested-transforms-expected.txt
@@ -6,7 +6,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 FAIL rootSVGElement.getBBox().x should be close to 115. Was 116.01841735839844.
-FAIL rootSVGElement.getBBox().y should be close to -154. Was -162.8862762451172.
+FAIL rootSVGElement.getBBox().y should be close to -154. Was -162.9019012451172.
 PASS rootSVGElement.getBBox().x is 367
 PASS rootSVGElement.getBBox().y is 550
 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect-expected.png b/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect-expected.png
index 97840d9..9ab5c0a0 100644
--- a/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect3-expected.png b/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect3-expected.png
index 5ba6b39..94db01f 100644
--- a/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect3-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/batik/text/textEffect3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/css/text-gradient-shadow-expected.png b/third_party/blink/web_tests/platform/mac/svg/css/text-gradient-shadow-expected.png
index 65b96fc..c85b3aa 100644
--- a/third_party/blink/web_tests/platform/mac/svg/css/text-gradient-shadow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/css/text-gradient-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-expected.png
index 05d6a938..db2b26f 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-on-path-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-on-path-expected.png
index 51fe156d..e5e21c0 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-on-path-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-on-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
index cfd2202c9..4c7c47e 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/selection-styles-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/selection-styles-expected.png
index 23a0ddd0..a87b73f 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/selection-styles-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/selection-styles-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
index c9464aa..53a1836 100644
--- a/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png
index 1cca895..61835ed 100644
--- a/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/transforms/text-with-pattern-with-svg-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/zoom/page/zoom-zoom-coords-expected.txt b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-zoom-coords-expected.txt
similarity index 91%
rename from third_party/blink/web_tests/svg/zoom/page/zoom-zoom-coords-expected.txt
rename to third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-zoom-coords-expected.txt
index 5f49b1b..c301e76 100644
--- a/third_party/blink/web_tests/svg/zoom/page/zoom-zoom-coords-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-zoom-coords-expected.txt
@@ -61,9 +61,9 @@
 PASS image1.bottom is 275.00
 PASS text1.left is 100.00
 PASS text1.top is 282.66
-PASS text1.width is 47.98
+FAIL text1.width should be 47.98. Was 48.000003814697266.
 PASS text1.height is 6.16
-PASS text1.right is 147.98
+FAIL text1.right should be 147.98. Was 148.00000381469727.
 PASS text1.bottom is 288.82
 
 
@@ -113,9 +113,9 @@
 PASS image3.bottom is 550.00
 PASS text3.left is 1100.00
 PASS text3.top is 565.33
-PASS text3.width is 95.97
+FAIL text3.width should be 95.97. Was 95.99999237060547.
 PASS text3.height is 12.31
-PASS text3.right is 1195.97
+FAIL text3.right should be 1195.97. Was 1195.9999923706055.
 PASS text3.bottom is 577.64
 
 
diff --git a/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
index 23942c2..f032a01 100644
--- a/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
+++ b/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-animated-expected.png b/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
index 17e1196..d30199a 100644
--- a/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
+++ b/third_party/blink/web_tests/platform/win/compositing/reflections/nested-reflection-animated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/color-profile-layer-filter-expected.png b/third_party/blink/web_tests/platform/win/images/color-profile-layer-filter-expected.png
new file mode 100644
index 0000000..aa0ab37
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/media/video-layer-crash-expected.png b/third_party/blink/web_tests/platform/win/media/video-layer-crash-expected.png
index a991cf96..f51e113 100644
--- a/third_party/blink/web_tests/platform/win/media/video-layer-crash-expected.png
+++ b/third_party/blink/web_tests/platform/win/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
index b008652..3939835 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-and-object-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-creation-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-creation-expected.png
index f242b2c..7b1b5e7 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-creation-expected.png
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/js-late-gradient-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/tabgroup-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/tabgroup-expected.txt
index 34c8e228..b184175 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/tabgroup-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/tabgroup-expected.txt
@@ -69,7 +69,7 @@
         },
         {
           "object": "LayoutSVGText text",
-          "rect": [10, 257, 50, 29],
+          "rect": [11, 257, 49, 29],
           "reason": "chunk appeared"
         },
         {
diff --git a/third_party/blink/web_tests/platform/win/svg/batik/text/textEffect3-expected.png b/third_party/blink/web_tests/platform/win/svg/batik/text/textEffect3-expected.png
index f34b6df5..e44378b 100644
--- a/third_party/blink/web_tests/platform/win/svg/batik/text/textEffect3-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/batik/text/textEffect3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-expected.png b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-expected.png
index cf065fb5..955aeb2 100644
--- a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-on-path-expected.png b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-on-path-expected.png
index ed3c882..f69da56 100644
--- a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-on-path-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-on-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.png b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
index 0f15a1d..a71ebd7 100644
--- a/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png b/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
index faf659f..b482b63 100644
--- a/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png b/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png
index 5b2ce54..6392750 100644
--- a/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/transforms/text-with-pattern-with-svg-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-zoom-coords-expected.txt b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-zoom-coords-expected.txt
index 180c82a..a93e34d1 100644
--- a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-zoom-coords-expected.txt
+++ b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-zoom-coords-expected.txt
@@ -61,9 +61,9 @@
 PASS image1.bottom is 275.00
 PASS text1.left is 100.00
 PASS text1.top is 282.66
-FAIL text1.width should be 47.98. Was 49.1875.
+FAIL text1.width should be 47.98. Was 49.203128814697266.
 PASS text1.height is 6.16
-FAIL text1.right should be 147.98. Was 149.1875.
+FAIL text1.right should be 147.98. Was 149.20312881469727.
 PASS text1.bottom is 288.82
 
 
@@ -87,10 +87,10 @@
 PASS image2.bottom is 125.00
 PASS text2.left is 175.00
 PASS text2.top is 132.66
-FAIL text2.width should be 47.98. Was 47.421878814697266.
-FAIL text2.height should be 6.02. Was 5.921872138977051.
-FAIL text2.right should be 222.98. Was 222.42187881469727.
-FAIL text2.bottom should be 138.7. Was 138.58593463897705.
+FAIL text2.width should be 47.98. Was 47.437496185302734.
+FAIL text2.height should be 6.02. Was 5.937491416931152.
+FAIL text2.right should be 222.98. Was 222.43749618530273.
+FAIL text2.bottom should be 138.7. Was 138.60155391693115.
 
 
 PASS svg3.left is 900.00
@@ -113,9 +113,9 @@
 PASS image3.bottom is 550.00
 PASS text3.left is 1100.00
 PASS text3.top is 565.33
-FAIL text3.width should be 95.97. Was 98.3750228881836.
+FAIL text3.width should be 95.97. Was 98.40630340576172.
 PASS text3.height is 12.31
-FAIL text3.right should be 1195.97. Was 1198.3750228881836.
+FAIL text3.right should be 1195.97. Was 1198.4063034057617.
 PASS text3.bottom is 577.64
 
 
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
index c8c60ee..7f401133 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-layer-filter-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-expected.png
index 2395ff19..eeb8ac1e 100644
--- a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-expected.png
+++ b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-on-path-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-on-path-expected.png
index 64a6070..860ca9c 100644
--- a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-on-path-expected.png
+++ b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-on-path-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
index 4b58c55..0b4621f 100644
--- a/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
+++ b/third_party/blink/web_tests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/animations/script-tests/animate-text-nested-transforms.js b/third_party/blink/web_tests/svg/animations/script-tests/animate-text-nested-transforms.js
index d3dd0d4..b0e2683 100644
--- a/third_party/blink/web_tests/svg/animations/script-tests/animate-text-nested-transforms.js
+++ b/third_party/blink/web_tests/svg/animations/script-tests/animate-text-nested-transforms.js
@@ -33,10 +33,10 @@
         ["animation", 0.001, startSample],
         ["animation", 39.999, endSample]
     ];
-    
+
     runAnimationTest(expectedValues);
 }
 
 window.clickX = 310;
-window.clickY = 30;
+window.clickY = 28;
 var successfullyParsed = true;
diff --git a/third_party/blink/web_tests/svg/zoom/zoomed-text-in-clippath.html b/third_party/blink/web_tests/svg/zoom/zoomed-text-in-clippath.html
new file mode 100644
index 0000000..144af8a
--- /dev/null
+++ b/third_party/blink/web_tests/svg/zoom/zoomed-text-in-clippath.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>The bounds of text content rounds "outward"</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<svg height="200" style="zoom: 1.5">
+  <clipPath id="clip" clipPathUnits="objectBoundingBox">
+    <text y=".8" font-size="1">X</text>
+  </clipPath>
+  <rect width="200" height="200" fill="green" clip-path="url(#clip)"/>
+</svg>
+<script>
+  test(function() {
+    let clip_text = clip.firstElementChild;
+    let clip_text_bbox = clip_text.getBBox();
+    let clip_text_extents = clip_text.getExtentOfChar(0);
+    assert_less_than_equal(clip_text_bbox.x, clip_text_extents.x, 'left');
+    assert_less_than_equal(clip_text_bbox.y, clip_text_extents.y, 'top');
+    assert_greater_than_equal(clip_text_bbox.x + clip_text_bbox.width,
+                              clip_text_extents.x + clip_text_extents.width, 'right');
+    assert_greater_than_equal(clip_text_bbox.y + clip_text_bbox.height,
+                              clip_text_extents.y + clip_text_extents.height, 'bottom');
+  });
+</script>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d2957771..e11cb721 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10065,11 +10065,15 @@
 <enum name="CrostiniExportContainerResult">
   <int value="0" label="Success"/>
   <int value="1" label="Failed"/>
+  <int value="2" label="Failed VM Stopped"/>
+  <int value="3" label="Failed VM Started"/>
 </enum>
 
 <enum name="CrostiniImportContainerResult">
   <int value="0" label="Success"/>
   <int value="1" label="Failed"/>
+  <int value="2" label="Failed VM Stopped"/>
+  <int value="3" label="Failed VM Started"/>
 </enum>
 
 <enum name="CrostiniSetupResult">
@@ -18389,7 +18393,7 @@
   <int value="1247" label="WALLPAPERPRIVATE_GETCURRENTWALLPAPERTHUMBNAIL"/>
   <int value="1248" label="ACCESSIBILITY_PRIVATE_ONSELECTTOSPEAKSTATECHANGED"/>
   <int value="1249" label="INPUTMETHODPRIVATE_GETCOMPOSITIONBOUNDS"/>
-  <int value="1250" label="FILEMANAGERPRIVATE_ISCROSTINIENABLED"/>
+  <int value="1250" label="DELETED_FILEMANAGERPRIVATE_ISCROSTINIENABLED"/>
   <int value="1251" label="FILEMANAGERPRIVATE_MOUNTCROSTINI"/>
   <int value="1252" label="CECPRIVATE_QUERYDISPLAYCECPOWERSTATE"/>
   <int value="1253" label="DEVELOPERPRIVATE_ADDHOSTPERMISSION"/>
@@ -18470,6 +18474,8 @@
   <int value="1323" label="AUTOTESTPRIVATE_SETTABLETMODEENABLED"/>
   <int value="1324" label="AUTOTESTPRIVATE_GETSHELFAUTOHIDEBEHAVIOR"/>
   <int value="1325" label="AUTOTESTPRIVATE_SETSHELFAUTOHIDEBEHAVIOR"/>
+  <int value="1326" label="AUTOTESTPRIVATE_EXPORTCROSTINI"/>
+  <int value="1327" label="AUTOTESTPRIVATE_IMPORTCROSTINI"/>
 </enum>
 
 <enum name="ExtensionIconState">
@@ -32593,6 +32599,7 @@
   <int value="-234687894"
       label="NonValidatingReloadOnRefreshContentV2:disabled"/>
   <int value="-231922000" label="enable-renderer-mojo-channel"/>
+  <int value="-231426350" label="AutofillEnableToolbarStatusChip:enabled"/>
   <int value="-230824955" label="NTPMostLikelyFaviconsFromServer:enabled"/>
   <int value="-225505731" label="CCTModule:enabled"/>
   <int value="-220599034" label="UsePdfCompositorServiceForPrint:enabled"/>
@@ -33180,6 +33187,7 @@
   <int value="740056959" label="ImeServiceConnectable:enabled"/>
   <int value="745783589" label="translate-force-trigger-on-english"/>
   <int value="745868416" label="disable-system-timezone-automatic-detection"/>
+  <int value="746765012" label="AutofillEnableToolbarStatusChip:disabled"/>
   <int value="746944193" label="enable-automatic-password-saving:disabled"/>
   <int value="747076955" label="MobileIdentityConsistency:enabled"/>
   <int value="747847237" label="PhysicalWeb:enabled"/>
@@ -52799,6 +52807,9 @@
   <int value="4" label="Download page resumed"/>
   <int value="5" label="Download page canceled"/>
   <int value="6" label="Content suggestion settings"/>
+  <int value="7" label="Web app action share"/>
+  <int value="8" label="Web app action open in Chrome"/>
+  <int value="9" label="Offline content suggestion settings"/>
 </enum>
 
 <enum name="SystemNotificationType">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 10e368c..676bc96 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -57523,6 +57523,16 @@
   </summary>
 </histogram>
 
+<histogram name="NativeSmbFileShare.GetSharesResult"
+    enum="NativeSmbFileShare_MountResult" expires_after="M78">
+  <owner>amistry@chromium.org</owner>
+  <owner>slangley@chromium.org</owner>
+  <summary>
+    The result of the GetShares operation for Native SMB File Share. This is
+    recorded after the D-Bus call to GetShares returns.
+  </summary>
+</histogram>
+
 <histogram name="NativeSmbFileShare.MountCount">
   <owner>zentaro@chromium.org</owner>
   <summary>
@@ -116730,7 +116740,7 @@
 </histogram>
 
 <histogram name="Sync.AutofillProfile.DeleteOrigin"
-    enum="AutofillProfileSyncChangeOrigin" expires_after="M73">
+    enum="AutofillProfileSyncChangeOrigin" expires_after="M75">
   <owner>jkrcal@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index f177d59..1cc04c4 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -129,7 +129,7 @@
           'num_shards': 19
         }
       ],
-      'platform': 'android',
+      'platform': 'android-chrome',
       'dimension': {
         'device_os': 'O',
         'device_type': 'gobo',
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 38d8f42..0963a99 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -2811,6 +2811,14 @@
                         nullptr);
 }
 
+void AXPlatformNodeAuraLinux::OnInvalidStatusChanged() {
+  DCHECK(atk_object_);
+
+  atk_object_notify_state_change(
+      ATK_OBJECT(atk_object_), ATK_STATE_INVALID_ENTRY,
+      GetData().GetInvalidState() != ax::mojom::InvalidState::kFalse);
+}
+
 void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(
     ax::mojom::Event event_type) {
   switch (event_type) {
@@ -2848,6 +2856,9 @@
     case ax::mojom::Event::kValueChanged:
       OnValueChanged();
       break;
+    case ax::mojom::Event::kInvalidStatusChanged:
+      OnInvalidStatusChanged();
+      break;
     case ax::mojom::Event::kWindowActivated:
       OnWindowActivated();
       break;
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h
index 877c83f..ff805bb5 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -91,6 +91,7 @@
   void OnValueChanged();
   void OnNameChanged();
   void OnDescriptionChanged();
+  void OnInvalidStatusChanged();
 
   bool SupportsSelectionWithAtkSelection();
   bool SelectionAndFocusAreTheSame();
diff --git a/ui/shell_dialogs/select_file_dialog_mac.h b/ui/shell_dialogs/select_file_dialog_mac.h
index 5c62bac..6ac62d10 100644
--- a/ui/shell_dialogs/select_file_dialog_mac.h
+++ b/ui/shell_dialogs/select_file_dialog_mac.h
@@ -7,10 +7,11 @@
 
 #import <Cocoa/Cocoa.h>
 
-#include <map>
+#include <list>
 #include <memory>
 #include <vector>
 
+#include "base/callback.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -27,6 +28,57 @@
 class SelectFileDialogMacTest;
 }  // namespace test
 
+// TODO(https://crbug.com/913303): Move this structure to ui/views_bridge_mac.
+// This structure provides a C++ (or mojo) interface for creating a NSSavePanel.
+class SavePanelBridge {
+ public:
+  // Callback made from the NSSavePanel's completion block.
+  using PanelEndedCallback =
+      base::OnceCallback<void(bool was_cancelled,
+                              const std::vector<base::FilePath>& files,
+                              int index)>;
+
+  SavePanelBridge(PanelEndedCallback callback);
+  ~SavePanelBridge();
+
+  void Initialize(SelectFileDialog::Type type,
+                  NSWindow* owning_window,
+                  const base::string16& title,
+                  const base::FilePath& default_path,
+                  const SelectFileDialog::FileTypeInfo* file_types,
+                  int file_type_index,
+                  const base::FilePath::StringType& default_extension);
+  NSSavePanel* GetNativePanelForTesting() { return panel_.get(); }
+
+ private:
+  // Sets the accessory view for |dialog_| and sets
+  // |extension_dropdown_handler_|.
+  void SetAccessoryView(const SelectFileDialog::FileTypeInfo* file_types,
+                        int file_type_index,
+                        const base::FilePath::StringType& default_extension);
+
+  // Called when the panel completes.
+  void OnPanelEnded(bool did_cancel);
+
+  // The callback to make when this dialog ends.
+  PanelEndedCallback callback_;
+
+  // Type type of this dialog.
+  SelectFileDialog::Type type_;
+
+  // The NSSavePanel that |this| tracks.
+  base::scoped_nsobject<NSSavePanel> panel_;
+
+  // The delegate for |panel|.
+  base::scoped_nsobject<SelectFileDialogDelegate> delegate_;
+
+  // Extension dropdown handler corresponding to this file dialog.
+  base::scoped_nsobject<ExtensionDropdownHandler> extension_dropdown_handler_;
+
+  base::WeakPtrFactory<SavePanelBridge> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(SavePanelBridge);
+};
+
 // Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a
 // file or folder.
 // Exported for unit tests.
@@ -54,32 +106,19 @@
  private:
   friend class test::SelectFileDialogMacTest;
 
-  // Callback made when a panel is closed.
-  void FileWasSelected(NSSavePanel* dialog,
-                       bool is_multi,
-                       bool was_cancelled,
-                       const std::vector<base::FilePath>& files,
-                       int index);
-
   // Struct to store data associated with a file dialog while it is showing.
   struct DialogData {
     DialogData(gfx::NativeWindow parent_window_, void* params_);
     ~DialogData();
 
     // The parent window for the panel. Weak, used only for comparisons.
-    const gfx::NativeWindow parent_window;
+    gfx::NativeWindow parent_window;
 
     // |params| user data associated with this file dialog.
-    void* const params;
+    void* params;
 
-    // The NSSavePanel that |this| tracks.
-    base::scoped_nsobject<NSSavePanel> panel;
-
-    // The delegate for |panel|.
-    base::scoped_nsobject<SelectFileDialogDelegate> delegate;
-
-    // Extension dropdown handler corresponding to this file dialog.
-    base::scoped_nsobject<ExtensionDropdownHandler> extension_dropdown_handler;
+    // Bridge to the Cocoa NSSavePanel.
+    std::unique_ptr<SavePanelBridge> save_panel_bridge;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(DialogData);
@@ -87,18 +126,17 @@
 
   ~SelectFileDialogImpl() override;
 
-  // Sets the accessory view for the |dialog| and returns the associated
-  // ExtensionDropdownHandler.
-  static base::scoped_nsobject<ExtensionDropdownHandler> SetAccessoryView(
-      NSSavePanel* dialog,
-      const FileTypeInfo* file_types,
-      int file_type_index,
-      const base::FilePath::StringType& default_extension);
+  // Callback made when a panel is closed.
+  void FileWasSelected(DialogData* dialog_data,
+                       bool is_multi,
+                       bool was_cancelled,
+                       const std::vector<base::FilePath>& files,
+                       int index);
 
   bool HasMultipleFileTypeChoicesImpl() override;
 
-  // A map from file dialogs to the DialogData associated with them.
-  std::map<NSSavePanel*, std::unique_ptr<DialogData>> dialog_data_map_;
+  // A list containing a DialogData for all active dialogs.
+  std::list<DialogData> dialog_data_list_;
 
   bool hasMultipleFileTypeChoices_;
 
diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm
index 6fef1370..21c7e89 100644
--- a/ui/shell_dialogs/select_file_dialog_mac.mm
+++ b/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/callback.h"
 #include "base/files/file_util.h"
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
@@ -113,19 +112,21 @@
 
 namespace ui {
 
-// Callback made from the NSSavePanel's completion block.
-using PanelEndedCallback =
-    base::RepeatingCallback<void(bool was_cancelled,
-                                 const std::vector<base::FilePath>& files,
-                                 int index)>;
+using Type = SelectFileDialog::Type;
+using FileTypeInfo = SelectFileDialog::FileTypeInfo;
 
-// Function called by the NSSavePanel's completion back.
-// TODO(https://crbug.com/913303): Move this function to be a member of
-// DialogData.
-void PanelEnded(NSSavePanel* panel,
-                ui::SelectFileDialog::Type type,
-                bool did_cancel,
-                PanelEndedCallback callback);
+SavePanelBridge::SavePanelBridge(PanelEndedCallback callback)
+    : callback_(std::move(callback)), weak_factory_(this) {}
+
+SavePanelBridge::~SavePanelBridge() {
+  // If we never executed our callback, then the panel never closed. Cancel it
+  // now.
+  if (callback_)
+    [panel_ cancel:panel_];
+
+  // Balance the setDelegate called during Initialize.
+  [panel_ setDelegate:nil];
+}
 
 SelectFileDialogImpl::SelectFileDialogImpl(
     Listener* listener,
@@ -133,8 +134,8 @@
     : SelectFileDialog(listener, std::move(policy)), weak_factory_(this) {}
 
 bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
-  for (const auto& key_value_pair : dialog_data_map_) {
-    if (key_value_pair.second->parent_window == parent_window)
+  for (const auto& dialog_data : dialog_data_list_) {
+    if (dialog_data.parent_window == parent_window)
       return true;
   }
   return false;
@@ -145,15 +146,17 @@
 }
 
 void SelectFileDialogImpl::FileWasSelected(
-    NSSavePanel* dialog,
+    DialogData* dialog_data,
     bool is_multi,
     bool was_cancelled,
     const std::vector<base::FilePath>& files,
     int index) {
-  auto it = dialog_data_map_.find(dialog);
-  DCHECK(it != dialog_data_map_.end());
-  void* params = it->second->params;
-  dialog_data_map_.erase(it);
+  auto it = std::find_if(
+      dialog_data_list_.begin(), dialog_data_list_.end(),
+      [dialog_data](const DialogData& d) { return &d == dialog_data; });
+  DCHECK(it != dialog_data_list_.end());
+  void* params = dialog_data->params;
+  dialog_data_list_.erase(it);
 
   if (!listener_)
     return;
@@ -190,16 +193,42 @@
     [owning_window makeKeyAndOrderFront:nil];
     [owning_window setLevel:NSModalPanelWindowLevel];
   }
-  std::unique_ptr<DialogData> dialog_data =
-      std::make_unique<DialogData>(owning_native_window, params);
 
-  // Note: we need to retain the dialog as owning_window can be null.
+  hasMultipleFileTypeChoices_ =
+      file_types ? file_types->extensions.size() > 1 : true;
+
+  // Add a new DialogData to the list.
+  dialog_data_list_.emplace_back(owning_window, params);
+  DialogData& dialog_data = dialog_data_list_.back();
+
+  // Create a NSSavePanel for it. Note that it is safe to pass |dialog_data| by
+  // a pointer because it will only be removed from the list when the callback
+  // is made or after the callback has been cancelled by |weak_factory_|.
+  dialog_data.save_panel_bridge =
+      std::make_unique<SavePanelBridge>(base::BindOnce(
+          &SelectFileDialogImpl::FileWasSelected, weak_factory_.GetWeakPtr(),
+          &dialog_data, type == SELECT_OPEN_MULTI_FILE));
+  dialog_data.save_panel_bridge->Initialize(type, owning_window, title,
+                                            default_path, file_types,
+                                            file_type_index, default_extension);
+}
+
+void SavePanelBridge::Initialize(
+    Type type,
+    NSWindow* owning_window,
+    const base::string16& title,
+    const base::FilePath& default_path,
+    const FileTypeInfo* file_types,
+    int file_type_index,
+    const base::FilePath::StringType& default_extension) {
+  type_ = type;
+  // Note: we need to retain the dialog as |owning_window| can be null.
   // (See http://crbug.com/29213 .)
-  if (type == SELECT_SAVEAS_FILE)
-    dialog_data->panel.reset([[NSSavePanel savePanel] retain]);
+  if (type_ == SelectFileDialog::SELECT_SAVEAS_FILE)
+    panel_.reset([[NSSavePanel savePanel] retain]);
   else
-    dialog_data->panel.reset([[NSOpenPanel openPanel] retain]);
-  NSSavePanel* dialog = dialog_data->panel.get();
+    panel_.reset([[NSOpenPanel openPanel] retain]);
+  NSSavePanel* dialog = panel_.get();
 
   if (!title.empty())
     [dialog setMessage:base::SysUTF16ToNSString(title)];
@@ -219,22 +248,18 @@
     }
   }
 
-  if (type != SELECT_FOLDER && type != SELECT_UPLOAD_FOLDER &&
-      type != SELECT_EXISTING_FOLDER) {
+  if (type_ != SelectFileDialog::SELECT_FOLDER &&
+      type_ != SelectFileDialog::SELECT_UPLOAD_FOLDER &&
+      type_ != SelectFileDialog::SELECT_EXISTING_FOLDER) {
     if (file_types) {
-      dialog_data->extension_dropdown_handler =
-          SelectFileDialogImpl::SetAccessoryView(
-              dialog, file_types, file_type_index, default_extension);
+      SetAccessoryView(file_types, file_type_index, default_extension);
     } else {
-      // If no type info is specified, anything goes.
+      // If no type_ info is specified, anything goes.
       [dialog setAllowsOtherFileTypes:YES];
     }
   }
 
-  hasMultipleFileTypeChoices_ =
-      file_types ? file_types->extensions.size() > 1 : true;
-
-  if (type == SELECT_SAVEAS_FILE) {
+  if (type_ == SelectFileDialog::SELECT_SAVEAS_FILE) {
     // When file extensions are hidden and removing the extension from
     // the default filename gives one which still has an extension
     // that OS X recognizes, it will get confused and think the user
@@ -252,51 +277,46 @@
   } else {
     NSOpenPanel* open_dialog = base::mac::ObjCCastStrict<NSOpenPanel>(dialog);
 
-    if (type == SELECT_OPEN_MULTI_FILE)
+    if (type_ == SelectFileDialog::SELECT_OPEN_MULTI_FILE)
       [open_dialog setAllowsMultipleSelection:YES];
     else
       [open_dialog setAllowsMultipleSelection:NO];
 
-    if (type == SELECT_FOLDER || type == SELECT_UPLOAD_FOLDER ||
-        type == SELECT_EXISTING_FOLDER) {
+    if (type_ == SelectFileDialog::SELECT_FOLDER ||
+        type_ == SelectFileDialog::SELECT_UPLOAD_FOLDER ||
+        type_ == SelectFileDialog::SELECT_EXISTING_FOLDER) {
       [open_dialog setCanChooseFiles:NO];
       [open_dialog setCanChooseDirectories:YES];
 
-      if (type == SELECT_FOLDER)
+      if (type_ == SelectFileDialog::SELECT_FOLDER)
         [open_dialog setCanCreateDirectories:YES];
       else
         [open_dialog setCanCreateDirectories:NO];
 
-      NSString *prompt = (type == SELECT_UPLOAD_FOLDER)
-          ? l10n_util::GetNSString(IDS_SELECT_UPLOAD_FOLDER_BUTTON_TITLE)
-          : l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE);
+      NSString* prompt =
+          (type_ == SelectFileDialog::SELECT_UPLOAD_FOLDER)
+              ? l10n_util::GetNSString(IDS_SELECT_UPLOAD_FOLDER_BUTTON_TITLE)
+              : l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE);
       [open_dialog setPrompt:prompt];
     } else {
       [open_dialog setCanChooseFiles:YES];
       [open_dialog setCanChooseDirectories:NO];
     }
 
-    dialog_data->delegate.reset([[SelectFileDialogDelegate alloc] init]);
-    [open_dialog setDelegate:dialog_data->delegate.get()];
+    delegate_.reset([[SelectFileDialogDelegate alloc] init]);
+    [open_dialog setDelegate:delegate_.get()];
   }
   if (default_dir)
     [dialog setDirectoryURL:[NSURL fileURLWithPath:default_dir]];
   if (default_filename)
     [dialog setNameFieldStringValue:default_filename];
 
-  // Add |dialog_data| to the map.
-  dialog_data_map_[dialog] = std::move(dialog_data);
-
-  // Ensure that |dialog| and |callback| (rather than |this|) be retained by the
-  // block.
-  auto callback = base::BindRepeating(
-      &SelectFileDialogImpl::FileWasSelected, weak_factory_.GetWeakPtr(),
-      dialog,
-      type == ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE /* is_multi */);
+  // Ensure that |callback| (rather than |this|) be retained by the block.
+  auto callback = base::BindRepeating(&SavePanelBridge::OnPanelEnded,
+                                      weak_factory_.GetWeakPtr());
   [dialog beginSheetModalForWindow:owning_window
                  completionHandler:^(NSInteger result) {
-                   PanelEnded(dialog, type,
-                              result != NSFileHandlingPanelOKButton, callback);
+                   callback.Run(result != NSFileHandlingPanelOKButton);
                  }];
 }
 
@@ -304,33 +324,31 @@
                                              void* params_)
     : parent_window(parent_window_), params(params_) {}
 
-SelectFileDialogImpl::DialogData::~DialogData() {
-  // Balance the setDelegate called during initialization.
-  [panel setDelegate:nil];
-}
+SelectFileDialogImpl::DialogData::~DialogData() {}
 
 SelectFileDialogImpl::~SelectFileDialogImpl() {
-  // Walk through the open dialogs and close them all. Clear |weak_factory_|
-  // beforehand, to ensure that no callbacks will be made.
+  // Clear |weak_factory_| beforehand, to ensure that no callbacks will be made
+  // when we cancel the NSSavePanels.
   weak_factory_.InvalidateWeakPtrs();
-  for (const auto& value : dialog_data_map_) {
-    NSSavePanel* panel = value.first;
-    [panel cancel:panel];
+
+  // Walk through the open dialogs and issue the cancel callbacks that would
+  // have been made.
+  for (const auto& dialog_data : dialog_data_list_) {
     if (listener_)
-      listener_->FileSelectionCanceled(value.second->params);
+      listener_->FileSelectionCanceled(dialog_data.params);
   }
-  dialog_data_map_.clear();
+
+  // Cancel the NSSavePanels be destroying their bridges.
+  dialog_data_list_.clear();
 }
 
-// static
-base::scoped_nsobject<ExtensionDropdownHandler>
-SelectFileDialogImpl::SetAccessoryView(
-    NSSavePanel* dialog,
+void SavePanelBridge::SetAccessoryView(
     const FileTypeInfo* file_types,
     int file_type_index,
     const base::FilePath::StringType& default_extension) {
   DCHECK(file_types);
   base::scoped_nsobject<NSView> accessory_view = CreateAccessoryView();
+  NSSavePanel* dialog = panel_.get();
   [dialog setAccessoryView:accessory_view.get()];
 
   NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag];
@@ -389,13 +407,13 @@
     [dialog setAllowsOtherFileTypes:YES];
   }
 
-  base::scoped_nsobject<ExtensionDropdownHandler> handler(
-      [[ExtensionDropdownHandler alloc] initWithDialog:dialog
-                                         fileTypeLists:file_type_lists]);
+  extension_dropdown_handler_.reset([[ExtensionDropdownHandler alloc]
+      initWithDialog:dialog
+       fileTypeLists:file_type_lists]);
 
   // This establishes a weak reference to handler. Hence we persist it as part
-  // of dialog_data_map_.
-  [popup setTarget:handler];
+  // of dialog_data_list_.
+  [popup setTarget:extension_dropdown_handler_];
   [popup setAction:@selector(popupAction:)];
 
   // file_type_index uses 1 based indexing.
@@ -404,7 +422,7 @@
               file_types->extensions.size());
     DCHECK_GE(file_type_index, 1);
     [popup selectItemAtIndex:file_type_index - 1];
-    [handler popupAction:popup];
+    [extension_dropdown_handler_ popupAction:popup];
   } else if (!default_extension.empty() && default_extension_index != -1) {
     [popup selectItemAtIndex:default_extension_index];
     [dialog
@@ -412,10 +430,8 @@
   } else {
     // Select the first item.
     [popup selectItemAtIndex:0];
-    [handler popupAction:popup];
+    [extension_dropdown_handler_ popupAction:popup];
   }
-
-  return handler;
 }
 
 bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
@@ -428,19 +444,19 @@
   return new SelectFileDialogImpl(listener, std::move(policy));
 }
 
-void PanelEnded(NSSavePanel* panel,
-                SelectFileDialog::Type type,
-                bool did_cancel,
-                PanelEndedCallback callback) {
+void SavePanelBridge::OnPanelEnded(bool did_cancel) {
+  if (!callback_)
+    return;
+
   int index = 0;
   std::vector<base::FilePath> paths;
   if (!did_cancel) {
-    if (type == SelectFileDialog::SELECT_SAVEAS_FILE) {
-      if ([[panel URL] isFileURL]) {
-        paths.push_back(base::mac::NSStringToFilePath([[panel URL] path]));
+    if (type_ == SelectFileDialog::SELECT_SAVEAS_FILE) {
+      if ([[panel_ URL] isFileURL]) {
+        paths.push_back(base::mac::NSStringToFilePath([[panel_ URL] path]));
       }
 
-      NSView* accessoryView = [panel accessoryView];
+      NSView* accessoryView = [panel_ accessoryView];
       if (accessoryView) {
         NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag];
         if (popup) {
@@ -451,15 +467,15 @@
         index = 1;
       }
     } else {
-      CHECK([panel isKindOfClass:[NSOpenPanel class]]);
-      NSArray* urls = [static_cast<NSOpenPanel*>(panel) URLs];
+      CHECK([panel_ isKindOfClass:[NSOpenPanel class]]);
+      NSArray* urls = [static_cast<NSOpenPanel*>(panel_) URLs];
       for (NSURL* url in urls)
         if ([url isFileURL])
           paths.push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
     }
   }
 
-  callback.Run(did_cancel, paths, index);
+  std::move(callback_).Run(did_cancel, paths, index);
 }
 
 }  // namespace ui
diff --git a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
index e6a99e4..4f71b81 100644
--- a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
+++ b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
@@ -102,7 +102,7 @@
 
   // Returns the number of panels currently active.
   size_t GetActivePanelCount() const {
-    return dialog_->dialog_data_map_.size();
+    return dialog_->dialog_data_list_.size();
   }
 
   // Returns one of the created NSSavePanel. If multiple SelectFile calls were
@@ -110,7 +110,8 @@
   // returned.
   NSSavePanel* GetPanel() const {
     DCHECK_GE(GetActivePanelCount(), 1lu);
-    return dialog_->dialog_data_map_.begin()->first;
+    return dialog_->dialog_data_list_.begin()
+        ->save_panel_bridge->GetNativePanelForTesting();
   }
 
   void ResetDialog() { dialog_ = new SelectFileDialogImpl(this, nullptr); }
diff --git a/ui/views_bridge_mac/native_widget_mac_nswindow.mm b/ui/views_bridge_mac/native_widget_mac_nswindow.mm
index 54ec2c8..fac57d3 100644
--- a/ui/views_bridge_mac/native_widget_mac_nswindow.mm
+++ b/ui/views_bridge_mac/native_widget_mac_nswindow.mm
@@ -200,6 +200,12 @@
 
 // Lets the traffic light buttons on the parent window keep their active state.
 - (BOOL)hasKeyAppearance {
+  // Note that this function is called off of the main thread. In such cases,
+  // it is not safe to access the mojo interface or the ui::Widget, as they are
+  // not reentrant.
+  // https://crbug.com/941506.
+  if (![NSThread isMainThread])
+    return [super hasKeyAppearance];
   if (bridgeImpl_) {
     bool isAlwaysRenderWindowAsKey = NO;
     bridgeImpl_->host()->GetAlwaysRenderWindowAsKey(&isAlwaysRenderWindowAsKey);