diff --git a/DEPS b/DEPS
index 38c360f..aec268e9 100644
--- a/DEPS
+++ b/DEPS
@@ -162,11 +162,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e26413128902fa676f709c0fcad08aff6aeda619',
+  'skia_revision': '165ca3f85b7a6a50647b998bf475c413de6b7a15',
   # 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': 'd96f3e7da3b1203b82d9f9f896bb49d85e337359',
+  'v8_revision': 'be6134761ccf7255bd481d6dae89e39a4eaadb19',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -174,7 +174,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '324b391559e7ff21bcd136b744a565b8167c5427',
+  'angle_revision': '120b61d34ba8da345ea08087a98959c3fa034356',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -197,7 +197,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling googletest
   # and whatever else without interference from each other.
-  'googletest_revision': 'eb56ee5a28b41fcc244205cc18ff7847f7c6b7bc',
+  'googletest_revision': '565f1b848215b77c3732bca345fe76a0431d8b34',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling lighttpd
   # and whatever else without interference from each other.
@@ -225,7 +225,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': '8a6f1eb1b962fcd59a79ca4c44ca5fcd361d2b54',
+  'catapult_revision': '8fe3e6ac1d7ae3776f2eb18b7a037b3c4c520e87',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -842,7 +842,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd28bb6a6a5c409f641289b240f3722228f15c47c',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ab1d1a8d60ddc5c22d4d19f38e93de0788945226',
       'condition': 'checkout_linux',
   },
 
@@ -1246,7 +1246,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '28b633cd961b50c4c75bfb7f62eeac79e27c1a79',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '3dd9de12f761026fe8b1782ac2617e4754a3eab0',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1455,7 +1455,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b56e461a7ced30b13b1cfe71aefaa0a14a1f8e88',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e12f9bdfbf6add3f44ade3f14da97a1b4d719790',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/DEPS b/android_webview/DEPS
index f28e133..058f928 100644
--- a/android_webview/DEPS
+++ b/android_webview/DEPS
@@ -22,6 +22,7 @@
   # Only allow this header in spellchecking since allowing all of spellchecking
   # would include both browser and renderer components.
   "+components/spellcheck/spellcheck_buildflags.h",
+  "+components/ui_devtools/buildflags.h",
   "+content/public/common",
   "+crypto",
   "+gpu",
diff --git a/android_webview/browser/gfx/BUILD.gn b/android_webview/browser/gfx/BUILD.gn
index 3e4ac5a..a879eb4 100644
--- a/android_webview/browser/gfx/BUILD.gn
+++ b/android_webview/browser/gfx/BUILD.gn
@@ -63,6 +63,7 @@
   deps = [
     "//android_webview:native_jni",
     "//base",
+    "//components/ui_devtools:buildflags",
     "//content/public/browser",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/service",
diff --git a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.cc b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.cc
index 5965e1d0..e9a8cec 100644
--- a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.cc
+++ b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.cc
@@ -120,7 +120,7 @@
           std::move(params->frame_sink_manager_client)));
 }
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 void VizCompositorThreadRunnerWebView::CreateVizDevTools(
     viz::mojom::VizDevToolsParamsPtr params) {
   NOTIMPLEMENTED();
diff --git a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
index b9e30549..7dfc92f 100644
--- a/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
+++ b/android_webview/browser/gfx/viz_compositor_thread_runner_webview.h
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
+#include "components/ui_devtools/buildflags.h"
 #include "components/viz/service/main/viz_compositor_thread_runner.h"
 
 namespace base {
@@ -56,7 +57,7 @@
   void CreateFrameSinkManager(viz::mojom::FrameSinkManagerParamsPtr params,
                               gpu::CommandBufferTaskExecutor* task_executor,
                               viz::GpuServiceImpl* gpu_service) override;
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   void CreateVizDevTools(viz::mojom::VizDevToolsParamsPtr params) override;
 #endif
   void CleanupForShutdown(base::OnceClosure cleanup_finished_callback) override;
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index 977954b..4235c044 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -643,6 +643,21 @@
       OnEndingAnimationComplete(/*canceled=*/true);
     delayed_animations_.clear();
 
+    // |should_focus_overview_| shall be true except when split view mode starts
+    // on transition between clamshell mode and tablet mode, on transition
+    // between user sessions, or on transition between virtual desks. Those are
+    // the cases where code arranges split view by first snapping a window on
+    // one side and then starting overview to be seen on the other side, meaning
+    // that the split view state here will be |SplitViewState::kLeftSnapped| or
+    // |SplitViewState::kRightSnapped|. We have to check the split view state
+    // before |SplitViewController::OnOverviewModeStarting|, because in case of
+    // |SplitViewState::kBothSnapped|, that function will insert one of the two
+    // snapped windows to overview.
+    const SplitViewState split_view_state =
+        Shell::Get()->split_view_controller()->state();
+    should_focus_overview_ = split_view_state == SplitViewState::kNoSnap ||
+                             split_view_state == SplitViewState::kBothSnapped;
+
     // Suspend occlusion tracker until the enter animation is complete.
     PauseOcclusionTracker();
 
@@ -706,8 +721,10 @@
 
   for (auto& observer : observers_)
     observer.OnOverviewModeStartingAnimationComplete(canceled);
-  if (overview_session_)
-    overview_session_->OnStartingAnimationComplete(canceled);
+  if (overview_session_) {
+    overview_session_->OnStartingAnimationComplete(canceled,
+                                                   should_focus_overview_);
+  }
   UnpauseOcclusionTracker(kOcclusionPauseDurationForStartMs);
   TRACE_EVENT_ASYNC_END1("ui", "OverviewController::EnterOverview", this,
                          "canceled", canceled);
diff --git a/ash/wm/overview/overview_controller.h b/ash/wm/overview/overview_controller.h
index 13efd1e..6b6122e 100644
--- a/ash/wm/overview/overview_controller.h
+++ b/ash/wm/overview/overview_controller.h
@@ -143,6 +143,10 @@
   // notify shell that the starting animations have been completed.
   std::vector<std::unique_ptr<DelayedAnimationObserver>> start_animations_;
 
+  // Indicates that overview shall gain focus when the starting animations have
+  // completed.
+  bool should_focus_overview_ = false;
+
   std::unique_ptr<aura::WindowOcclusionTracker::ScopedPause>
       occlusion_tracker_pauser_;
 
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index 93fa2a6..4168b5d 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -642,19 +642,20 @@
       window->UpdateRoundedCornersAndShadow();
 }
 
-void OverviewSession::OnStartingAnimationComplete(bool canceled) {
+void OverviewSession::OnStartingAnimationComplete(bool canceled,
+                                                  bool should_focus_overview) {
   for (auto& grid : grid_list_)
     grid->OnStartingAnimationComplete(canceled);
 
-  if (!canceled) {
-    if (overview_focus_widget_) {
-      if (enter_exit_overview_type_ == EnterExitOverviewType::kStartUnfocused)
-        overview_focus_widget_->ShowInactive();
-      else
-        overview_focus_widget_->Show();
-    }
-    Shell::Get()->overview_controller()->DelayedUpdateRoundedCornersAndShadow();
+  if (canceled)
+    return;
+  if (overview_focus_widget_) {
+    if (should_focus_overview)
+      overview_focus_widget_->Show();
+    else
+      overview_focus_widget_->ShowInactive();
   }
+  Shell::Get()->overview_controller()->DelayedUpdateRoundedCornersAndShadow();
 }
 
 void OverviewSession::OnWindowActivating(
diff --git a/ash/wm/overview/overview_session.h b/ash/wm/overview/overview_session.h
index 5432b9a..671517f 100644
--- a/ash/wm/overview/overview_session.h
+++ b/ash/wm/overview/overview_session.h
@@ -90,10 +90,6 @@
     // the source desk is in overview mode, while the target desk is not.
     // This should not be used for entering overview mode.
     kImmediateExit,
-    // Prevents overview from stealing the input focus. Used by code that starts
-    // overview after a window has already been snapped in split view. The
-    // purpose is so that overview does not steal focus from the snapped window.
-    kStartUnfocused,
   };
 
   // Callback which fills out the passed settings object. Used by several
@@ -215,8 +211,12 @@
   // Updates all the overview items' mask and shadow.
   void UpdateRoundedCornersAndShadow();
 
-  // Called when the overview mode starting animation completes.
-  void OnStartingAnimationComplete(bool canceled);
+  // Called when the overview mode starting animation completes. |canceled| is
+  // true when the starting animation is interrupted by ending overview mode. If
+  // |canceled| is false and |should_focus_overview| is true, then
+  // |overview_focus_widget_| shall gain focus. |should_focus_overview| has no
+  // effect when |canceled| is true.
+  void OnStartingAnimationComplete(bool canceled, bool should_focus_overview);
 
   // Called when windows are being activated/deactivated during
   // overview mode.
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index 0e3526f7..42601a1 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -17,7 +17,6 @@
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/wm/overview/overview_controller.h"
-#include "ash/wm/overview/overview_session.h"
 #include "ash/wm/tablet_mode/internal_input_devices_event_blocker.h"
 #include "ash/wm/tablet_mode/tablet_mode_window_manager.h"
 #include "ash/wm/window_state.h"
@@ -1012,8 +1011,7 @@
   const auto state = Shell::Get()->split_view_controller()->state();
   if (state == SplitViewState::kLeftSnapped ||
       state == SplitViewState::kRightSnapped) {
-    Shell::Get()->overview_controller()->StartOverview(
-        OverviewSession::EnterExitOverviewType::kStartUnfocused);
+    Shell::Get()->overview_controller()->StartOverview();
   }
 
   UpdateInternalInputDevicesEventBlocker();
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
index fb3dd8f..92280eda 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -1467,18 +1467,6 @@
   EXPECT_EQ(window1.get(), window_util::GetActiveWindow());
 }
 
-// Test that it is okay to write code that first starts split view by snapping a
-// window on one side, and then starts overview to be seen on the other side.
-TEST_F(TabletModeControllerTest,
-       ProgrammaticallyStartSplitViewAndThenOverview) {
-  SplitViewController* split_view_controller =
-      Shell::Get()->split_view_controller();
-  tablet_mode_controller()->SetEnabledForTest(true);
-  std::unique_ptr<aura::Window> window = CreateTestWindow();
-  split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
-  EXPECT_TRUE(Shell::Get()->overview_controller()->StartOverview());
-}
-
 // Test that tablet mode controller does not respond to the input device changes
 // during its suspend.
 TEST_F(TabletModeControllerTest, DoNotObserverInputDeviceChangeDuringSuspend) {
diff --git a/base/BUILD.gn b/base/BUILD.gn
index dcda6ea..5168c982 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2067,6 +2067,8 @@
   header_dir = "base/debug"
   enable_gdbinit_warning =
       is_debug && (strip_absolute_paths_from_debug_symbols || use_custom_libcxx)
+  enable_lldbinit_warning =
+      is_debug && strip_absolute_paths_from_debug_symbols && is_mac
 
   flags = [
     "ENABLE_LOCATION_SOURCE=$enable_location_source",
@@ -2075,6 +2077,7 @@
     "UNSAFE_DEVELOPER_BUILD=$is_unsafe_developer_build",
     "CAN_UNWIND_WITH_CFI_TABLE=$can_unwind_with_cfi_table",
     "ENABLE_GDBINIT_WARNING=$enable_gdbinit_warning",
+    "ENABLE_LLDBINIT_WARNING=$enable_lldbinit_warning",
   ]
 }
 
diff --git a/base/debug/debugger.h b/base/debug/debugger.h
index 318aa880..efc9b40 100644
--- a/base/debug/debugger.h
+++ b/base/debug/debugger.h
@@ -40,7 +40,8 @@
 
 // If a debugger is present, verifies that it is properly set up, and DCHECK()s
 // if misconfigured.  Currently only verifies that //tools/gdb/gdbinit has been
-// sourced when using gdb on Linux.
+// sourced when using gdb on Linux and //tools/lldb/lldbinit.py has been sourced
+// when using lldb on macOS.
 BASE_EXPORT void VerifyDebugger();
 
 }  // namespace debug
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc
index 45bf1da..c96101e 100644
--- a/base/debug/debugger_posix.cc
+++ b/base/debug/debugger_posix.cc
@@ -128,7 +128,22 @@
   return being_debugged;
 }
 
-void VerifyDebugger() {}
+void VerifyDebugger() {
+#if BUILDFLAG(ENABLE_LLDBINIT_WARNING)
+  if (Environment::Create()->HasVar("CHROMIUM_LLDBINIT_SOURCED"))
+    return;
+  if (!BeingDebugged())
+    return;
+  DCHECK(false)
+      << "Detected lldb without sourcing //tools/lldb/lldbinit.py. lldb may "
+         "not be able to find debug symbols. Please see debug instructions for "
+         "using //tools/lldb/lldbinit.py:\n"
+         "https://chromium.googlesource.com/chromium/src/+/master/docs/"
+         "lldbinit.md\n"
+         "To continue anyway, type 'continue' in lldb. To always skip this "
+         "check, define an environment variable CHROMIUM_LLDBINIT_SOURCED=1";
+#endif
+}
 
 #elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX)
 
diff --git a/base/threading/scoped_thread_priority.cc b/base/threading/scoped_thread_priority.cc
index 63b3887..1315705 100644
--- a/base/threading/scoped_thread_priority.cc
+++ b/base/threading/scoped_thread_priority.cc
@@ -4,12 +4,32 @@
 
 #include "base/threading/scoped_thread_priority.h"
 
+#include "base/containers/flat_set.h"
 #include "base/location.h"
+#include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
 #include "base/trace_event/trace_event.h"
 
 namespace base {
 
+namespace {
+
+#if defined(OS_WIN)
+// Flags the location |from_here| as executed. Returns true if the location
+// was not previously executed.
+bool ShouldBoostThreadPriorityForLocation(const Location& from_here) {
+  using ExecutedProgramCounterSet = base::flat_set<const void*>;
+  static base::NoDestructor<base::Lock> lock;
+  static base::NoDestructor<ExecutedProgramCounterSet> cache;
+
+  base::AutoLock auto_lock(*lock);
+  return cache.get()->insert(from_here.program_counter()).second;
+}
+#endif  // OS_WIN
+
+}  // namespace
+
 #if defined(OS_WIN)
 // Enable the boost of thread priority when the code may load a library. The
 // thread priority boost is required to avoid priority inversion on the loader
@@ -28,6 +48,11 @@
   if (!base::FeatureList::IsEnabled(kBoostThreadPriorityOnLibraryLoading))
     return;
 
+  // If the code at |from_here| has already been executed, do not boost the
+  // thread priority.
+  if (!ShouldBoostThreadPriorityForLocation(from_here))
+    return;
+
   base::ThreadPriority priority = PlatformThread::GetCurrentThreadPriority();
   if (priority == base::ThreadPriority::BACKGROUND) {
     original_thread_priority_ = priority;
diff --git a/build/android/gyp/util/zipalign.py b/build/android/gyp/util/zipalign.py
index 0110df6..eb5aaed 100644
--- a/build/android/gyp/util/zipalign.py
+++ b/build/android/gyp/util/zipalign.py
@@ -69,7 +69,7 @@
   """
   cur_offset = zip_obj.fp.tell()
   header_size = _FIXED_ZIP_HEADER_LEN + len(zip_info.filename)
-  padding_needed = (header_size - cur_offset) % alignment
+  padding_needed = (cur_offset - header_size) % alignment
 
   # Extra field used to 4-byte align classes.dex. Alignment speeds up
   # execution when dex files are used via incremental install.
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index befd9d7..f0b7e39 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -23,6 +23,10 @@
   import("//build/config/arm.gni")
 }
 
+if (is_mac) {
+  import("//build/config/mac/symbols.gni")
+}
+
 declare_args() {
   # How many symbols to include in the build. This affects the performance of
   # the build since the symbols are large and dealing with them is slow.
@@ -197,8 +201,13 @@
   # in turn is important for goma compile hit rate.
   # Setting this to true may make it harder to debug binaries on Linux, see
   # https://chromium.googlesource.com/chromium/src/+/master/docs/linux_debugging.md#Source-level-debug-with-fdebug_compilation_dir
+  # It's not clear if the crash server will correctly handle dSYMs with relative
+  # paths, so we disable this feature for official benefit. The main benefit is
+  # deterministic builds to reduce compile times, so this is less relevant for
+  # official builders.
   strip_absolute_paths_from_debug_symbols =
-      is_android || is_fuchsia || is_nacl || (is_win && use_lld) || is_linux
+      is_android || is_fuchsia || is_nacl || (is_win && use_lld) || is_linux ||
+      (is_mac && !enable_dsyms)
 }
 
 # If it wasn't manually set, set to an appropriate default.
diff --git a/build/config/fuchsia/package.gni b/build/config/fuchsia/package.gni
index 1395c61..746b382 100644
--- a/build/config/fuchsia/package.gni
+++ b/build/config/fuchsia/package.gni
@@ -40,13 +40,12 @@
   _build_ids_file = "$_pkg_out_dir/ids.txt"
   _component_manifest = "$_pkg_out_dir/${pkg.package_name}.cmx"
   _meta_far_file = "$_pkg_out_dir/meta.far"
-  _combined_far_file = "$_pkg_out_dir/${pkg.package_name}-0.far"
-  _final_far_file = "$_pkg_out_dir/${pkg.package_name}.far"
+  _package_far_file = "$_pkg_out_dir/${pkg.package_name}"
+  _package_far_file_with_suffix = "${_package_far_file}.far"
   _package_info_path = "$_pkg_out_dir/package"
 
   _write_manifest_target = "${pkg.package_name}__write_manifest"
   _package_target = "${pkg.package_name}__pkg"
-  _bundle_target = "${pkg.package_name}__bundle"
 
   # Generates a manifest file based on the GN runtime deps
   # suitable for "pm" tool consumption.
@@ -145,7 +144,7 @@
   }
 
   # Creates a package containing the metadata archive and blob data.
-  action(_bundle_target) {
+  action(target_name) {
     forward_variables_from(invoker, [ "testonly" ])
 
     script = "//build/gn_run_binary.py"
@@ -163,7 +162,15 @@
     ]
 
     outputs = [
-      _combined_far_file,
+      _package_far_file_with_suffix,
+    ]
+
+    data = [
+      _package_far_file_with_suffix,
+
+      # Files specified here so that they can be read by isolated testbots.
+      _package_info_path,
+      _build_ids_file,
     ]
 
     args = [
@@ -173,37 +180,8 @@
       "-m",
       rebase_path(_archive_manifest, root_build_dir),
       "archive",
-    ]
-  }
-
-  # Copies the archive to a well-known path.
-  # TODO(kmarshall): Use a 'pm' output flag to write directly to the desired
-  # file path instead.
-  copy(target_name) {
-    forward_variables_from(invoker, [ "testonly" ])
-
-    # Allows dependent targets to make use of "ids.txt".
-    public_deps = [
-      ":$_write_manifest_target",
-    ]
-
-    deps = [
-      ":$_bundle_target",
-    ]
-
-    data = [
-      _final_far_file,
-
-      # Files specified here so that they can be read by isolated testbots.
-      _package_info_path,
-      _build_ids_file,
-    ]
-
-    sources = [
-      _combined_far_file,
-    ]
-    outputs = [
-      _final_far_file,
+      "-output",
+      rebase_path(_package_far_file, root_build_dir),
     ]
   }
 }
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h
index d95c0ca..d32489d3 100644
--- a/cc/mojo_embedder/async_layer_tree_frame_sink.h
+++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -92,7 +92,6 @@
         synthetic_begin_frame_source;
     std::unique_ptr<viz::HitTestDataProvider> hit_test_data_provider;
     UnboundMessagePipes pipes;
-    bool enable_surface_synchronization = false;
     bool wants_animate_only_begin_frames = false;
     const char* client_name = nullptr;
   };
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
index 82fd309..48ec0281 100644
--- a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
+++ b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
@@ -79,7 +79,6 @@
   init_params.gpu_memory_buffer_manager = &test_gpu_memory_buffer_manager;
   init_params.pipes.compositor_frame_sink_info = std::move(sink_info);
   init_params.pipes.client_request = std::move(client_request);
-  init_params.enable_surface_synchronization = true;
   auto layer_tree_frame_sink = std::make_unique<AsyncLayerTreeFrameSink>(
       std::move(provider), nullptr, &init_params);
 
@@ -144,7 +143,6 @@
     init_params_.gpu_memory_buffer_manager = &test_gpu_memory_buffer_manager_;
     init_params_.pipes.compositor_frame_sink_info = std::move(sink_info);
     init_params_.pipes.client_request = std::move(client_request);
-    init_params_.enable_surface_synchronization = true;
     init_params_.hit_test_data_provider =
         std::make_unique<viz::HitTestDataProviderDrawQuad>(
             /*should_ask_for_child_region=*/true, /*root_accepts_events=*/true);
diff --git a/chrome/VERSION b/chrome/VERSION
index 109c2f82..ff41ff3 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=78
 MINOR=0
-BUILD=3897
+BUILD=3898
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 9500d992..176e00ab 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -924,6 +924,7 @@
   "java/src/org/chromium/chrome/browser/night_mode/NightModeMetrics.java",
   "java/src/org/chromium/chrome/browser/night_mode/NightModeStateProvider.java",
   "java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java",
+  "java/src/org/chromium/chrome/browser/night_mode/PowerSavingModeMonitor.java",
   "java/src/org/chromium/chrome/browser/night_mode/RemoteViewsWithNightModeInflater.java",
   "java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java",
   "java/src/org/chromium/chrome/browser/notifications/ActionInfo.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 25eca5d..f569c32 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -51,6 +51,7 @@
   "junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java",
+  "junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/CustomTabStatusBarColorProviderTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java",
   "junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
index dd825cc8..9877317 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -24,7 +24,7 @@
  * objects.
  */
 public class TabGridDialogCoordinator implements TabGridDialogMediator.ResetHandler {
-    final static String COMPONENT_NAME = "TabGridDialog";
+    private final String mComponentName;
     private final Context mContext;
     private final TabListCoordinator mTabListCoordinator;
     private final TabGridDialogMediator mMediator;
@@ -39,15 +39,19 @@
             TabGridDialogMediator.AnimationParamsProvider animationParamsProvider) {
         mContext = context;
 
+        mComponentName = animationParamsProvider == null ? "TabGridDialogFromStrip"
+                                                         : "TabGridDialogInSwitcher";
+
         mToolbarPropertyModel = new PropertyModel(TabGridSheetProperties.ALL_KEYS);
 
-        mMediator = new TabGridDialogMediator(context, this, mToolbarPropertyModel,
-                tabModelSelector, tabCreatorManager, resetHandler, animationParamsProvider);
+        mMediator =
+                new TabGridDialogMediator(context, this, mToolbarPropertyModel, tabModelSelector,
+                        tabCreatorManager, resetHandler, animationParamsProvider, mComponentName);
 
         mTabListCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.GRID, context,
                 tabModelSelector, tabContentManager::getTabThumbnailWithCallback, null, false, null,
                 gridCardOnClickListenerProvider, mMediator.getTabGridDialogHandler(), null, null,
-                containerView, null, false, COMPONENT_NAME);
+                containerView, null, false, mComponentName);
 
         mParentLayout = new TabGridDialogParent(context, containerView);
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index 95b857e..ee04480 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -11,6 +11,7 @@
 import android.view.View;
 
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
@@ -79,12 +80,13 @@
     private final TabSwitcherMediator.ResetHandler mTabSwitcherResetHandler;
     private final AnimationParamsProvider mAnimationParamsProvider;
     private final DialogHandler mTabGridDialogHandler;
+    private final String mComponentName;
     private int mCurrentTabId = Tab.INVALID_TAB_ID;
 
     TabGridDialogMediator(Context context, ResetHandler dialogResetHandler, PropertyModel model,
             TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager,
             TabSwitcherMediator.ResetHandler tabSwitcherResetHandler,
-            AnimationParamsProvider animationParamsProvider) {
+            AnimationParamsProvider animationParamsProvider, String componentName) {
         mContext = context;
         mModel = model;
         mTabModelSelector = tabModelSelector;
@@ -93,6 +95,7 @@
         mTabSwitcherResetHandler = tabSwitcherResetHandler;
         mAnimationParamsProvider = animationParamsProvider;
         mTabGridDialogHandler = new DialogHandler();
+        mComponentName = componentName;
 
         // Register for tab model.
         mTabModelObserver = new EmptyTabModelObserver() {
@@ -255,6 +258,7 @@
             @Override
             public void onScrimClick() {
                 hideDialog(true);
+                RecordUserAction.record("TabGridDialog.Exit");
             }
             @Override
             public void onScrimVisibilityChanged(boolean visible) {}
@@ -265,6 +269,7 @@
     private View.OnClickListener getCollapseButtonClickListener() {
         return view -> {
             hideDialog(true);
+            RecordUserAction.record("TabGridDialog.Exit");
         };
     }
 
@@ -287,6 +292,7 @@
             mTabCreatorManager.getTabCreator(currentTab.isIncognito())
                     .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL),
                             TabLaunchType.FROM_CHROME_UI, parentTabToAttach);
+            RecordUserAction.record("MobileNewTabOpened." + mComponentName);
         };
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java
index 0768409f..c100ccc 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java
@@ -159,7 +159,6 @@
                     View selectedItemView = selectedViewHolder.itemView;
                     onTabMergeToGroup(mSelectedTabIndex, mHoveredTabIndex);
                     mRecyclerView.getLayoutManager().removeView(selectedItemView);
-                    RecordUserAction.record("GridTabSwitcher.Drag.AddToGroupOrCreateGroup");
                 }
             }
             mModel.updateSelectedTabForMergeToGroup(mSelectedTabIndex, false);
@@ -180,7 +179,7 @@
                     filter.moveTabOutOfGroup(
                             mModel.get(mUnGroupTabIndex).get(TabProperties.TAB_ID));
                     mRecyclerView.getLayoutManager().removeView(ungroupItemView);
-                    RecordUserAction.record("TabGridDialog.Drag.RemoveFromGroup");
+                    RecordUserAction.record("TabGrid.Drag.RemoveFromGroup." + mComponentName);
                 }
             }
             mHoveredTabIndex = TabModel.INVALID_TAB_INDEX;
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 916c3d37..361124a 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
@@ -24,6 +24,7 @@
 import org.chromium.chrome.browser.tasks.tab_groups.EmptyTabGroupModelFilterObserver;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
+import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -210,7 +211,11 @@
             Tab currentTab = mTabModelSelector.getCurrentTab();
             if (currentTab == null) return;
             mResetHandler.resetGridWithListOfTabs(getRelatedTabsForId(currentTab.getId()));
-            RecordUserAction.record("TabGroup.ExpandedFromStrip");
+            if (FeatureUtilities.isTabGroupsAndroidUiImprovementsEnabled()) {
+                RecordUserAction.record("TabGroup.ExpandedFromStrip.TabGridDialog");
+            } else {
+                RecordUserAction.record("TabGroup.ExpandedFromStrip.TabGridSheet");
+            }
         });
         mToolbarPropertyModel.set(TabStripToolbarViewProperties.ADD_CLICK_LISTENER, view -> {
             Tab currentTab = mTabModelSelector.getCurrentTab();
@@ -224,7 +229,7 @@
             mTabCreatorManager.getTabCreator(currentTab.isIncognito())
                     .createNewTab(new LoadUrlParams(UrlConstants.NTP_URL),
                             TabLaunchType.FROM_CHROME_UI, parentTabToAttach);
-            RecordUserAction.record("MobileNewTabOpened" + TabGroupUiCoordinator.COMPONENT_NAME);
+            RecordUserAction.record("MobileNewTabOpened." + TabGroupUiCoordinator.COMPONENT_NAME);
         });
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 209422a2..7b17100 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -263,8 +263,9 @@
         }
 
         /**
-         * Records Tabs.TabOffsetOfSwitch and MobileTabSwitched for the component only if the
-         * fromTab and toTab have the same filter index.
+         * Records MobileTabSwitched for the component. Also, records Tabs.TabOffsetOfSwitch but
+         * only when fromTab and toTab are within the same group. This method only records UMA
+         * for components other than TabSwitcher.
          *
          * @param fromTab The previous selected tab.
          * @param toTab The new selected tab.
@@ -277,6 +278,8 @@
                                         .getCurrentTabModelFilter()
                                         .indexOf(toTab);
 
+            RecordUserAction.record("MobileTabSwitched." + mComponentName);
+
             if (fromFilterIndex != toFilterIndex) return;
 
             int fromIndex = TabModelUtils.getTabIndexById(
@@ -286,8 +289,6 @@
 
             RecordHistogram.recordSparseHistogram(
                     "Tabs.TabOffsetOfSwitch." + mComponentName, fromIndex - toIndex);
-
-            RecordUserAction.record("MobileTabSwitched." + mComponentName);
         }
     };
 
@@ -534,6 +535,12 @@
 
                     if (!isValidMovePosition(srcIndex) || !isValidMovePosition(desIndex)) return;
                     mModel.removeAt(srcIndex);
+                    if (getRelatedTabsForId(movedTab.getId()).size() == 2) {
+                        // When users use drop-to-merge to create a group.
+                        RecordUserAction.record("TabGroup.Created.DropToMerge");
+                    } else {
+                        RecordUserAction.record("TabGrid.Drag.DropToMerge");
+                    }
 
                     desIndex = srcIndex > desIndex ? desIndex : desIndex - 1;
                     Tab newSelectedTab = mTabModelSelector.getTabModelFilterProvider()
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index f8c6642..197d5cc 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -121,6 +121,7 @@
     private int mModelIndexWhenShown;
     private int mTabIdwhenShown;
     private int mIndexInNewModelWhenSwitched;
+    private boolean mIsSelectingInTabSwitcher;
 
     private boolean mShowTabsInMruOrder;
 
@@ -199,7 +200,8 @@
                     mShouldIgnoreNextSelect = false;
                     return;
                 }
-                if (mContainerViewModel.get(IS_VISIBLE)) {
+                if (mIsSelectingInTabSwitcher) {
+                    mIsSelectingInTabSwitcher = false;
                     TabModelFilter modelFilter = mTabModelSelector.getTabModelFilterProvider()
                                                          .getCurrentTabModelFilter();
                     if (modelFilter instanceof TabGroupModelFilter) {
@@ -208,7 +210,9 @@
 
                     // Use TabSelectionType.From_USER to filter the new tab creation case.
                     if (type == TabSelectionType.FROM_USER) recordUserSwitchedTab(tab, lastId);
+                }
 
+                if (mContainerViewModel.get(IS_VISIBLE)) {
                     onTabSelecting(tab.getId());
                 }
             }
@@ -327,7 +331,6 @@
 
         Tab fromTab = TabModelUtils.getTabById(mTabModelSelector.getCurrentModel(), lastId);
         assert fromTab != null;
-
         if (mModelIndexWhenShown == mTabModelSelector.getCurrentModelIndex()) {
             if (tab.getId() == mTabIdwhenShown) {
                 RecordUserAction.record("MobileTabReturnedToCurrentTab");
@@ -342,8 +345,12 @@
                                       .indexOf(tab);
 
                 if (fromIndex != toIndex || fromTab.getId() == tab.getId()) {
-                    RecordUserAction.record(
-                            "MobileTabSwitched." + TabSwitcherCoordinator.COMPONENT_NAME);
+                    // Only log when you switch a tab page directly from tab switcher.
+                    if (!FeatureUtilities.isTabGroupsAndroidUiImprovementsEnabled()
+                            || getRelatedTabs(tab.getId()).size() == 1) {
+                        RecordUserAction.record(
+                                "MobileTabSwitched." + TabSwitcherCoordinator.COMPONENT_NAME);
+                    }
                     RecordHistogram.recordSparseHistogram(
                             "Tabs.TabOffsetOfSwitch." + TabSwitcherCoordinator.COMPONENT_NAME,
                             fromIndex - toIndex);
@@ -360,7 +367,12 @@
                 // here.
                 RecordUserAction.record("MobileTabSwitched");
             }
-            RecordUserAction.record("MobileTabSwitched." + TabSwitcherCoordinator.COMPONENT_NAME);
+            // Only log when you switch a tab page directly from tab switcher.
+            if (!FeatureUtilities.isTabGroupsAndroidUiImprovementsEnabled()
+                    || getRelatedTabs(tab.getId()).size() == 1) {
+                RecordUserAction.record(
+                        "MobileTabSwitched." + TabSwitcherCoordinator.COMPONENT_NAME);
+            }
         }
     }
 
@@ -530,11 +542,13 @@
                 relatedTabs = null;
             }
             mTabGridDialogResetHandler.resetWithListOfTabs(relatedTabs);
+            RecordUserAction.record("TabGridDialog.ExpandedFromSwitcher");
         };
     }
 
     @Override
     public void onTabSelecting(int tabId) {
+        mIsSelectingInTabSwitcher = true;
         mOnTabSelectingListener.onTabSelecting(LayoutManager.time(), tabId);
     }
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index 884c063c..9794ad5f 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -164,7 +164,7 @@
         mModel = new PropertyModel(TabGridSheetProperties.ALL_KEYS);
         mMediator =
                 new TabGridDialogMediator(mContext, mDialogResetHandler, mModel, mTabModelSelector,
-                        mTabCreatorManager, mTabSwitcherResetHandler, mAnimationParamsProvider);
+                        mTabCreatorManager, mTabSwitcherResetHandler, mAnimationParamsProvider, "");
     }
 
     @After
@@ -417,7 +417,7 @@
         // For strip we don't play zoom-in/zoom-out for show/hide dialog, and thus
         // the animationParamsProvider is null.
         mMediator = new TabGridDialogMediator(mContext, mDialogResetHandler, mModel,
-                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler, null);
+                mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler, null, "");
         // Mock that the dialog is hidden and animation source Rect and header title are all null.
         mModel.set(TabGridSheetProperties.IS_DIALOG_VISIBLE, false);
         mModel.set(TabGridSheetProperties.ANIMATION_PARAMS, null);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
index 9f4f728..daa0a19 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -26,7 +26,9 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
@@ -38,6 +40,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ThemeColorProvider;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.tab.Tab;
@@ -51,6 +54,7 @@
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
+import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
 
@@ -64,6 +68,9 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class TabGroupUiMediatorUnitTest {
+    @Rule
+    public TestRule mProcessor = new Features.JUnitProcessor();
+
     private static final int TAB1_ID = 456;
     private static final int TAB2_ID = 789;
     private static final int TAB3_ID = 123;
@@ -291,7 +298,10 @@
     }
 
     @Test
-    public void onClickExpand() {
+    @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
+            ChromeFeatureList.TAB_GROUPS_UI_IMPROVEMENTS_ANDROID})
+    public void
+    onClickExpand() {
         initAndAssertProperties(mTab2);
 
         View.OnClickListener listener =
diff --git a/chrome/android/java/res/layout/navigation_sheet.xml b/chrome/android/java/res/layout/navigation_sheet.xml
index 33f138c..6aaaa44 100644
--- a/chrome/android/java/res/layout/navigation_sheet.xml
+++ b/chrome/android/java/res/layout/navigation_sheet.xml
@@ -12,5 +12,6 @@
         android:layout_height="match_parent"
         android:divider="@null"
         android:dividerHeight="0dp"
-        android:paddingTop="@dimen/navigation_sheet_content_top_padding" />
+        android:paddingTop="@dimen/navigation_sheet_content_top_padding"
+        android:paddingBottom="@dimen/navigation_sheet_content_bottom_padding" />
 </org.chromium.chrome.browser.gesturenav.NavigationSheetView>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index 5a8e090..f20f7f7 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -172,6 +172,10 @@
     <color name="payments_section_edit_background">@color/modern_secondary_color</color>
     <color name="payments_section_chevron">#B2B2B2</color>
 
+    <!-- History Navigation UI colors -->
+    <color name="navigation_bubble_background_color">@color/default_bg_color_elev_2</color>
+    <color name="navigation_bubble_arrow">@android:color/black</color>
+
     <!-- Scrollbar colors -->
     <color name="default_scroll_thumb">@color/modern_grey_800_alpha_38</color>
 
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index f5099c1..cadb70a9 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -657,7 +657,8 @@
     <dimen name="navigation_bubble_text_end_padding">8dp</dimen>
     <dimen name="navigation_sheet_toolbar_bottom_padding">44dp</dimen>
     <dimen name="navigation_sheet_content_top_padding">18dp</dimen>
-    <dimen name="navigation_sheet_content_bottom_padding">8dp</dimen>
+    <dimen name="navigation_sheet_content_bottom_padding">4dp</dimen>
+    <dimen name="navigation_sheet_content_wrap_padding">4dp</dimen>
 
     <!-- ChromeTextInputLayout dimensions -->
     <dimen name="text_input_layout_padding_start">3dp</dimen>
diff --git a/chrome/android/java/res_night/values-night/colors.xml b/chrome/android/java/res_night/values-night/colors.xml
index 6893531..80addf6 100644
--- a/chrome/android/java/res_night/values-night/colors.xml
+++ b/chrome/android/java/res_night/values-night/colors.xml
@@ -32,6 +32,9 @@
     <color name="photo_picker_tile_bg_color">@color/modern_grey_800</color>
     <color name="photo_picker_special_tile_bg_color">@color/modern_grey_800</color>
 
+    <!-- History Navigation UI colors -->
+    <color name="navigation_bubble_arrow">@android:color/white</color>
+
     <!-- Scrollbar colors -->
     <color name="default_scroll_thumb">@color/white_alpha_20</color>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
index 0fa804f..77aa6c07 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -462,7 +462,6 @@
     @CalledByNative
     private void notifyWillUseSurfaceControl() {
         mIsSurfaceControlEnabled = true;
-        mCompositorSurfaceManager.requestSurface(getSurfacePixelFormat());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 9d058df..246a000 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -77,6 +77,8 @@
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
+import org.chromium.chrome.browser.night_mode.PowerSavingModeMonitor;
+import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
 import org.chromium.chrome.browser.page_info.PageInfoController;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabAssociatedApp;
@@ -290,7 +292,10 @@
 
     @Override
     protected NightModeStateProvider createNightModeStateProvider() {
-        mNightModeStateController = new CustomTabNightModeStateController(getLifecycleDispatcher());
+        // This is called before Dagger component is created, so using getInstance() directly.
+        mNightModeStateController = new CustomTabNightModeStateController(getLifecycleDispatcher(),
+                SystemNightModeMonitor.getInstance(),
+                PowerSavingModeMonitor.getInstance());
         return mNightModeStateController;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java
index f7e9540c..3168b55 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
+import org.chromium.chrome.browser.night_mode.PowerSavingModeMonitor;
 import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
@@ -22,9 +23,12 @@
 /**
  * Maintains and provides the night mode state for {@link CustomTabActivity}.
  */
-public class CustomTabNightModeStateController
-        implements Destroyable, NightModeStateProvider, SystemNightModeMonitor.Observer {
+public class CustomTabNightModeStateController implements Destroyable, NightModeStateProvider {
     private final ObserverList<Observer> mObservers = new ObserverList<>();
+    private final PowerSavingModeMonitor mPowerSavingModeMonitor;
+    private final SystemNightModeMonitor mSystemNightModeMonitor;
+    private final SystemNightModeMonitor.Observer mSystemNightModeObserver = this::updateNightMode;
+    private final Runnable mPowerSaveModeObserver = this::updateNightMode;
 
     /**
      * The color scheme requested for the CCT. Only {@link CustomTabsIntent#COLOR_SCHEME_LIGHT}
@@ -34,11 +38,13 @@
     private int mRequestedColorScheme;
     private AppCompatDelegate mAppCompatDelegate;
 
-    /**
-     * @param lifecycleDispatcher The {@link ActivityLifecycleDispatcher} that will notify this
-     *                            class about lifecycle changes.
-     */
-    CustomTabNightModeStateController(ActivityLifecycleDispatcher lifecycleDispatcher) {
+    private boolean mIsInNightMode;
+
+    CustomTabNightModeStateController(ActivityLifecycleDispatcher lifecycleDispatcher,
+            SystemNightModeMonitor systemNightModeMonitor,
+            PowerSavingModeMonitor powerSavingModeMonitor) {
+        mSystemNightModeMonitor = systemNightModeMonitor;
+        mPowerSavingModeMonitor = powerSavingModeMonitor;
         lifecycleDispatcher.register(this);
     }
 
@@ -62,29 +68,25 @@
 
         updateNightMode();
 
-        // No need to observe system night mode if the intent specifies a light/dark color scheme.
+        // No need to observe system settings if the intent specifies a light/dark color scheme.
         if (mRequestedColorScheme == CustomTabsIntent.COLOR_SCHEME_SYSTEM) {
-            SystemNightModeMonitor.getInstance().addObserver(this);
+            mSystemNightModeMonitor.addObserver(mSystemNightModeObserver);
+            mPowerSavingModeMonitor.addObserver(mPowerSaveModeObserver);
         }
     }
 
     // Destroyable implementation.
     @Override
     public void destroy() {
-        SystemNightModeMonitor.getInstance().removeObserver(this);
+        mSystemNightModeMonitor.removeObserver(mSystemNightModeObserver);
+        mPowerSavingModeMonitor.removeObserver(mPowerSaveModeObserver);
     }
 
     // NightModeStateProvider implementation.
     @Override
     public boolean isInNightMode() {
-        switch (mRequestedColorScheme) {
-            case CustomTabsIntent.COLOR_SCHEME_LIGHT:
-                return false;
-            case CustomTabsIntent.COLOR_SCHEME_DARK:
-                return true;
-            default:
-                return SystemNightModeMonitor.getInstance().isSystemNightModeOn();
-        }
+        return mIsInNightMode;
+
     }
 
     @Override
@@ -104,19 +106,27 @@
         return false;
     }
 
-    // SystemNightModeMonitor.Observer implementation.
-    @Override
-    public void onSystemNightModeChanged() {
-        updateNightMode();
-        // We need to notify observers on system night mode change so that activities can be
-        // restarted as needed (we do not handle color scheme changes during runtime). No need to
-        // check for color scheme because we don't observe system night mode for light/dark color
-        // scheme.
-        for (Observer observer : mObservers) observer.onNightModeStateChanged();
+    private void updateNightMode() {
+        boolean shouldBeInNightMode = shouldBeInNightMode();
+        if (mIsInNightMode == shouldBeInNightMode) return;
+
+        mIsInNightMode = shouldBeInNightMode;
+        mAppCompatDelegate.setLocalNightMode(mIsInNightMode ? AppCompatDelegate.MODE_NIGHT_YES
+                                                             : AppCompatDelegate.MODE_NIGHT_NO);
+        for (Observer observer : mObservers) {
+            observer.onNightModeStateChanged();
+        }
     }
 
-    private void updateNightMode() {
-        mAppCompatDelegate.setLocalNightMode(isInNightMode() ? AppCompatDelegate.MODE_NIGHT_YES
-                                                             : AppCompatDelegate.MODE_NIGHT_NO);
+    private boolean shouldBeInNightMode() {
+        switch (mRequestedColorScheme) {
+            case CustomTabsIntent.COLOR_SCHEME_LIGHT:
+                return false;
+            case CustomTabsIntent.COLOR_SCHEME_DARK:
+                return true;
+            default:
+                return mSystemNightModeMonitor.isSystemNightModeOn() ||
+                        mPowerSavingModeMonitor.powerSavingIsOn();
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java
index 7ac7ed0..d00d222b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java
@@ -6,6 +6,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.PorterDuff.Mode;
 import android.os.Build;
 import android.support.annotation.DrawableRes;
 import android.util.AttributeSet;
@@ -70,12 +71,15 @@
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
             setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         }
-        mBlack = ApiCompatibilityUtils.getColor(getResources(), android.R.color.black);
+        mBlack = ApiCompatibilityUtils.getColor(getResources(), R.color.navigation_bubble_arrow);
         mBlue = ApiCompatibilityUtils.getColor(getResources(), R.color.default_icon_color_blue);
 
         mColorUpdateListener = new ColorUpdateListener();
         mColorAnimator = ValueAnimator.ofFloat(0, 1).setDuration(COLOR_TRANSITION_DURATION_MS);
         mColorAnimator.addUpdateListener(mColorUpdateListener);
+        getBackground().setColorFilter(ApiCompatibilityUtils.getColor(getResources(),
+                                               R.color.navigation_bubble_background_color),
+                Mode.MULTIPLY);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
index 643a7c20..65cc9a92 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
@@ -6,7 +6,6 @@
 
 import android.content.Context;
 import android.os.Handler;
-import android.view.HapticFeedbackConstants;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -119,9 +118,7 @@
         listview.setAdapter(mModelAdapter);
 
         mSheetPeekRunnable = () -> {
-            if (isVisible()) return;
-            parent.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-            peek(mForward);
+            if (!isVisible()) peek(mForward);
         };
 
         mPeekSheetThreshold =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java
index 24bdb96..1a4dcfa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetView.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.gesturenav;
 
 import android.content.Context;
+import android.support.annotation.IdRes;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ListView;
@@ -30,10 +31,13 @@
     public NavigationSheetView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mItemHeight = getResources().getDimensionPixelSize(R.dimen.navigation_popup_item_height);
-        mContentPadding =
-                getResources().getDimensionPixelSize(R.dimen.navigation_sheet_content_top_padding)
-                + getResources().getDimensionPixelSize(
-                        R.dimen.navigation_sheet_content_bottom_padding);
+        mContentPadding = getSizePx(context, R.dimen.navigation_sheet_content_top_padding)
+                + getSizePx(context, R.dimen.navigation_sheet_content_bottom_padding)
+                + getSizePx(context, R.dimen.navigation_sheet_content_wrap_padding);
+    }
+
+    private static int getSizePx(Context context, @IdRes int id) {
+        return context.getResources().getDimensionPixelSize(id);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java
index 07865db1..33643ef 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java
@@ -6,21 +6,12 @@
 
 import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.UI_THEME_SETTING_KEY;
 
-import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Build;
-import android.os.PowerManager;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.v7.app.AppCompatDelegate;
 import android.text.TextUtils;
 
 import org.chromium.base.ApplicationState;
 import org.chromium.base.ApplicationStatus;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.preferences.themes.ThemePreferences;
@@ -34,6 +25,9 @@
     private final ObserverList<Observer> mObservers = new ObserverList<>();
     private final SystemNightModeMonitor mSystemNightModeMonitor;
     private final ChromePreferenceManager mChromePreferenceManager;
+    private final PowerSavingModeMonitor mPowerSaveModeMonitor;
+
+    private final Runnable mPowerSaveModeObserver = this::updateNightMode;
 
     /**
      * Whether night mode is enabled throughout the entire app. If null, night mode is not
@@ -42,11 +36,6 @@
     private Boolean mNightModeOn;
     private ChromePreferenceManager.Observer mPreferenceObserver;
 
-    /** Whether power save mode is on. This is always false on pre-L. */
-    private boolean mPowerSaveModeOn;
-    private @Nullable PowerManager mPowerManager;
-    private @Nullable BroadcastReceiver mPowerModeReceiver;
-
     /** Whether this class has started listening to relevant states for night mode. */
     private boolean mIsStarted;
 
@@ -55,19 +44,22 @@
      * {@link GlobalNightModeStateProviderHolder#getInstance()} instead.
      * @param systemNightModeMonitor The {@link SystemNightModeMonitor} that maintains the system
      *                               night mode state.
+     * @param powerSaveModeMonitor The {@link PowerSavingModeMonitor} that maintains the system
+     *                              power saving setting.
      * @param chromePreferenceManager The {@link ChromePreferenceManager} that maintains shared
      *                                preferences.
      */
     GlobalNightModeStateController(@NonNull SystemNightModeMonitor systemNightModeMonitor,
+            @NonNull PowerSavingModeMonitor powerSaveModeMonitor,
             @NonNull ChromePreferenceManager chromePreferenceManager) {
         mSystemNightModeMonitor = systemNightModeMonitor;
         mChromePreferenceManager = chromePreferenceManager;
+        mPowerSaveModeMonitor = powerSaveModeMonitor;
 
         mPreferenceObserver = key -> {
             if (TextUtils.equals(key, UI_THEME_SETTING_KEY)) updateNightMode();
         };
 
-        initializeForPowerSaveMode();
         updateNightMode();
 
         // It is unlikely that this is called after an activity is stopped or destroyed, but
@@ -117,12 +109,8 @@
         if (mIsStarted) return;
         mIsStarted = true;
 
-        if (mPowerModeReceiver != null) {
-            updatePowerSaveMode();
-            ContextUtils.getApplicationContext().registerReceiver(mPowerModeReceiver,
-                    new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
-        }
         mSystemNightModeMonitor.addObserver(this);
+        mPowerSaveModeMonitor.addObserver(mPowerSaveModeObserver);
         mChromePreferenceManager.addObserver(mPreferenceObserver);
         updateNightMode();
     }
@@ -132,17 +120,16 @@
         if (!mIsStarted) return;
         mIsStarted = false;
 
-        if (mPowerModeReceiver != null) {
-            ContextUtils.getApplicationContext().unregisterReceiver(mPowerModeReceiver);
-        }
         mSystemNightModeMonitor.removeObserver(this);
+        mPowerSaveModeMonitor.removeObserver(mPowerSaveModeObserver);
         mChromePreferenceManager.removeObserver(mPreferenceObserver);
     }
 
     private void updateNightMode() {
+        boolean powerSaveModeOn = mPowerSaveModeMonitor.powerSavingIsOn();
         final int themeSetting = mChromePreferenceManager.readInt(UI_THEME_SETTING_KEY);
         final boolean newNightModeOn = themeSetting == ThemePreferences.ThemeSetting.SYSTEM_DEFAULT
-                        && (mPowerSaveModeOn || mSystemNightModeMonitor.isSystemNightModeOn())
+                        && (powerSaveModeOn || mSystemNightModeMonitor.isSystemNightModeOn())
                 || themeSetting == ThemePreferences.ThemeSetting.DARK;
         if (mNightModeOn != null && newNightModeOn == mNightModeOn) return;
 
@@ -154,28 +141,7 @@
         NightModeMetrics.recordNightModeState(mNightModeOn);
         NightModeMetrics.recordThemePreferencesState(themeSetting);
         if (mNightModeOn) {
-            NightModeMetrics.recordNightModeEnabledReason(themeSetting, mPowerSaveModeOn);
+            NightModeMetrics.recordNightModeEnabledReason(themeSetting, powerSaveModeOn);
         }
     }
-
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    private void initializeForPowerSaveMode() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
-        mPowerManager = (PowerManager) ContextUtils.getApplicationContext().getSystemService(
-                Context.POWER_SERVICE);
-        updatePowerSaveMode();
-        mPowerModeReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                updatePowerSaveMode();
-                updateNightMode();
-            }
-        };
-    }
-
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    private void updatePowerSaveMode() {
-        mPowerSaveModeOn = mPowerManager.isPowerSaveMode();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
index d50a3722..87a0bad6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateProviderHolder.java
@@ -63,6 +63,7 @@
                 sInstance = new DummyNightModeStateProvider();
             } else {
                 sInstance = new GlobalNightModeStateController(SystemNightModeMonitor.getInstance(),
+                        PowerSavingModeMonitor.getInstance(),
                         ChromePreferenceManager.getInstance());
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/PowerSavingModeMonitor.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/PowerSavingModeMonitor.java
new file mode 100644
index 0000000..ac0f27d2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/PowerSavingModeMonitor.java
@@ -0,0 +1,114 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.night_mode;
+
+import android.annotation.TargetApi;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+import android.os.PowerManager;
+import android.support.annotation.Nullable;
+
+import org.chromium.base.ApplicationState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.ObserverList;
+
+/**
+ * Observes and keeps a record of whether the system power saving mode is on.
+ */
+public class PowerSavingModeMonitor {
+    private static PowerSavingModeMonitor sInstance;
+
+    /** Returns the instance of this singleton. */
+    public static PowerSavingModeMonitor getInstance() {
+        if (sInstance == null) {
+            sInstance = new PowerSavingModeMonitor();
+        }
+        return sInstance;
+    }
+
+    private final ObserverList<Runnable> mObservers = new ObserverList<>();
+    @Nullable private final PowerManager mPowerManager;
+    @Nullable private BroadcastReceiver mPowerModeReceiver;
+
+    private boolean mPowerSavingIsOn;
+
+    /** Returns whether power saving mode is currently on. */
+    public boolean powerSavingIsOn() {
+        return mPowerSavingIsOn;
+    }
+
+    /** Adds an observer of power saving mode changes. */
+    public void addObserver(Runnable observer) {
+        mObservers.addObserver(observer);
+    }
+
+    /** Removes an observer of power saving mode changes. */
+    public void removeObserver(Runnable observer) {
+        mObservers.removeObserver(observer);
+    }
+
+    private PowerSavingModeMonitor() {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            // Power manager not available before Lollipop. mPowerSavingIsOn is false forever.
+            mPowerManager = null;
+            return;
+        }
+        mPowerManager = (PowerManager) ContextUtils.getApplicationContext().getSystemService(
+                Context.POWER_SERVICE);
+
+        updatePowerSaveMode();
+        updateAccordingToAppState();
+        ApplicationStatus.registerApplicationStateListener(state -> updateAccordingToAppState());
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    private void updateAccordingToAppState() {
+        final int applicationState = ApplicationStatus.getStateForApplication();
+        if (applicationState == ApplicationState.HAS_RUNNING_ACTIVITIES
+                || applicationState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
+            start();
+        } else {
+            stop();
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    private void start() {
+        if (mPowerModeReceiver == null) {
+            mPowerModeReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    updatePowerSaveMode();
+                }
+            };
+            ContextUtils.getApplicationContext().registerReceiver(mPowerModeReceiver,
+                    new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
+        }
+        updatePowerSaveMode();
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    private void stop() {
+        if (mPowerModeReceiver != null) {
+            ContextUtils.getApplicationContext().unregisterReceiver(mPowerModeReceiver);
+            mPowerModeReceiver = null;
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    private void updatePowerSaveMode() {
+        boolean newValue = mPowerManager != null && mPowerManager.isPowerSaveMode();
+        if (newValue == mPowerSavingIsOn) return;
+
+        mPowerSavingIsOn = newValue;
+        for (Runnable observer : mObservers) {
+            observer.run();
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java
index bd1dd987..f89ec4d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/SystemNightModeMonitor.java
@@ -8,7 +8,6 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ObserverList;
-import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeApplication;
 
 /**
@@ -77,9 +76,4 @@
         mSystemNightModeOn =
                 (uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
     }
-
-    @VisibleForTesting
-    void notifyObserversForTesting() {
-        for (Observer observer : mObservers) observer.onSystemNightModeChanged();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
index dd6084e..144648c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -50,6 +50,12 @@
     void setAutocompleteProfile(Profile profile);
 
     /**
+     * Specify whether location bar should present icons when focused.
+     * @param showIcon True if we should show the icons when the url is focused.
+     */
+    void setShowIconsWhenUrlFocused(boolean showIcon);
+
+    /**
      * Call to force the UI to update the state of various buttons based on whether or not the
      * current tab is incognito.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index bc4294c7..ded2f152a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -355,6 +355,11 @@
         mOmniboxPrerender.initializeForProfile(profile);
     }
 
+    @Override
+    public void setShowIconsWhenUrlFocused(boolean showIcon) {
+        mStatusViewCoordinator.setShowIconsWhenUrlFocused(showIcon);
+    }
+
     /** Focuses the current page. */
     private void focusCurrentTab() {
         if (mToolbarDataProvider.hasTab()) getCurrentTab().requestFocus();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index b220c0b..81546ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -65,7 +65,7 @@
         if (mShouldShowSearchEngineLogo) {
             mFirstVisibleFocusedView = findViewById(R.id.location_bar_status);
         }
-        mStatusViewCoordinator.setShowIconsWhenUrlFocused(shouldShowSearchEngineLogo);
+        setShowIconsWhenUrlFocused(shouldShowSearchEngineLogo);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
index 1c1ef4c..19e29e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.VisibleForTesting;
+import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.favicon.FaviconHelper;
@@ -21,6 +22,7 @@
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
+import org.chromium.content_public.browser.BrowserStartupController;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -49,7 +51,11 @@
     public static boolean shouldShowSearchEngineLogo() {
         return !LocaleManager.getInstance().needToCheckForSearchEnginePromo()
                 && ChromeFeatureList.isInitialized()
-                && ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO);
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO)
+                // Using the profile now, so we need to pay attention to browser initialization.
+                && BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                           .isFullBrowserStarted()
+                && !Profile.getLastUsedProfile().isOffTheRecord();
     }
 
     public static boolean shouldRoundedSearchEngineLogo() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
index 8817cd24..0642bfb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -37,7 +37,6 @@
     private boolean mPageIsOffline;
     private boolean mShowStatusIconWhenUrlFocused;
     private boolean mIsSecurityButtonShown;
-    private boolean mShouldShowSearchEngineLogo;
     private boolean mIsSearchEngineGoogle;
     private boolean mShouldCancelCustomFavicon;
 
@@ -305,7 +304,6 @@
         mModel.set(StatusProperties.STATUS_ICON_TINT_RES, 0);
 
         mIsSearchEngineGoogle = isSearchEngineGoogle;
-        mShouldShowSearchEngineLogo = shouldShowSearchEngineLogo;
         updateLocationBarIcon();
     }
 
@@ -337,7 +335,7 @@
                 && mToolbarCommonPropertiesModel.getDisplaySearchTerms() != null
                 && SearchEngineLogoUtils.doesUrlMatchDefaultSearchEngine(
                         mToolbarCommonPropertiesModel.getCurrentUrl());
-        if (mShouldShowSearchEngineLogo
+        if (SearchEngineLogoUtils.shouldShowSearchEngineLogo()
                 && (showFocused || showUnfocusedNewTabPage || showUnfocusedSearchResultsPage)) {
             mShouldCancelCustomFavicon = false;
             mModel.set(StatusProperties.STATUS_ICON_TINT_RES, /* no tint */ 0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
index 5bef816..5932ba2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
@@ -26,7 +26,8 @@
     static final WritableIntPropertyKey STATUS_ICON_TINT_RES = new WritableIntPropertyKey();
 
     /** Specifies the icon. */
-    static final WritableObjectPropertyKey<Bitmap> STATUS_ICON = new WritableObjectPropertyKey<>();
+    static final WritableObjectPropertyKey<Bitmap> STATUS_ICON =
+            new WritableObjectPropertyKey<>(true);
 
     /** Specifies accessibility string presented to user upon long click on security icon. */
     public static final WritableIntPropertyKey STATUS_ICON_ACCESSIBILITY_TOAST_RES =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
index 9934919..e7c9661 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
@@ -93,6 +93,7 @@
                     IntentHandler.PACKAGE_GSA, imageUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
         }
         Intent intent = new Intent(Intent.ACTION_VIEW).setData(lensUri);
+        intent.setPackage(IntentHandler.PACKAGE_GSA);
         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         return intent;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index b5b7c93..0f37cc99 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1872,6 +1872,8 @@
                     mAppMenuPropertiesDelegate.setBookmarkBridge(mBookmarkBridge);
                 }
                 mLocationBar.setAutocompleteProfile(profile);
+                mLocationBar.setShowIconsWhenUrlFocused(
+                        SearchEngineLogoUtils.shouldShowSearchEngineLogo());
             }
             mCurrentProfile = profile;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
index 050ffab5..d57745de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -829,6 +829,9 @@
         public void setAutocompleteProfile(Profile profile) {}
 
         @Override
+        public void setShowIconsWhenUrlFocused(boolean showIcon) {}
+
+        @Override
         public int getUrlContainerMarginEnd() {
             return 0;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
index cdf435a..8603a85 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -427,7 +427,7 @@
             @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap,
             ShareTarget shareTarget, String shareTargetActivityName, boolean forceNavigation,
             boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) {
-        super(WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName, url, scope, primaryIcon, name,
+        super(WebappRegistry.webApkIdForPackage(webApkPackageName), url, scope, primaryIcon, name,
                 shortName, displayMode, orientation, source, themeColor, backgroundColor,
                 defaultBackgroundColor, false /* isIconGenerated */,
                 isPrimaryIconMaskable /* isIconAdaptive */, forceNavigation);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
index f6a416b..5f34856 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
@@ -13,7 +13,6 @@
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.metrics.WebApkUma;
-import org.chromium.webapk.lib.common.WebApkConstants;
 
 /**
  * Java counterpart to webapk_installer.h
@@ -80,7 +79,7 @@
 
                 // Stores the source info of WebAPK in WebappDataStorage.
                 WebappRegistry.getInstance().register(
-                        WebApkConstants.WEBAPK_ID_PREFIX + packageName,
+                        WebappRegistry.webApkIdForPackage(packageName),
                         new WebappRegistry.FetchWebappDataStorageCallback() {
                             @Override
                             public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkManagedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkManagedActivity.java
index 0acf963..46ef9ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkManagedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkManagedActivity.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.webapps;
 
-import org.chromium.webapk.lib.common.WebApkConstants;
-
 /**
  * Type of WebApkActivity and it is targeted on Android versions older than L, similar to
  * WebappManagedActivity for WebappActivity.
@@ -28,7 +26,7 @@
 
     @Override
     protected String getActivityId() {
-        return WebApkConstants.WEBAPK_ID_PREFIX + String.valueOf(mActivityIndex);
+        return WebappRegistry.webApkIdForPackage(String.valueOf(mActivityIndex));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
index 595c9af..defa15a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -86,6 +86,13 @@
     }
 
     /**
+     * Returns the {@link WebappDataStorage} id for the passed-in WebAPK package name.
+     */
+    public static String webApkIdForPackage(String webApkPackageName) {
+        return WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName;
+    }
+
+    /**
      * Warm up the WebappRegistry and a specific WebappDataStorage SharedPreferences.
      * @param id The web app id to warm up in addition to the WebappRegistry.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index 8a154bf..cd4eec1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -9,6 +9,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.Rect;
 import android.os.Build;
 import android.support.annotation.IntDef;
@@ -21,6 +22,7 @@
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
+import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ObserverList;
 import org.chromium.base.Supplier;
 import org.chromium.base.VisibleForTesting;
@@ -516,7 +518,8 @@
 
         mToolbarHolder =
                 (TouchRestrictingFrameLayout) findViewById(R.id.bottom_sheet_toolbar_container);
-        mToolbarHolder.setBackgroundResource(R.drawable.top_round);
+        setBackground(mToolbarHolder);
+
         mDefaultToolbarView = mToolbarHolder.findViewById(R.id.bottom_sheet_toolbar);
 
         mActivity = activity;
@@ -526,8 +529,7 @@
         mBottomSheetContentContainer =
                 (TouchRestrictingFrameLayout) findViewById(R.id.bottom_sheet_content);
         mBottomSheetContentContainer.setBottomSheet(this);
-        mBottomSheetContentContainer.setBackgroundResource(R.drawable.top_round);
-
+        setBackground(mBottomSheetContentContainer);
         mDpToPx = mActivity.getResources().getDisplayMetrics().density;
 
         // Listen to height changes on the root.
@@ -658,6 +660,18 @@
         mSheetContainer.removeView(this);
     }
 
+    /**
+     * Sets the background with round corner drawable, adjusts the color for dark mode.
+     * @param view View in BottomSheet to set the drawable to.
+     */
+    private static void setBackground(View view) {
+        view.setBackgroundResource(R.drawable.top_round);
+        view.getBackground().setColorFilter(
+                ApiCompatibilityUtils.getColor(
+                        view.getContext().getResources(), org.chromium.ui.R.color.sheet_bg_color),
+                Mode.MULTIPLY);
+    }
+
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
index 38be979..c596840 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java
@@ -13,11 +13,13 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
 import java.io.File;
@@ -25,6 +27,7 @@
 /**
  * Test content URI can be generated correctly by {@link DownloadFileProvider}.
  */
+@RunWith(ChromeJUnit4ClassRunner.class)
 public class DownloadFileProviderTest {
     private static final String PRIMARY_STORAGE_DOWNLOAD_DIRECTORY_PATH =
             "/storage/emulated/1234/Download";
diff --git a/chrome/android/junit/DEPS b/chrome/android/junit/DEPS
index 3c0e0e1..69fb45d 100644
--- a/chrome/android/junit/DEPS
+++ b/chrome/android/junit/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "!clank/java/src/org/chromium/chrome/browser/AppHooksImpl.java",
+  "+chrome/lib/lifecycle/public",
   "+components/autofill/android/java/src/org/chromium/components/autofill",
   "+components/background_task_scheduler/android",
   "+components/bookmarks/common/android",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java
new file mode 100644
index 0000000..799b66e
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java
@@ -0,0 +1,165 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_SYSTEM;
+
+import android.content.Intent;
+import android.support.v7.app.AppCompatDelegate;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
+import org.chromium.chrome.browser.night_mode.PowerSavingModeMonitor;
+import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
+import org.chromium.chrome.browser.util.FeatureUtilities;
+
+import androidx.browser.customtabs.CustomTabsIntent;
+
+/**
+ * Tests for {@link CustomTabNightModeStateController}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class CustomTabNightModeStateControllerTest {
+    @Mock
+    private PowerSavingModeMonitor mPowerSavingModeMonitor;
+    @Mock
+    private SystemNightModeMonitor mSystemNightModeMonitor;
+    @Mock
+    private ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
+    @Mock
+    private AppCompatDelegate mAppCompatDelegate;
+    @Captor
+    private ArgumentCaptor<SystemNightModeMonitor.Observer> mSystemNightModeObserverCaptor;
+    @Captor
+    private ArgumentCaptor<Runnable> mPowerSavingObserverCaptor;
+
+    private CustomTabNightModeStateController mNightModeController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        doNothing().when(mSystemNightModeMonitor).addObserver(
+                mSystemNightModeObserverCaptor.capture());
+        doNothing().when(mPowerSavingModeMonitor).addObserver(
+                mPowerSavingObserverCaptor.capture());
+        mNightModeController = new CustomTabNightModeStateController(mActivityLifecycleDispatcher,
+                mSystemNightModeMonitor, mPowerSavingModeMonitor);
+        FeatureUtilities.setNightModeForCustomTabsAvailableForTesting(true);
+    }
+
+    @After
+    public void tearDown() {
+        FeatureUtilities.setNightModeForCustomTabsAvailableForTesting(false);
+    }
+
+    @Test
+    public void nightModeIfOff_WhenSchemeForced() {
+        initializeWithColorScheme(COLOR_SCHEME_LIGHT);
+        assertFalse(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void nightModeIfOn_WhenSchemeForced() {
+        initializeWithColorScheme(COLOR_SCHEME_DARK);
+        assertTrue(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void ignoresSystemSetting_WhenSchemeForced() {
+        initializeWithColorScheme(COLOR_SCHEME_LIGHT);
+        setSystemNightMode(true);
+        assertFalse(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void ignoresPowerSaving_WhenSchemeForced() {
+        initializeWithColorScheme(COLOR_SCHEME_LIGHT);
+        setPowerSavingMode(true);
+        assertFalse(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void followsSystemSetting_WhenSchemeIsSystem() {
+        setSystemNightMode(true);
+        initializeWithColorScheme(COLOR_SCHEME_SYSTEM);
+        assertTrue(mNightModeController.isInNightMode());
+
+        setSystemNightMode(false);
+        assertFalse(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void followsPowerSavingMode_WhenSchemeIsSystem() {
+        setPowerSavingMode(true);
+        initializeWithColorScheme(COLOR_SCHEME_SYSTEM);
+        assertTrue(mNightModeController.isInNightMode());
+
+        setPowerSavingMode(false);
+        assertFalse(mNightModeController.isInNightMode());
+    }
+
+    @Test
+    public void notifiesObservers_WhenNightModeChanged() {
+        NightModeStateProvider.Observer observer = mock(NightModeStateProvider.Observer.class);
+        initializeWithColorScheme(COLOR_SCHEME_SYSTEM);
+        mNightModeController.addObserver(observer);
+        setSystemNightMode(true);
+        verify(observer).onNightModeStateChanged();
+    }
+
+    @Test
+    public void doesntNotifyObservers_WhenNightModeDoesntChange() {
+        // Extra calls to observers may lead to unnecessary activity restarts
+        setSystemNightMode(true);
+        NightModeStateProvider.Observer observer = mock(NightModeStateProvider.Observer.class);
+        initializeWithColorScheme(COLOR_SCHEME_SYSTEM);
+        mNightModeController.addObserver(observer);
+        setPowerSavingMode(true);
+        verify(observer, never()).onNightModeStateChanged();
+    }
+
+    private void initializeWithColorScheme(int colorScheme) {
+        Intent intent = new CustomTabsIntent.Builder().setColorScheme(colorScheme).build().intent;
+        mNightModeController.initialize(mAppCompatDelegate, intent);
+    }
+
+    private void setPowerSavingMode(boolean isPowerSaving) {
+        when(mPowerSavingModeMonitor.powerSavingIsOn()).thenReturn(isPowerSaving);
+        for (Runnable observer : mPowerSavingObserverCaptor.getAllValues()) {
+            observer.run();
+        }
+    }
+
+    private void setSystemNightMode(boolean isInNightMode) {
+        when(mSystemNightModeMonitor.isSystemNightModeOn()).thenReturn(isInNightMode);
+        for (SystemNightModeMonitor.Observer observer :
+                mSystemNightModeObserverCaptor.getAllValues()) {
+            observer.onSystemNightModeChanged();
+        }
+    }
+
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java
index 87954d1..c9c3897 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java
@@ -6,31 +6,26 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
+import static org.mockito.AdditionalAnswers.answerVoid;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.robolectric.Shadows.shadowOf;
 
 import static org.chromium.base.ApplicationState.HAS_RUNNING_ACTIVITIES;
 import static org.chromium.base.ApplicationState.HAS_STOPPED_ACTIVITIES;
 import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.UI_THEME_SETTING_KEY;
 
-import android.content.Context;
-import android.content.Intent;
-import android.os.PowerManager;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
+import org.mockito.stubbing.VoidAnswer1;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowPowerManager;
 
-import org.chromium.base.ContextUtils;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.preferences.themes.ThemePreferences;
@@ -46,15 +41,25 @@
 
     private GlobalNightModeStateController mGlobalNightModeStateController;
 
+    @Mock
     private SystemNightModeMonitor mSystemNightModeMonitor;
 
+    private SystemNightModeMonitor.Observer mSystemNightModeObserver;
+
+    @Mock
+    private PowerSavingModeMonitor mPowerSavingMonitor;
+
+    private Runnable mPowerModeObserver;
+
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        captureObservers();
 
-        mSystemNightModeMonitor = spy(SystemNightModeMonitor.getInstance());
         mGlobalNightModeStateController = new GlobalNightModeStateController(
-                mSystemNightModeMonitor, ChromePreferenceManager.getInstance());
+                mSystemNightModeMonitor, mPowerSavingMonitor,
+                ChromePreferenceManager.getInstance());
 
         mGlobalNightModeStateController.onApplicationStateChange(HAS_RUNNING_ACTIVITIES);
 
@@ -62,6 +67,23 @@
         assertFalse(GlobalNightModeStateProviderHolder.getInstance().isInNightMode());
     }
 
+    private void captureObservers() {
+        // We need to mock removeObserver as well as addObserver, so can't use ArgumentCaptor.
+        doAnswer(answerVoid((VoidAnswer1<SystemNightModeMonitor.Observer>)
+                observer -> mSystemNightModeObserver = observer))
+                .when(mSystemNightModeMonitor).addObserver(any());
+        doAnswer(answerVoid((VoidAnswer1<SystemNightModeMonitor.Observer>)
+                observer -> mSystemNightModeObserver = null))
+                .when(mSystemNightModeMonitor).removeObserver(any());
+
+        doAnswer(answerVoid((VoidAnswer1<Runnable>)
+                observer -> mPowerModeObserver = observer))
+                .when(mPowerSavingMonitor).addObserver(any());
+        doAnswer(answerVoid((VoidAnswer1<Runnable>)
+                observer -> mPowerModeObserver = null))
+                .when(mPowerSavingMonitor).removeObserver(any());
+    }
+
     @After
     public void tearDown() throws Exception {
         ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY);
@@ -182,12 +204,10 @@
      * @param isPowerSaveMode Whether power save mode is enabled or not.
      */
     private void setIsPowerSaveMode(boolean isPowerSaveMode) {
-        PowerManager powerManager = (PowerManager) RuntimeEnvironment.application.getSystemService(
-                Context.POWER_SERVICE);
-        ShadowPowerManager shadowPowerManager = shadowOf(powerManager);
-        shadowPowerManager.setIsPowerSaveMode(isPowerSaveMode);
-        ContextUtils.getApplicationContext().sendBroadcast(
-                new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
+        when(mPowerSavingMonitor.powerSavingIsOn()).thenReturn(isPowerSaveMode);
+        if (mPowerModeObserver != null) {
+            mPowerModeObserver.run();
+        }
     }
 
     /**
@@ -196,6 +216,8 @@
      */
     private void setSystemNightMode(boolean isSystemNightModeOn) {
         when(mSystemNightModeMonitor.isSystemNightModeOn()).thenReturn(isSystemNightModeOn);
-        mSystemNightModeMonitor.notifyObserversForTesting();
+        if (mSystemNightModeObserver != null) {
+            mSystemNightModeObserver.onSystemNightModeChanged();
+        }
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index 65a4e1f..0f7e6b4 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -248,12 +248,17 @@
         }
     }
 
-    private static String getWebApkId(String packageName) {
-        return WebApkConstants.WEBAPK_ID_PREFIX + packageName;
+    private void registerStorageForWebApkPackage(String webApkPackageName) {
+        WebappRegistry.getInstance().register(WebappRegistry.webApkIdForPackage(webApkPackageName),
+                new WebappRegistry.FetchWebappDataStorageCallback() {
+                    @Override
+                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
+                });
     }
 
     private WebappDataStorage getStorage(String packageName) {
-        return WebappRegistry.getInstance().getWebappDataStorage(getWebApkId(packageName));
+        return WebappRegistry.getInstance().getWebappDataStorage(
+                WebappRegistry.webApkIdForPackage(packageName));
     }
 
     /**
@@ -488,12 +493,7 @@
 
         registerWebApk(
                 WEBAPK_PACKAGE_NAME, defaultManifestData(), REQUEST_UPDATE_FOR_SHELL_APK_VERSION);
-
-        WebappRegistry.getInstance().register(getWebApkId(WEBAPK_PACKAGE_NAME),
-                new WebappRegistry.FetchWebappDataStorageCallback() {
-                    @Override
-                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
-                });
+        registerStorageForWebApkPackage(WEBAPK_PACKAGE_NAME);
 
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
         storage.updateTimeOfLastCheckForUpdatedWebManifest();
@@ -1168,11 +1168,7 @@
     public void testForceUpdateUnboundWebApk() throws Exception {
         registerWebApk(UNBOUND_WEBAPK_PACKAGE_NAME, defaultManifestData(),
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION);
-        WebappRegistry.getInstance().register(getWebApkId(UNBOUND_WEBAPK_PACKAGE_NAME),
-                new WebappRegistry.FetchWebappDataStorageCallback() {
-                    @Override
-                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
-                });
+        registerStorageForWebApkPackage(UNBOUND_WEBAPK_PACKAGE_NAME);
         WebappDataStorage storage = getStorage(UNBOUND_WEBAPK_PACKAGE_NAME);
         storage.updateWebApkPackageNameForTests(UNBOUND_WEBAPK_PACKAGE_NAME);
         // Should no-op for an unbound WebAPK.
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 1b041dd..3f0464df 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -222,8 +222,17 @@
   <message name="IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_MESSAGE" desc="Message displayed under title in cellular setup when Chrome OS encounters an error preparing the cellular device for setup. Prompts user to insert SIM and try again.">
     Please insert your SIM and try again
   </message>
-  <message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_TITLE" desc="Title for cellular setup step in which the user uses the embedded carrier provisioning portal to make payment and activate the device." translateable="false">
-    Provisioning Page
+  <message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_LOADING_TITLE" desc="Title for cellular setup step which indicates that a connection is in progress to the user's mobile data provider (e.g., Verizon).">
+    Connecting to <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>
+  </message>
+  <message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_TITLE" desc="Title for cellular setup step which indicates that the Chromebook was unable to establish a connection to the user's mobile data provider (e.g., Verizon).">
+    Couldn't connect to <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>
+  </message>
+  <message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_MESSAGE" desc="Message for the cellular setup step which indicates that the Chromebook was unable to establish a connection to the user's mobile data provider (e.g., Verizon).">
+    Please try again. For technical support, contact <ph name="CARRIER_NAME">$1<ex>Google Fi</ex></ph>.
+  </message>
+  <message name="IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ACTIVE_TITLE" desc="Title for cellular setup step which indicates that the Chromebook is in the process of connecting to a mobile network.">
+    Connect to mobile network
   </message>
   <message name="IDS_CELLULAR_SETUP_FINAL_PAGE_TITLE" desc="Title for the final success screen of cellular setup that tells the user that setup is completed but service is being activated">
     Mobile data being activated
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 0b208bd..8e7cc35 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10020,15 +10020,15 @@
 
     <!-- SMS strings -->
     <message name="IDS_SMS_INFOBAR_TITLE" desc="Title shown when Chrome is waiting for an SMS on the user's behalf">
-      Do you want to enter the code on this site?
+      Verify your phone number
     </message>
 
     <message name="IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED" desc="Message shown when Chrome has received an SMS on the user's behalf">
-      <ph name="ORIGIN">$1<ex>example.com</ex></ph> sent a verification code to your phone
+      <ph name="ONE_TIME_CODE">$1<ex>123</ex></ph> is your code for <ph name="ORIGIN">$2<ex>example.com</ex></ph>
     </message>
 
     <message name="IDS_SMS_INFOBAR_BUTTON_OK" desc="Text for the button shown when Chrome has received an SMS on the user's behalf">
-      Enter code
+      Verify
     </message>
 
   </messages>
diff --git a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_BUTTON_OK.png.sha1 b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_BUTTON_OK.png.sha1
index 9e2bf61..2de6095 100644
--- a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_BUTTON_OK.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_BUTTON_OK.png.sha1
@@ -1 +1 @@
-d2da91cc316334522197c0b6cb4eb0c8dddc58f5
\ No newline at end of file
+ec42e9bf6331f8ff015d0965578b87c52b19d4bd
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED.png.sha1 b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED.png.sha1
index 9e2bf61..2de6095 100644
--- a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED.png.sha1
@@ -1 +1 @@
-d2da91cc316334522197c0b6cb4eb0c8dddc58f5
\ No newline at end of file
+ec42e9bf6331f8ff015d0965578b87c52b19d4bd
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_TITLE.png.sha1
index 9e2bf61..2de6095 100644
--- a/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_TITLE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_SMS_INFOBAR_TITLE.png.sha1
@@ -1 +1 @@
-d2da91cc316334522197c0b6cb4eb0c8dddc58f5
\ No newline at end of file
+ec42e9bf6331f8ff015d0965578b87c52b19d4bd
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 20e7a119..a87d11d 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3579,6 +3579,18 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_ALL_SHOWN" desc="Label for the button to delete all visible cookies for a site.">
     Remove All Shown
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_ALL_THIRD_PARTY" desc="Label for the subpage button to open a confirmation dialog to remove all cookies available in third-party contexts.">
+    Remove Third-Party Cookies
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_REMOVE_DIALOG_TITLE" desc="Title of the dialog that warns about deleting third-party cookie data.">
+    Clear third-party cookies
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_REMOVE_CONFIRMATION" desc="Text for the dialog that warns about deleting third-party cookie data.">
+    This will delete all cookies and site data available in third-party contexts. Do you want to continue?
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_CLEAR_THIRD_PARTY_COOKIES" desc="Label for the confirmation dialog button to delete all cookies and site data for third-party contexts.">
+    Clear third-party cookies
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_DIALOG_TITLE" desc="Title of the dialog that warns about deleting all site data.">
     Clear site data
   </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 4ab67edf..afe3ad3 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -16,6 +16,8 @@
     "add.icon",
     "ads.icon",
     "apps.icon",
+    "autofill/webauthn_offer_dialog_header.icon",
+    "autofill/webauthn_offer_dialog_header_dark.icon",
     "blocked_badge.icon",
     "blocked_redirect.icon",
     "bluetooth.icon",
diff --git a/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header.icon b/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header.icon
new file mode 100644
index 0000000..988e785
--- /dev/null
+++ b/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header.icon
@@ -0,0 +1,145 @@
+// 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.
+
+CANVAS_DIMENSIONS, 448,
+NEW_PATH,
+PATH_COLOR_ARGB, 0x0A, 0x00, 0x00, 0x00,
+MOVE_TO, 0, 0,
+R_H_LINE_TO, 448,
+R_V_LINE_TO, 119,
+H_LINE_TO, 0,
+CLOSE,
+NEW_PATH,
+STROKE, 1,
+PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
+MOVE_TO, 318.49f, 67.44f,
+H_LINE_TO, 275,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+MOVE_TO, 372.49f, 33.44f,
+H_LINE_TO, 329,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+MOVE_TO, 60.49f, 72.44f,
+H_LINE_TO, 17,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
+CIRCLE, 128, 87, 37.058,
+NEW_PATH,
+STROKE, 1,
+PATH_COLOR_ARGB, 0xFF, 0xE8, 0xE9, 0xEB,
+CIRCLE, 128, 87, 37.058,
+NEW_PATH,
+STROKE, 1,
+PATH_COLOR_ARGB, 0xFF, 0xBD, 0xC0, 0xC5,
+MOVE_TO, 140.08f, 47.81f,
+ARC_TO, 40.99f, 40.99f, 0, 0, 0, 128, 46,
+R_CUBIC_TO, -5.24f, 0, -10.25f, 0.98f, -14.85f, 2.77f,
+R_ARC_TO, 41.07f, 41.07f, 0, 0, 0, -15.34f, 10.49f,
+MOVE_TO, 87, 87,
+R_CUBIC_TO, 0, 4.36f, 0.68f, 8.56f, 1.94f, 12.5f,
+R_MOVE_TO, 12.64f, 18.86f,
+ARC_TO, 40.85f, 40.85f, 0, 0, 0, 128, 128,
+R_CUBIC_TO, 11.43f, 0, 21.77f, -4.68f, 29.21f, -12.23f,
+ARC_TO, 40.96f, 40.96f, 0, 0, 0, 167.45f, 98.2f,
+MOVE_TO, 169, 87,
+R_ARC_TO, 40.84f, 40.84f, 0, 0, 0, -3.94f, -17.57f,
+ARC_TO, 41.14f, 41.14f, 0, 0, 0, 154.73f, 55.91f,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x1A, 0x73, 0xE8,
+MOVE_TO, 142.03f, 69.83f,
+R_CUBIC_TO, -0.19f, 0, -0.39f, -0.05f, -0.56f, -0.14f,
+R_CUBIC_TO, -4.64f, -2.33f, -8.65f, -3.33f, -13.46f, -3.33f,
+R_CUBIC_TO, -4.79f, 0, -9.33f, 1.11f, -13.46f, 3.33f,
+R_ARC_TO, 1.25f, 1.25f, 0, 0, 1, -1.64f, -0.47f,
+R_ARC_TO, 1.18f, 1.18f, 0, 0, 1, 0.48f, -1.6f,
+R_CUBIC_TO, 4.5f, -2.38f, 9.43f, -3.61f, 14.62f, -3.61f,
+R_CUBIC_TO, 5.15f, 0, 9.65f, 1.11f, 14.58f, 3.59f,
+R_CUBIC_TO, 0.6f, 0.31f, 0.82f, 1.01f, 0.51f, 1.58f,
+R_CUBIC_TO, -0.22f, 0.43f, -0.63f, 0.66f, -1.06f, 0.66f,
+CLOSE,
+R_MOVE_TO, -34.54f, 12.95f,
+R_CUBIC_TO, -0.24f, 0, -0.48f, -0.07f, -0.7f, -0.22f,
+R_ARC_TO, 1.24f, 1.24f, 0, 0, 1, -0.29f, -1.72f,
+R_CUBIC_TO, 2.39f, -3.43f, 5.43f, -6.13f, 9.05f, -8.02f,
+R_CUBIC_TO, 7.58f, -3.97f, 17.29f, -4, 24.89f, -0.02f,
+R_CUBIC_TO, 3.62f, 1.89f, 6.66f, 4.56f, 9.05f, 7.97f,
+R_CUBIC_TO, 0.39f, 0.54f, 0.27f, 1.33f, -0.29f, 1.72f,
+R_ARC_TO, 1.19f, 1.19f, 0, 0, 1, -1.69f, -0.29f,
+R_CUBIC_TO, -2.17f, -3.09f, -4.92f, -5.52f, -8.18f, -7.21f,
+R_CUBIC_TO, -6.93f, -3.6f, -15.79f, -3.6f, -22.69f, 0.02f,
+R_CUBIC_TO, -3.28f, 1.72f, -6.03f, 4.17f, -8.21f, 7.26f,
+R_CUBIC_TO, -0.19f, 0.34f, -0.56f, 0.52f, -0.94f, 0.52f,
+CLOSE,
+R_MOVE_TO, 14.77f, 29.14f,
+R_CUBIC_TO, -0.31f, 0, -0.62f, -0.12f, -0.84f, -0.36f,
+R_CUBIC_TO, -2.09f, -2.12f, -3.22f, -3.48f, -4.84f, -6.42f,
+R_CUBIC_TO, -1.66f, -2.99f, -2.53f, -6.63f, -2.53f, -10.55f,
+R_CUBIC_TO, 0, -7.22f, 6.11f, -13.1f, 13.62f, -13.1f,
+R_CUBIC_TO, 7.51f, 0, 13.62f, 5.88f, 13.62f, 13.1f,
+R_CUBIC_TO, 0, 0.68f, -0.53f, 1.22f, -1.2f, 1.22f,
+R_ARC_TO, 1.2f, 1.2f, 0, 0, 1, -1.2f, -1.22f,
+R_CUBIC_TO, 0, -5.88f, -5.03f, -10.67f, -11.21f, -10.67f,
+R_CUBIC_TO, -6.18f, 0, -11.21f, 4.79f, -11.21f, 10.67f,
+R_CUBIC_TO, 0, 3.5f, 0.77f, 6.73f, 2.24f, 9.36f,
+R_CUBIC_TO, 1.54f, 2.8f, 2.6f, 3.99f, 4.45f, 5.88f,
+R_CUBIC_TO, 0.46f, 0.49f, 0.46f, 1.24f, 0, 1.73f,
+R_ARC_TO, 1.31f, 1.31f, 0, 0, 1, -0.89f, 0.37f,
+CLOSE,
+R_MOVE_TO, 17.11f, -3.88f,
+R_CUBIC_TO, -2.82f, 0, -5.31f, -0.74f, -7.35f, -2.19f,
+R_CUBIC_TO, -3.53f, -2.49f, -5.64f, -6.53f, -5.64f, -10.82f,
+R_CUBIC_TO, 0, -0.69f, 0.52f, -1.23f, 1.19f, -1.23f,
+R_CUBIC_TO, 0.66f, 0, 1.19f, 0.54f, 1.19f, 1.23f,
+R_ARC_TO, 10.71f, 10.71f, 0, 0, 0, 4.6f, 8.77f,
+R_CUBIC_TO, 1.68f, 1.18f, 3.65f, 1.75f, 6.03f, 1.75f,
+R_CUBIC_TO, 0.57f, 0, 1.52f, -0.07f, 2.47f, -0.25f,
+R_CUBIC_TO, 0.64f, -0.12f, 1.26f, 0.32f, 1.38f, 1.01f,
+R_ARC_TO, 1.23f, 1.23f, 0, 0, 1, -0.97f, 1.43f,
+R_ARC_TO, 15.61f, 15.61f, 0, 0, 1, -2.87f, 0.3f,
+CLOSE,
+R_MOVE_TO, -4.35f, 4.53f,
+R_CUBIC_TO, -0.1f, 0, -0.22f, -0.02f, -0.31f, -0.05f,
+R_CUBIC_TO, -3.83f, -1.07f, -6.33f, -2.5f, -8.95f, -5.11f,
+R_CUBIC_TO, -3.37f, -3.38f, -5.22f, -7.88f, -5.22f, -12.69f,
+R_CUBIC_TO, 0, -3.94f, 3.32f, -7.15f, 7.41f, -7.15f,
+R_CUBIC_TO, 4.09f, 0, 7.41f, 3.21f, 7.41f, 7.15f,
+R_CUBIC_TO, 0, 2.6f, 2.24f, 4.72f, 5, 4.72f,
+R_CUBIC_TO, 2.77f, 0, 5.01f, -2.12f, 5.01f, -4.72f,
+R_CUBIC_TO, 0, -9.17f, -7.82f, -16.6f, -17.44f, -16.6f,
+R_CUBIC_TO, -6.83f, 0, -13.09f, 3.84f, -15.9f, 9.8f,
+R_CUBIC_TO, -0.94f, 1.97f, -1.42f, 4.28f, -1.42f, 6.81f,
+R_CUBIC_TO, 0, 1.9f, 0.17f, 4.89f, 1.61f, 8.78f,
+R_CUBIC_TO, 0.24f, 0.63f, -0.07f, 1.34f, -0.7f, 1.56f,
+R_ARC_TO, 1.19f, 1.19f, 0, 0, 1, -1.54f, -0.7f,
+R_CUBIC_TO, -1.18f, -3.18f, -1.76f, -6.34f, -1.76f, -9.63f,
+R_CUBIC_TO, 0, -2.92f, 0.55f, -5.57f, 1.64f, -7.88f,
+R_CUBIC_TO, 3.2f, -6.78f, 10.3f, -11.18f, 18.07f, -11.18f,
+R_CUBIC_TO, 10.95f, 0, 19.85f, 8.53f, 19.85f, 19.04f,
+R_CUBIC_TO, 0, 3.94f, -3.32f, 7.15f, -7.41f, 7.15f,
+R_CUBIC_TO, -4.09f, 0, -7.41f, -3.21f, -7.41f, -7.15f,
+R_CUBIC_TO, 0, -2.6f, -2.24f, -4.72f, -5, -4.72f,
+R_CUBIC_TO, -2.76f, 0, -5, 2.12f, -5, 4.72f,
+R_CUBIC_TO, 0, 4.16f, 1.59f, 8.05f, 4.5f, 10.97f,
+R_CUBIC_TO, 2.29f, 2.29f, 4.47f, 3.55f, 7.87f, 4.5f,
+R_CUBIC_TO, 0.65f, 0.17f, 1.01f, 0.85f, 0.84f, 1.48f,
+R_CUBIC_TO, -0.12f, 0.56f, -0.63f, 0.92f, -1.13f, 0.92f,
+CLOSE
\ No newline at end of file
diff --git a/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header_dark.icon b/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header_dark.icon
new file mode 100644
index 0000000..db9ebc3
--- /dev/null
+++ b/chrome/app/vector_icons/autofill/webauthn_offer_dialog_header_dark.icon
@@ -0,0 +1,136 @@
+// 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.
+
+CANVAS_DIMENSIONS, 448,
+PATH_COLOR_ARGB, 0x18, 0x00, 0x00, 0x00,
+MOVE_TO, 318.49f, 67.44f,
+H_LINE_TO, 275,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 302.36f, 52,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+MOVE_TO, 372.49f, 33.44f,
+H_LINE_TO, 329,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 356.36f, 18,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+MOVE_TO, 60.49f, 72.44f,
+H_LINE_TO, 17,
+R_CUBIC_TO, 0.36f, -5.48f, 4.94f, -9.83f, 10.51f, -9.83f,
+R_CUBIC_TO, 1.18f, 0, 2.36f, 0.21f, 3.51f, 0.61f,
+R_LINE_TO, 0.47f, 0.17f,
+R_LINE_TO, 0.31f, -0.39f,
+ARC_TO, 16.09f, 16.09f, 0, 0, 1, 44.36f, 57,
+R_CUBIC_TO, 8.67f, 0, 15.76f, 6.87f, 16.13f, 15.44f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x41, 0x44, 0x47,
+CIRCLE, 128, 87, 37.058,
+NEW_PATH,
+STROKE, 1,
+PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
+CIRCLE, 128, 87, 37.058,
+NEW_PATH,
+STROKE, 1,
+PATH_COLOR_ARGB, 0xFF, 0x5F, 0x63, 0x68,
+MOVE_TO, 140.08f, 47.81f,
+ARC_TO, 40.99f, 40.99f, 0, 0, 0, 128, 46,
+R_CUBIC_TO, -5.24f, 0, -10.25f, 0.98f, -14.85f, 2.77f,
+R_ARC_TO, 41.07f, 41.07f, 0, 0, 0, -15.34f, 10.49f,
+MOVE_TO, 87, 87,
+R_CUBIC_TO, 0, 4.36f, 0.68f, 8.56f, 1.94f, 12.5f,
+R_MOVE_TO, 12.64f, 18.86f,
+ARC_TO, 40.85f, 40.85f, 0, 0, 0, 128, 128,
+R_CUBIC_TO, 11.43f, 0, 21.77f, -4.68f, 29.21f, -12.23f,
+ARC_TO, 40.96f, 40.96f, 0, 0, 0, 167.45f, 98.2f,
+MOVE_TO, 169, 87,
+R_ARC_TO, 40.84f, 40.84f, 0, 0, 0, -3.94f, -17.57f,
+ARC_TO, 41.14f, 41.14f, 0, 0, 0, 154.73f, 55.91f,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x8A, 0xB4, 0xF8,
+MOVE_TO, 142.03f, 69.83f,
+R_CUBIC_TO, -0.19f, 0, -0.39f, -0.05f, -0.56f, -0.14f,
+R_CUBIC_TO, -4.64f, -2.33f, -8.65f, -3.33f, -13.46f, -3.33f,
+R_CUBIC_TO, -4.79f, 0, -9.33f, 1.11f, -13.46f, 3.33f,
+R_ARC_TO, 1.25f, 1.25f, 0, 0, 1, -1.64f, -0.47f,
+R_ARC_TO, 1.18f, 1.18f, 0, 0, 1, 0.48f, -1.6f,
+R_CUBIC_TO, 4.5f, -2.38f, 9.43f, -3.61f, 14.62f, -3.61f,
+R_CUBIC_TO, 5.15f, 0, 9.65f, 1.11f, 14.58f, 3.59f,
+R_CUBIC_TO, 0.6f, 0.31f, 0.82f, 1.01f, 0.51f, 1.58f,
+R_CUBIC_TO, -0.22f, 0.43f, -0.63f, 0.66f, -1.06f, 0.66f,
+CLOSE,
+R_MOVE_TO, -34.54f, 12.95f,
+R_CUBIC_TO, -0.24f, 0, -0.48f, -0.07f, -0.7f, -0.22f,
+R_ARC_TO, 1.24f, 1.24f, 0, 0, 1, -0.29f, -1.72f,
+R_CUBIC_TO, 2.39f, -3.43f, 5.43f, -6.13f, 9.05f, -8.02f,
+R_CUBIC_TO, 7.58f, -3.97f, 17.29f, -4, 24.89f, -0.02f,
+R_CUBIC_TO, 3.62f, 1.89f, 6.66f, 4.56f, 9.05f, 7.97f,
+R_CUBIC_TO, 0.39f, 0.54f, 0.27f, 1.33f, -0.29f, 1.72f,
+R_ARC_TO, 1.19f, 1.19f, 0, 0, 1, -1.69f, -0.29f,
+R_CUBIC_TO, -2.17f, -3.09f, -4.92f, -5.52f, -8.18f, -7.21f,
+R_CUBIC_TO, -6.93f, -3.6f, -15.79f, -3.6f, -22.69f, 0.02f,
+R_CUBIC_TO, -3.28f, 1.72f, -6.03f, 4.17f, -8.21f, 7.26f,
+R_CUBIC_TO, -0.19f, 0.34f, -0.56f, 0.52f, -0.94f, 0.52f,
+CLOSE,
+R_MOVE_TO, 14.77f, 29.14f,
+R_CUBIC_TO, -0.31f, 0, -0.62f, -0.12f, -0.84f, -0.36f,
+R_CUBIC_TO, -2.09f, -2.12f, -3.22f, -3.48f, -4.84f, -6.42f,
+R_CUBIC_TO, -1.66f, -2.99f, -2.53f, -6.63f, -2.53f, -10.55f,
+R_CUBIC_TO, 0, -7.22f, 6.11f, -13.1f, 13.62f, -13.1f,
+R_CUBIC_TO, 7.51f, 0, 13.62f, 5.88f, 13.62f, 13.1f,
+R_CUBIC_TO, 0, 0.68f, -0.53f, 1.22f, -1.2f, 1.22f,
+R_ARC_TO, 1.2f, 1.2f, 0, 0, 1, -1.2f, -1.22f,
+R_CUBIC_TO, 0, -5.88f, -5.03f, -10.67f, -11.21f, -10.67f,
+R_CUBIC_TO, -6.18f, 0, -11.21f, 4.79f, -11.21f, 10.67f,
+R_CUBIC_TO, 0, 3.5f, 0.77f, 6.73f, 2.24f, 9.36f,
+R_CUBIC_TO, 1.54f, 2.8f, 2.6f, 3.99f, 4.45f, 5.88f,
+R_CUBIC_TO, 0.46f, 0.49f, 0.46f, 1.24f, 0, 1.73f,
+R_ARC_TO, 1.31f, 1.31f, 0, 0, 1, -0.89f, 0.37f,
+CLOSE,
+R_MOVE_TO, 17.11f, -3.88f,
+R_CUBIC_TO, -2.82f, 0, -5.31f, -0.74f, -7.35f, -2.19f,
+R_CUBIC_TO, -3.53f, -2.49f, -5.64f, -6.53f, -5.64f, -10.82f,
+R_CUBIC_TO, 0, -0.69f, 0.52f, -1.23f, 1.19f, -1.23f,
+R_CUBIC_TO, 0.66f, 0, 1.19f, 0.54f, 1.19f, 1.23f,
+R_ARC_TO, 10.71f, 10.71f, 0, 0, 0, 4.6f, 8.77f,
+R_CUBIC_TO, 1.68f, 1.18f, 3.65f, 1.75f, 6.03f, 1.75f,
+R_CUBIC_TO, 0.57f, 0, 1.52f, -0.07f, 2.47f, -0.25f,
+R_CUBIC_TO, 0.64f, -0.12f, 1.26f, 0.32f, 1.38f, 1.01f,
+R_ARC_TO, 1.23f, 1.23f, 0, 0, 1, -0.97f, 1.43f,
+R_ARC_TO, 15.61f, 15.61f, 0, 0, 1, -2.87f, 0.3f,
+CLOSE,
+R_MOVE_TO, -4.35f, 4.53f,
+R_CUBIC_TO, -0.1f, 0, -0.22f, -0.02f, -0.31f, -0.05f,
+R_CUBIC_TO, -3.83f, -1.07f, -6.33f, -2.5f, -8.95f, -5.11f,
+R_CUBIC_TO, -3.37f, -3.38f, -5.22f, -7.88f, -5.22f, -12.69f,
+R_CUBIC_TO, 0, -3.94f, 3.32f, -7.15f, 7.41f, -7.15f,
+R_CUBIC_TO, 4.09f, 0, 7.41f, 3.21f, 7.41f, 7.15f,
+R_CUBIC_TO, 0, 2.6f, 2.24f, 4.72f, 5, 4.72f,
+R_CUBIC_TO, 2.77f, 0, 5.01f, -2.12f, 5.01f, -4.72f,
+R_CUBIC_TO, 0, -9.17f, -7.82f, -16.6f, -17.44f, -16.6f,
+R_CUBIC_TO, -6.83f, 0, -13.09f, 3.84f, -15.9f, 9.8f,
+R_CUBIC_TO, -0.94f, 1.97f, -1.42f, 4.28f, -1.42f, 6.81f,
+R_CUBIC_TO, 0, 1.9f, 0.17f, 4.89f, 1.61f, 8.78f,
+R_CUBIC_TO, 0.24f, 0.63f, -0.07f, 1.34f, -0.7f, 1.56f,
+R_ARC_TO, 1.19f, 1.19f, 0, 0, 1, -1.54f, -0.7f,
+R_CUBIC_TO, -1.18f, -3.18f, -1.76f, -6.34f, -1.76f, -9.63f,
+R_CUBIC_TO, 0, -2.92f, 0.55f, -5.57f, 1.64f, -7.88f,
+R_CUBIC_TO, 3.2f, -6.78f, 10.3f, -11.18f, 18.07f, -11.18f,
+R_CUBIC_TO, 10.95f, 0, 19.85f, 8.53f, 19.85f, 19.04f,
+R_CUBIC_TO, 0, 3.94f, -3.32f, 7.15f, -7.41f, 7.15f,
+R_CUBIC_TO, -4.09f, 0, -7.41f, -3.21f, -7.41f, -7.15f,
+R_CUBIC_TO, 0, -2.6f, -2.24f, -4.72f, -5, -4.72f,
+R_CUBIC_TO, -2.76f, 0, -5, 2.12f, -5, 4.72f,
+R_CUBIC_TO, 0, 4.16f, 1.59f, 8.05f, 4.5f, 10.97f,
+R_CUBIC_TO, 2.29f, 2.29f, 4.47f, 3.55f, 7.87f, 4.5f,
+R_CUBIC_TO, 0.65f, 0.17f, 1.01f, 0.85f, 0.84f, 1.48f,
+R_CUBIC_TO, -0.12f, 0.56f, -0.63f, 0.92f, -1.13f, 0.92f,
+CLOSE
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3d0e16b..f8fbdf5d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -58,6 +58,7 @@
 #include "components/autofill/core/common/autofill_util.h"
 #include "components/autofill_assistant/browser/features.h"
 #include "components/browser_sync/browser_sync_switches.h"
+#include "components/browsing_data/core/features.h"
 #include "components/cloud_devices/common/cloud_devices_switches.h"
 #include "components/content_settings/core/common/features.h"
 #include "components/contextual_search/core/browser/public.h"
@@ -2886,12 +2887,11 @@
      flag_descriptions::kOmniboxUISwapTitleAndUrlDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(omnibox::kUIExperimentSwapTitleAndUrl)},
 
-#if defined(OS_ANDROID)
     {"omnibox-zero-suggestions-on-ntp",
      flag_descriptions::kOmniboxZeroSuggestionsOnNTPName,
-     flag_descriptions::kOmniboxZeroSuggestionsOnNTPDescription, kOsAndroid,
+     flag_descriptions::kOmniboxZeroSuggestionsOnNTPDescription,
+     kOsDesktop | kOsAndroid,
      FEATURE_VALUE_TYPE(omnibox::kZeroSuggestionsOnNTP)},
-#endif
 
     {"omnibox-material-design-weather-icons",
      flag_descriptions::kOmniboxMaterialDesignWeatherIconsName,
@@ -3019,10 +3019,6 @@
     {"ntp-realbox", flag_descriptions::kNtpRealboxName,
      flag_descriptions::kNtpRealboxDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kNtpRealbox)},
-
-    {"ntp-zero-suggest", flag_descriptions::kNtpZeroSuggestName,
-     flag_descriptions::kNtpZeroSuggestDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(features::kNtpZeroSuggest)},
 #endif  // !defined(OS_ANDROID)
 
 #if defined(DCHECK_IS_CONFIGURABLE)
@@ -4101,6 +4097,13 @@
      flag_descriptions::kSameSiteByDefaultCookiesDescription, kOsAll,
      FEATURE_VALUE_TYPE(net::features::kSameSiteByDefaultCookies)},
 
+    {"enable-removing-all-third-party-cookies",
+     flag_descriptions::kEnableRemovingAllThirdPartyCookiesName,
+     flag_descriptions::kEnableRemovingAllThirdPartyCookiesDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         browsing_data::features::kEnableRemovingAllThirdPartyCookies)},
+
     {"enable-send-tab-to-self-broadcast",
      flag_descriptions::kSendTabToSelfBroadcastName,
      flag_descriptions::kSendTabToSelfBroadcastDescription, kOsAll,
diff --git a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
index 6c12b86..7daf950d 100644
--- a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
+++ b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "content/public/common/use_zoom_for_dsf_policy.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
 namespace contextual_search {
 
@@ -42,10 +42,10 @@
 void CreateUnhandledTapNotifierImpl(
     float device_scale_factor,
     UnhandledTapCallback callback,
-    blink::mojom::UnhandledTapNotifierRequest request) {
-  mojo::MakeStrongBinding(std::make_unique<UnhandledTapNotifierImpl>(
-                              device_scale_factor, std::move(callback)),
-                          std::move(request));
+    mojo::PendingReceiver<blink::mojom::UnhandledTapNotifier> receiver) {
+  mojo::MakeSelfOwnedReceiver(std::make_unique<UnhandledTapNotifierImpl>(
+                                  device_scale_factor, std::move(callback)),
+                              std::move(receiver));
 }
 
 }  // namespace contextual_search
diff --git a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.h b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.h
index b7ed9e2..617de4f 100644
--- a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.h
+++ b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/android/contextualsearch/unhandled_tap_web_contents_observer.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/unhandled_tap_notifier/unhandled_tap_notifier.mojom.h"
 
 namespace contextual_search {
@@ -42,7 +43,7 @@
 void CreateUnhandledTapNotifierImpl(
     float device_scale_factor,
     UnhandledTapCallback callback,
-    blink::mojom::UnhandledTapNotifierRequest request);
+    mojo::PendingReceiver<blink::mojom::UnhandledTapNotifier> receiver);
 
 }  // namespace contextual_search
 
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index fa79898f..1121b95 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -165,10 +165,11 @@
 void TabWebContentsDelegateAndroid::CreateSmsPrompt(
     content::RenderFrameHost* host,
     const url::Origin& origin,
+    const std::string& one_time_code,
     base::OnceClosure on_confirm,
     base::OnceClosure on_cancel) {
   auto* web_contents = content::WebContents::FromRenderFrameHost(host);
-  SmsInfoBar::Create(web_contents, origin, std::move(on_confirm),
+  SmsInfoBar::Create(web_contents, origin, one_time_code, std::move(on_confirm),
                      std::move(on_cancel));
 }
 
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.h b/chrome/browser/android/tab_web_contents_delegate_android.h
index bbb15ca..5383f47f 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.h
+++ b/chrome/browser/android/tab_web_contents_delegate_android.h
@@ -49,6 +49,7 @@
       const content::BluetoothChooser::EventHandler& event_handler) override;
   void CreateSmsPrompt(content::RenderFrameHost*,
                        const url::Origin&,
+                       const std::string& one_time_code,
                        base::OnceClosure on_confirm,
                        base::OnceClosure on_cancel) override;
   std::unique_ptr<content::BluetoothScanningPrompt> ShowBluetoothScanningPrompt(
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index d345c53..9029f1f 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -189,35 +189,32 @@
                        int32_t size_hint_in_dip,
                        bool allow_placeholder_icon,
                        LoadIconCallback callback) {
-  if (icon_key) {
-    // Treat the Play Store as a special case, loading an icon defined by a
-    // resource instead of asking the Android VM (or the cache of previous
-    // responses from the Android VM). Presumably this is for bootstrapping:
-    // the Play Store icon (the UI for enabling and installing Android apps)
-    // should be showable even before the user has installed their first
-    // Android app and before bringing up an Android VM for the first time.
-    if (app_id == arc::kPlayStoreAppId) {
-      LoadPlayStoreIcon(icon_compression, size_hint_in_dip,
-                        static_cast<IconEffects>(icon_key->icon_effects),
-                        std::move(callback));
-      return;
-    }
-
-    // Try loading the icon from an on-disk cache. If that fails, fall back to
-    // LoadIconFromVM.
-    LoadIconFromFileWithFallback(
-        icon_compression, size_hint_in_dip,
-        GetCachedIconFilePath(app_id, size_hint_in_dip),
-        static_cast<IconEffects>(icon_key->icon_effects), std::move(callback),
-        base::BindOnce(&ArcApps::LoadIconFromVM, weak_ptr_factory_.GetWeakPtr(),
-                       app_id, icon_compression, size_hint_in_dip,
-                       allow_placeholder_icon,
-                       static_cast<IconEffects>(icon_key->icon_effects)));
+  if (!icon_key) {
+    std::move(callback).Run(apps::mojom::IconValue::New());
     return;
   }
+  IconEffects icon_effects = static_cast<IconEffects>(icon_key->icon_effects);
 
-  // On failure, we still run the callback, with the zero IconValue.
-  std::move(callback).Run(apps::mojom::IconValue::New());
+  // Treat the Play Store as a special case, loading an icon defined by a
+  // resource instead of asking the Android VM (or the cache of previous
+  // responses from the Android VM). Presumably this is for bootstrapping:
+  // the Play Store icon (the UI for enabling and installing Android apps)
+  // should be showable even before the user has installed their first
+  // Android app and before bringing up an Android VM for the first time.
+  if (app_id == arc::kPlayStoreAppId) {
+    LoadPlayStoreIcon(icon_compression, size_hint_in_dip, icon_effects,
+                      std::move(callback));
+  } else if (allow_placeholder_icon) {
+    constexpr bool is_placeholder_icon = true;
+    LoadIconFromResource(icon_compression, size_hint_in_dip,
+                         IDR_APP_DEFAULT_ICON, is_placeholder_icon,
+                         icon_effects, std::move(callback));
+  } else {
+    arc_icon_once_loader_.LoadIcon(
+        app_id, size_hint_in_dip, icon_compression,
+        base::BindOnce(&OnArcAppIconCompletelyLoaded, icon_compression,
+                       size_hint_in_dip, icon_effects, std::move(callback)));
+  }
 }
 
 void ArcApps::Launch(const std::string& app_id,
@@ -398,41 +395,6 @@
   }
 }
 
-const base::FilePath ArcApps::GetCachedIconFilePath(const std::string& app_id,
-                                                    int32_t size_hint_in_dip) {
-  ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_);
-  if (!prefs) {
-    return base::FilePath();
-  }
-  // TODO(crbug.com/826982): process the app_id argument like the private
-  // GetAppFromAppOrGroupId function and the ArcAppIcon::mapped_app_id_ field
-  // in arc_app_icon.cc?
-  return prefs->GetIconPath(
-      app_id,
-      ArcAppIconDescriptor(size_hint_in_dip,
-                           apps_util::GetPrimaryDisplayUIScaleFactor()));
-}
-
-void ArcApps::LoadIconFromVM(const std::string app_id,
-                             apps::mojom::IconCompression icon_compression,
-                             int32_t size_hint_in_dip,
-                             bool allow_placeholder_icon,
-                             IconEffects icon_effects,
-                             LoadIconCallback callback) {
-  if (allow_placeholder_icon) {
-    constexpr bool is_placeholder_icon = true;
-    LoadIconFromResource(icon_compression, size_hint_in_dip,
-                         IDR_APP_DEFAULT_ICON, is_placeholder_icon,
-                         icon_effects, std::move(callback));
-    return;
-  }
-
-  arc_icon_once_loader_.LoadIcon(
-      app_id, size_hint_in_dip, icon_compression,
-      base::BindOnce(&OnArcAppIconCompletelyLoaded, icon_compression,
-                     size_hint_in_dip, icon_effects, std::move(callback)));
-}
-
 void ArcApps::LoadPlayStoreIcon(apps::mojom::IconCompression icon_compression,
                                 int32_t size_hint_in_dip,
                                 IconEffects icon_effects,
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h
index 88f5c24..e705947 100644
--- a/chrome/browser/apps/app_service/arc_apps.h
+++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "base/callback_forward.h"
-#include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
@@ -84,14 +83,6 @@
       const arc::mojom::ArcPackageInfo& package_info) override;
   void OnPackageListInitialRefreshed() override;
 
-  const base::FilePath GetCachedIconFilePath(const std::string& app_id,
-                                             int32_t size_hint_in_dip);
-  void LoadIconFromVM(const std::string app_id,
-                      apps::mojom::IconCompression icon_compression,
-                      int32_t size_hint_in_dip,
-                      bool allow_placeholder_icon,
-                      IconEffects icon_effects,
-                      LoadIconCallback callback);
   void LoadPlayStoreIcon(apps::mojom::IconCompression icon_compression,
                          int32_t size_hint_in_dip,
                          IconEffects icon_effects,
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index 6ea0ceb..9dea7b3 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -268,8 +268,7 @@
   base::OnceCallback<void(net::CanonicalCookie::CookieInclusionStatus)>
       callback = base::BindLambdaForTesting(
           [&success, &loop](net::CanonicalCookie::CookieInclusionStatus s) {
-            success =
-                (s == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+            success = s.IsInclude();
             loop.Quit();
           });
   network::mojom::CookieManager* cookie_manager =
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 42230db9..35af3c3 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -291,8 +291,7 @@
         *cookie, "http", net::CookieOptions(),
         base::BindLambdaForTesting(
             [&](net::CanonicalCookie::CookieInclusionStatus result) {
-              EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-                        result);
+              EXPECT_TRUE(result.IsInclude());
               run_loop.Quit();
             }));
     run_loop.Run();
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
index 88c159b..d9867d23 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl.cc
@@ -182,7 +182,7 @@
     const GURL& install_url,
     SuccessCallback callback,
     net::CanonicalCookie::CookieInclusionStatus status) {
-  if (status != net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+  if (!status.IsInclude()) {
     PA_LOG(WARNING)
         << "AndroidSmsAppSetupControllerImpl::"
         << "OnSetRememberDeviceByDefaultCookieResult(): Failed to set "
@@ -328,7 +328,7 @@
     const GURL& app_url,
     SuccessCallback callback,
     net::CanonicalCookie::CookieInclusionStatus status) {
-  if (status != net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+  if (!status.IsInclude()) {
     PA_LOG(ERROR)
         << "AndroidSmsAppSetupControllerImpl::OnSetMigrationCookieResult(): "
         << "Failed to set migration cookie for " << app_url << ". Proceeding "
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
index 8a1c2db9..9782339 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_setup_controller_impl_unittest.cc
@@ -78,12 +78,12 @@
               !std::get<2>(params).exclude_httponly());
     EXPECT_EQ(expect_same_site_context,
               std::get<2>(params).same_site_cookie_context());
-    net::CanonicalCookie::CookieInclusionStatus status =
-        net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    net::CanonicalCookie::CookieInclusionStatus status;
 
-    if (!success)
-      status =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+    if (!success) {
+      status.AddExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+    }
 
     std::move(std::get<3>(params)).Run(status);
   }
diff --git a/chrome/browser/chromeos/crostini/crostini_export_import.cc b/chrome/browser/chromeos/crostini/crostini_export_import.cc
index 6b59735d..431d188 100644
--- a/chrome/browser/chromeos/crostini/crostini_export_import.cc
+++ b/chrome/browser/chromeos/crostini/crostini_export_import.cc
@@ -221,9 +221,12 @@
     LOG(ERROR) << "Error sharing for export " << container_path.value() << ": "
                << failure_reason;
     auto it = notifications_.find(container_id);
-    DCHECK(it != notifications_.end()) << ContainerIdToString(container_id)
-                                       << " has no notification to update";
-    RemoveNotification(it).SetStatusFailed();
+    if (it != notifications_.end()) {
+      RemoveNotification(it).SetStatusFailed();
+    } else {
+      NOTREACHED() << ContainerIdToString(container_id)
+                   << " has no notification to update";
+    }
     return;
   }
   CrostiniManager::GetForProfile(profile_)->ExportLxdContainer(
@@ -241,8 +244,11 @@
     uint64_t container_size,
     uint64_t compressed_size) {
   auto it = notifications_.find(container_id);
-  DCHECK(it != notifications_.end())
-      << ContainerIdToString(container_id) << " has no notification to update";
+  if (it == notifications_.end()) {
+    NOTREACHED() << ContainerIdToString(container_id)
+                 << " has no notification to update";
+    return;
+  }
 
   ExportContainerResult enum_hist_result = ExportContainerResult::kSuccess;
   if (result == CrostiniResult::SUCCESS) {
@@ -334,8 +340,11 @@
     uint64_t progress_speed) {
   ContainerId container_id(vm_name, container_name);
   auto it = notifications_.find(container_id);
-  DCHECK(it != notifications_.end())
-      << ContainerIdToString(container_id) << " has no notification to update";
+  if (it == notifications_.end()) {
+    NOTREACHED() << ContainerIdToString(container_id)
+                 << " has no notification to update";
+    return;
+  }
 
   switch (status) {
     // Rescale PACK:1-100 => 0-50.
@@ -357,8 +366,11 @@
     const StreamingExportStatus& status) {
   ContainerId container_id(vm_name, container_name);
   auto it = notifications_.find(container_id);
-  DCHECK(it != notifications_.end())
-      << ContainerIdToString(container_id) << " has no notification to update";
+  if (it == notifications_.end()) {
+    NOTREACHED() << ContainerIdToString(container_id)
+                 << " has no notification to update";
+    return;
+  }
 
   const auto files_percent = 100.0 * status.exported_files / status.total_files;
   const auto bytes_percent = 100.0 * status.exported_bytes / status.total_bytes;
@@ -380,9 +392,12 @@
     LOG(ERROR) << "Error sharing for import " << container_path.value() << ": "
                << failure_reason;
     auto it = notifications_.find(container_id);
-    DCHECK(it != notifications_.end()) << ContainerIdToString(container_id)
-                                       << " has no notification to update";
-    RemoveNotification(it).SetStatusFailed();
+    if (it != notifications_.end()) {
+      RemoveNotification(it).SetStatusFailed();
+    } else {
+      NOTREACHED() << ContainerIdToString(container_id)
+                   << " has no notification to update";
+    }
     return;
   }
   CrostiniManager::GetForProfile(profile_)->ImportLxdContainer(
@@ -403,31 +418,38 @@
   if (result == CrostiniResult::SUCCESS) {
     UMA_HISTOGRAM_LONG_TIMES("Crostini.RestoreTimeSuccess",
                              base::Time::Now() - start);
-    DCHECK(it != notifications_.end()) << ContainerIdToString(container_id)
-                                       << " has no notification to update";
-    switch (it->second->status()) {
-      case CrostiniExportImportNotification::Status::RUNNING:
-        // If a user requests to cancel, but the import completes before the
-        // cancel can happen, then the container will have been imported over
-        // and the cancel will have failed. However the period of time in which
-        // this can happen is very small (<5s), so it feels quite natural to
-        // pretend the cancel did not happen, and instead display success.
-      case CrostiniExportImportNotification::Status::CANCELLING:
-        RemoveNotification(it).SetStatusDone();
-        break;
-      default:
-        NOTREACHED();
+    if (it != notifications_.end()) {
+      switch (it->second->status()) {
+        case CrostiniExportImportNotification::Status::RUNNING:
+          // If a user requests to cancel, but the import completes before the
+          // cancel can happen, then the container will have been imported over
+          // and the cancel will have failed. However the period of time in
+          // which this can happen is very small (<5s), so it feels quite
+          // natural to pretend the cancel did not happen, and instead display
+          // success.
+        case CrostiniExportImportNotification::Status::CANCELLING:
+          RemoveNotification(it).SetStatusDone();
+          break;
+        default:
+          NOTREACHED();
+      }
+    } else {
+      NOTREACHED() << ContainerIdToString(container_id)
+                   << " has no notification to update";
     }
   } else if (result ==
              crostini::CrostiniResult::CONTAINER_EXPORT_IMPORT_CANCELLED) {
-    DCHECK(it != notifications_.end()) << ContainerIdToString(container_id)
-                                       << " has no notification to update";
-    switch (it->second->status()) {
-      case CrostiniExportImportNotification::Status::CANCELLING:
-        RemoveNotification(it).SetStatusCancelled();
-        break;
-      default:
-        NOTREACHED();
+    if (it != notifications_.end()) {
+      switch (it->second->status()) {
+        case CrostiniExportImportNotification::Status::CANCELLING:
+          RemoveNotification(it).SetStatusCancelled();
+          break;
+        default:
+          NOTREACHED();
+      }
+    } else {
+      NOTREACHED() << ContainerIdToString(container_id)
+                   << " has no notification to update";
     }
   } else {
     LOG(ERROR) << "Error importing " << int(result);
@@ -454,11 +476,14 @@
     if (result == CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED ||
         result == CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STOPPED ||
         result == CrostiniResult::CONTAINER_EXPORT_IMPORT_FAILED_VM_STARTED) {
-      DCHECK(it != notifications_.end()) << ContainerIdToString(container_id)
-                                         << " has no notification to update";
-      DCHECK(it->second->status() ==
-             CrostiniExportImportNotification::Status::RUNNING);
-      RemoveNotification(it).SetStatusFailed();
+      if (it != notifications_.end()) {
+        DCHECK(it->second->status() ==
+               CrostiniExportImportNotification::Status::RUNNING);
+        RemoveNotification(it).SetStatusFailed();
+      } else {
+        NOTREACHED() << ContainerIdToString(container_id)
+                     << " has no notification to update";
+      }
     } else {
       DCHECK(it == notifications_.end()) << ContainerIdToString(container_id)
                                          << " has unexpected notification";
@@ -485,8 +510,11 @@
     uint64_t minimum_required_space) {
   ContainerId container_id(vm_name, container_name);
   auto it = notifications_.find(container_id);
-  DCHECK(it != notifications_.end())
-      << ContainerIdToString(container_id) << " has no notification to update";
+  if (it == notifications_.end()) {
+    NOTREACHED() << ContainerIdToString(container_id)
+                 << " has no notification to update";
+    return;
+  }
 
   switch (status) {
     // Rescale UPLOAD:1-100 => 0-50.
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
index ca4ff3d..fae85a3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc
@@ -13,6 +13,7 @@
 #include "base/bind.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -64,7 +65,7 @@
 };
 
 bool OverrideFunction(const std::string& name,
-                      extensions::ExtensionFunctionFactory factory) {
+                      ExtensionFunctionFactory factory) {
   return ExtensionFunctionRegistry::GetInstance().OverrideFunctionForTesting(
       name, factory);
 }
@@ -194,7 +195,7 @@
   // the test.  This function will be called from ExtensionFunctinoDispatcher
   // whenever an extension function for fileBrowserHandlerInternal.selectFile
   // will be needed.
-  static ExtensionFunction* TestSelectFileFunctionFactory() {
+  static scoped_refptr<ExtensionFunction> TestSelectFileFunctionFactory() {
     EXPECT_TRUE(test_cases_);
     EXPECT_TRUE(!test_cases_ || current_test_case_ < test_cases_->size());
 
@@ -208,7 +209,7 @@
         new MockFileSelectorFactory(test_cases_->at(current_test_case_));
     current_test_case_++;
 
-    return new FileBrowserHandlerInternalSelectFileFunction(
+    return base::MakeRefCounted<FileBrowserHandlerInternalSelectFileFunction>(
         mock_factory, false);
   }
 
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 12fd53a..e446853 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -85,7 +85,7 @@
 void InjectCookieDoneCallback(
     base::OnceClosure done_closure,
     net::CanonicalCookie::CookieInclusionStatus status) {
-  ASSERT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+  ASSERT_TRUE(status.IsInclude());
   std::move(done_closure).Run();
 }
 
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.cc b/chrome/browser/chromeos/policy/system_log_uploader.cc
index eeea1cf..85a3a1e 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.cc
+++ b/chrome/browser/chromeos/policy/system_log_uploader.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -297,6 +298,9 @@
 const char* const SystemLogUploader::kContentTypeOctetStream =
     "application/octet-stream";
 
+const char* const SystemLogUploader::kSystemLogUploadResultHistogram =
+    "Enterprise.SystemLogUploadResult";
+
 SystemLogUploader::SystemLogUploader(
     std::unique_ptr<Delegate> syslog_delegate,
     const scoped_refptr<base::SequencedTaskRunner>& task_runner)
@@ -334,6 +338,12 @@
   log_upload_in_progress_ = false;
   retry_count_ = 0;
 
+  UMA_HISTOGRAM_ENUMERATION(
+      kSystemLogUploadResultHistogram,
+      base::FeatureList::IsEnabled(features::kUploadZippedSystemLogs)
+          ? ZIPPED_LOGS_UPLOAD_SUCCESS
+          : NON_ZIPPED_LOGS_UPLOAD_SUCCESS);
+
   // On successful log upload schedule the next log upload after
   // upload_frequency_ time from now.
   ScheduleNextSystemLogUpload(upload_frequency_);
@@ -344,6 +354,11 @@
   last_upload_attempt_ = base::Time::NowFromSystemTime();
   log_upload_in_progress_ = false;
 
+  UMA_HISTOGRAM_ENUMERATION(
+      kSystemLogUploadResultHistogram,
+      base::FeatureList::IsEnabled(features::kUploadZippedSystemLogs)
+          ? ZIPPED_LOGS_UPLOAD_FAILURE
+          : NON_ZIPPED_LOGS_UPLOAD_FAILURE);
   //  If we have hit the maximum number of retries, terminate this upload
   //  attempt and schedule the next one using the normal delay. Otherwise, retry
   //  uploading after kErrorUploadDelayMs milliseconds.
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.h b/chrome/browser/chromeos/policy/system_log_uploader.h
index 5cb8784..e40c9cbb 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.h
+++ b/chrome/browser/chromeos/policy/system_log_uploader.h
@@ -60,6 +60,9 @@
   static const char* const kZippedLogsFileName;
   static const char* const kContentTypeOctetStream;
 
+  // UMA histogram name.
+  static const char* const kSystemLogUploadResultHistogram;
+
   // A delegate interface used by SystemLogUploader to read the system logs
   // from the disk and create an upload job.
   class Delegate {
@@ -89,6 +92,19 @@
                                ZippedLogUploadCallback upload_callback) = 0;
   };
 
+  // Enum used for UMA. Do NOT reorder or remove entry.
+  // Don't forget to update enums.xml when adding new entries.
+  enum SystemLogUploadResult {
+    NON_ZIPPED_LOGS_UPLOAD_SUCCESS = 0,
+    ZIPPED_LOGS_UPLOAD_SUCCESS = 1,
+    NON_ZIPPED_LOGS_UPLOAD_FAILURE = 2,
+    ZIPPED_LOGS_UPLOAD_FAILURE = 3,
+
+    // Magic constant used by the histogram macros.
+    // Always update it to the max value.
+    kMaxValue = ZIPPED_LOGS_UPLOAD_FAILURE
+  };
+
   // Constructor. Callers can inject their own Delegate. A nullptr can be passed
   // for |syslog_delegate| to use the default implementation.
   SystemLogUploader(
diff --git a/chrome/browser/chromeos/policy/system_log_uploader_unittest.cc b/chrome/browser/chromeos/policy/system_log_uploader_unittest.cc
index a4e2de5..a898c32 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader_unittest.cc
+++ b/chrome/browser/chromeos/policy/system_log_uploader_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/time/time.h"
@@ -259,12 +260,29 @@
     EXPECT_GE(next_task, uploader.last_upload_attempt() + expected_delay);
   }
 
+  void ExpectSuccessHistogram(int amount) {
+    histogram_tester_.ExpectUniqueSample(
+        SystemLogUploader::kSystemLogUploadResultHistogram,
+        is_zipped_upload_ ? SystemLogUploader::ZIPPED_LOGS_UPLOAD_SUCCESS
+                          : SystemLogUploader::NON_ZIPPED_LOGS_UPLOAD_SUCCESS,
+        amount);
+  }
+
+  void ExpectFailureHistogram(int amount) {
+    histogram_tester_.ExpectUniqueSample(
+        SystemLogUploader::kSystemLogUploadResultHistogram,
+        is_zipped_upload_ ? SystemLogUploader::ZIPPED_LOGS_UPLOAD_FAILURE
+                          : SystemLogUploader::NON_ZIPPED_LOGS_UPLOAD_FAILURE,
+        amount);
+  }
+
  protected:
   content::BrowserTaskEnvironment task_environment_;
   chromeos::ScopedCrosSettingsTestHelper settings_helper_;
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
   bool is_zipped_upload_;
   base::test::ScopedFeatureList feature_list;
+  base::HistogramTester histogram_tester_;
 };
 
 // Check disabled system log uploads by default.
@@ -279,6 +297,8 @@
   SystemLogUploader uploader(std::move(syslog_delegate), task_runner_);
 
   task_runner_->RunPendingTasks();
+  histogram_tester_.ExpectTotalCount(
+      SystemLogUploader::kSystemLogUploadResultHistogram, 0);
 }
 
 // One success task pending.
@@ -298,6 +318,7 @@
   RunPendingUploadTaskAndCheckNext(
       uploader, base::TimeDelta::FromMilliseconds(
                     SystemLogUploader::kDefaultUploadDelayMs));
+  ExpectSuccessHistogram(/*amount=*/1);
 }
 
 // Three failed responses recieved.
@@ -326,6 +347,7 @@
   RunPendingUploadTaskAndCheckNext(uploader,
                                    base::TimeDelta::FromMilliseconds(
                                        SystemLogUploader::kErrorUploadDelayMs));
+  ExpectFailureHistogram(/*amount=*/3);
 }
 
 // Check header fields of system log files to upload.
@@ -345,6 +367,7 @@
   RunPendingUploadTaskAndCheckNext(
       uploader, base::TimeDelta::FromMilliseconds(
                     SystemLogUploader::kDefaultUploadDelayMs));
+  ExpectSuccessHistogram(/*amount=*/1);
 }
 
 // Disable system log uploads after one failed log upload.
@@ -364,6 +387,7 @@
   RunPendingUploadTaskAndCheckNext(uploader,
                                    base::TimeDelta::FromMilliseconds(
                                        SystemLogUploader::kErrorUploadDelayMs));
+  ExpectFailureHistogram(/*amount=*/1);
 
   // Disable log upload and check that frequency is usual, because there is no
   // errors, we should not upload logs.
@@ -377,6 +401,7 @@
   RunPendingUploadTaskAndCheckNext(
       uploader, base::TimeDelta::FromMilliseconds(
                     SystemLogUploader::kDefaultUploadDelayMs));
+  ExpectFailureHistogram(/*amount=*/1);
 }
 
 INSTANTIATE_TEST_SUITE_P(SystemLogUploaderTestInstance,
diff --git a/chrome/browser/extensions/activity_log/activity_actions.cc b/chrome/browser/extensions/activity_log/activity_actions.cc
index ec44aec..f71689e 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.cc
+++ b/chrome/browser/extensions/activity_log/activity_actions.cc
@@ -11,6 +11,7 @@
 #include "base/format_macros.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -63,9 +64,8 @@
 // refcount is one.  However, there are likely to be other stray references in
 // many cases that will prevent this optimization.
 scoped_refptr<Action> Action::Clone() const {
-  scoped_refptr<Action> clone(
-      new Action(
-          extension_id(), time(), action_type(), api_name(), action_id()));
+  auto clone = base::MakeRefCounted<Action>(
+      extension_id(), time(), action_type(), api_name(), action_id());
   if (args())
     clone->set_args(base::WrapUnique(args()->DeepCopy()));
   clone->set_page_url(page_url());
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index f61bad9..da2b44dd 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -15,6 +15,7 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/one_shot_event.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
@@ -421,8 +422,8 @@
   ActivityLog* activity_log = SafeGetActivityLog(browser_context);
   if (!activity_log || !activity_log->ShouldLog(extension_id))
     return;
-  scoped_refptr<Action> action =
-      new Action(extension_id, base::Time::Now(), type, activity_name);
+  auto action = base::MakeRefCounted<Action>(extension_id, base::Time::Now(),
+                                             type, activity_name);
   action->set_args(std::move(args));
   activity_log->LogAction(action);
 }
@@ -478,7 +479,7 @@
   ActivityLog* activity_log = SafeGetActivityLog(browser_context);
   if (!activity_log || !activity_log->ShouldLog(extension_id))
     return;
-  scoped_refptr<Action> action = new Action(
+  auto action = base::MakeRefCounted<Action>(
       extension_id, base::Time::Now(), Action::ACTION_WEB_REQUEST, api_call);
   action->set_page_url(url);
   action->set_page_incognito(is_incognito);
@@ -574,7 +575,7 @@
   cached_consumer_count_ =
       profile_->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive);
 
-  observers_ = new base::ObserverListThreadSafe<Observer>;
+  observers_ = base::MakeRefCounted<base::ObserverListThreadSafe<Observer>>();
 
   extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
   CheckActive(true);  // use cached
@@ -767,10 +768,9 @@
     // the call to tabs.executeScript will have already been logged anyway.
     if (!it->second.empty()) {
       scoped_refptr<Action> action;
-      action = new Action(extension->id(),
-                          base::Time::Now(),
-                          Action::ACTION_CONTENT_SCRIPT,
-                          "");  // no API call here
+      action = base::MakeRefCounted<Action>(extension->id(), base::Time::Now(),
+                                            Action::ACTION_CONTENT_SCRIPT,
+                                            "");  // no API call here
       action->set_page_url(on_url);
       action->set_page_title(base::UTF16ToUTF8(web_contents->GetTitle()));
       action->set_page_incognito(
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
index 6b7b2c5..a409a5d 100644
--- a/chrome/browser/extensions/activity_log/counting_policy.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -42,6 +42,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -489,11 +490,11 @@
 
   // Execute the query and get results.
   while (query.is_valid() && query.Step()) {
-    scoped_refptr<Action> action =
-        new Action(query.ColumnString(0),
-                   base::Time::FromInternalValue(query.ColumnInt64(1)),
-                   static_cast<Action::ActionType>(query.ColumnInt(2)),
-                   query.ColumnString(3), query.ColumnInt64(10));
+    auto action = base::MakeRefCounted<Action>(
+        query.ColumnString(0),
+        base::Time::FromInternalValue(query.ColumnInt64(1)),
+        static_cast<Action::ActionType>(query.ColumnInt(2)),
+        query.ColumnString(3), query.ColumnInt64(10));
 
     if (query.GetColumnType(4) != sql::ColumnType::kNull) {
       std::unique_ptr<base::Value> parsed_value =
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
index 784e87a..03d2644 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
@@ -14,6 +14,7 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
@@ -186,11 +187,11 @@
 
   // Execute the query and get results.
   while (query.is_valid() && query.Step()) {
-    scoped_refptr<Action> action =
-        new Action(query.ColumnString(0),
-                   base::Time::FromInternalValue(query.ColumnInt64(1)),
-                   static_cast<Action::ActionType>(query.ColumnInt(2)),
-                   query.ColumnString(3), query.ColumnInt64(9));
+    auto action = base::MakeRefCounted<Action>(
+        query.ColumnString(0),
+        base::Time::FromInternalValue(query.ColumnInt64(1)),
+        static_cast<Action::ActionType>(query.ColumnInt(2)),
+        query.ColumnString(3), query.ColumnInt64(9));
 
     if (query.GetColumnType(4) != sql::ColumnType::kNull) {
       std::unique_ptr<base::Value> parsed_value =
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index e72b5ae..b2e4c22d 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -64,8 +64,7 @@
       callback = base::BindLambdaForTesting(
           [&success,
            &loop_quit](net::CanonicalCookie::CookieInclusionStatus s) {
-            success =
-                (s == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+            success = s.IsInclude();
             std::move(loop_quit).Run();
           });
   network::mojom::CookieManager* cookie_manager =
@@ -76,8 +75,9 @@
   cookie_manager->SetCanonicalCookie(
       cookie, google_url.scheme(), options,
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
-          std::move(callback),
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
+          std::move(callback), net::CanonicalCookie::CookieInclusionStatus(
+                                   net::CanonicalCookie::CookieInclusionStatus::
+                                       EXCLUDE_UNKNOWN_ERROR)));
   loop.Run();
   return success;
 }
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index fe9d024..4772d8e 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/files/file_path.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
@@ -306,10 +307,10 @@
 ChromeExtensionsAPIClient::CreateContentRulesRegistry(
     content::BrowserContext* browser_context,
     RulesCacheDelegate* cache_delegate) const {
-  return scoped_refptr<ContentRulesRegistry>(new ChromeContentRulesRegistry(
+  return base::MakeRefCounted<ChromeContentRulesRegistry>(
       browser_context, cache_delegate,
       base::Bind(&CreateDefaultContentPredicateEvaluators,
-                 base::Unretained(browser_context))));
+                 base::Unretained(browser_context)));
 }
 
 std::unique_ptr<DevicePermissionsPrompt>
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_service.cc b/chrome/browser/extensions/api/content_settings/content_settings_service.cc
index 66c59d56..4775799 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_service.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_service.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
 
 #include "base/lazy_instance.h"
+#include "base/memory/scoped_refptr.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_prefs_scope.h"
 #include "extensions/browser/pref_names.h"
@@ -12,7 +13,7 @@
 namespace extensions {
 
 ContentSettingsService::ContentSettingsService(content::BrowserContext* context)
-    : content_settings_store_(new ContentSettingsStore()),
+    : content_settings_store_(base::MakeRefCounted<ContentSettingsStore>()),
       scoped_observer_(this) {}
 
 ContentSettingsService::~ContentSettingsService() {}
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc
index 9636917..aca854a 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -468,8 +468,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK_EQ(NO_RESPONSE, state_);
   state_ = SET_COMPLETED;
-  success_ = (set_cookie_result ==
-              net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  success_ = set_cookie_result.IsInclude();
 }
 
 void CookiesSetFunction::GetCookieListCallback(
diff --git a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
index b7903610..b8d2c3b 100644
--- a/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
+++ b/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
@@ -82,7 +83,7 @@
             .get();
   }
 
-  scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
+  auto helper = base::MakeRefCounted<WebstoreInstallHelper>(
       this, params_->details.id, params_->details.manifest, icon_url);
 
   // The helper will call us back via OnWebstoreParseSuccess or
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 3699a97f..6cd0dd1f 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -14,6 +14,7 @@
 #include "base/files/file_util.h"
 #include "base/guid.h"
 #include "base/lazy_instance.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -1890,11 +1891,10 @@
   if (!web_contents)
     return RespondNow(Error(kCouldNotFindWebContentsError));
 
-  scoped_refptr<WebstoreReinstaller> reinstaller(new WebstoreReinstaller(
+  auto reinstaller = base::MakeRefCounted<WebstoreReinstaller>(
       web_contents, params->extension_id,
       base::BindOnce(
-          &DeveloperPrivateRepairExtensionFunction::OnReinstallComplete,
-          this)));
+          &DeveloperPrivateRepairExtensionFunction::OnReinstallComplete, this));
   reinstaller->BeginReinstall();
 
   return RespondLater();
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index 7343e74..f0dbae03 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/lazy_instance.h"
+#include "base/memory/scoped_refptr.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.h"
@@ -85,10 +86,10 @@
       ->GetURLLoaderFactoryForBrowserProcess()
       ->Clone(mojo::MakeRequest(&url_loader_factory_info));
 
-  scoped_refptr<Operation> operation(
-      new WriteFromUrlOperation(weak_factory_.GetWeakPtr(), extension_id,
-                                std::move(url_loader_factory_info), url, hash,
-                                device_path, GetAssociatedDownloadFolder()));
+  auto operation = base::MakeRefCounted<WriteFromUrlOperation>(
+      weak_factory_.GetWeakPtr(), extension_id,
+      std::move(url_loader_factory_info), url, hash, device_path,
+      GetAssociatedDownloadFolder());
   operations_[extension_id] = operation;
   operation->PostTask(base::BindOnce(&Operation::Start, operation));
 
@@ -112,9 +113,9 @@
     return;
   }
 
-  scoped_refptr<Operation> operation(
-      new WriteFromFileOperation(weak_factory_.GetWeakPtr(), extension_id, path,
-                                 device_path, GetAssociatedDownloadFolder()));
+  auto operation = base::MakeRefCounted<WriteFromFileOperation>(
+      weak_factory_.GetWeakPtr(), extension_id, path, device_path,
+      GetAssociatedDownloadFolder());
   operations_[extension_id] = operation;
   operation->PostTask(base::BindOnce(&Operation::Start, operation));
   std::move(callback).Run(true, "");
@@ -145,9 +146,9 @@
     return;
   }
 
-  scoped_refptr<Operation> operation(new DestroyPartitionsOperation(
+  auto operation = base::MakeRefCounted<DestroyPartitionsOperation>(
       weak_factory_.GetWeakPtr(), extension_id, device_path,
-      GetAssociatedDownloadFolder()));
+      GetAssociatedDownloadFolder());
   operations_[extension_id] = operation;
   operation->PostTask(base::BindOnce(&Operation::Start, operation));
   std::move(callback).Run(true, "");
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h
index 5dd0087..e333dd5b 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h
@@ -5,6 +5,7 @@
 #define CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_REMOVABLE_STORAGE_PROVIDER_H_
 
 #include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
 #include "chrome/common/extensions/api/image_writer_private.h"
 #include "chrome/common/ref_counted_util.h"
 
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
index 525557c..780f0c7 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
 
+#include "base/memory/scoped_refptr.h"
 #include "chromeos/disks/disk.h"
 #include "chromeos/disks/disk_mount_manager.h"
 
@@ -24,7 +25,7 @@
 RemovableStorageProvider::PopulateDeviceList() {
   DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
   const DiskMountManager::DiskMap& disks = disk_mount_manager->disks();
-  scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
+  auto device_list = base::MakeRefCounted<StorageDeviceList>();
 
   for (DiskMountManager::DiskMap::const_iterator iter = disks.begin();
        iter != disks.end();
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc
index fa04548..fa2976b 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include "base/files/file_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
 #include "content/public/browser/browser_thread.h"
@@ -57,7 +58,7 @@
     return nullptr;
   }
 
-  scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
+  auto device_list = base::MakeRefCounted<StorageDeviceList>();
   /* Create a list of the devices in the 'block' subsystem. */
   device::ScopedUdevEnumeratePtr enumerate(
       device::udev_enumerate_new(udev.get()));
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc
index 4cc1022..d6e49e8 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc
@@ -14,6 +14,7 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_ioobject.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "chrome/common/extensions/image_writer/image_writer_util_mac.h"
@@ -42,7 +43,7 @@
   }
 
   base::mac::ScopedIOObject<io_object_t> disk_obj;
-  scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
+  auto device_list = base::MakeRefCounted<StorageDeviceList>();
   while (disk_obj.reset(IOIteratorNext(disk_iterator)), disk_obj) {
     std::string bsd_name;
     uint64_t size_in_bytes;
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
index cd04a903..e069f5f 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_win.cc
@@ -15,6 +15,7 @@
 
 #include <memory>
 
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -197,7 +198,7 @@
   SP_DEVICE_INTERFACE_DATA interface_data;
   interface_data.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
 
-  scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
+  auto device_list = base::MakeRefCounted<StorageDeviceList>();
   while (SetupDiEnumDeviceInterfaces(
       interface_enumerator,
       NULL,                    // Device Info data.
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index c5670d60..edfdcbf 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/path_service.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
@@ -327,11 +328,11 @@
     const base::FilePath& profile_directory,
     bool require_native_initiated_connections,
     const std::string& connect_id)
-    : core_(new Core(allow_user_level_hosts,
-                     window_handle,
-                     profile_directory,
-                     require_native_initiated_connections,
-                     connect_id)) {}
+    : core_(base::MakeRefCounted<Core>(allow_user_level_hosts,
+                                       window_handle,
+                                       profile_directory,
+                                       require_native_initiated_connections,
+                                       connect_id)) {}
 
 NativeProcessLauncherImpl::~NativeProcessLauncherImpl() {
   core_->Detach();
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index b7199b5..874af5d5 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -16,6 +16,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
@@ -2002,8 +2003,7 @@
                           ? content::ZoomFactorToZoomLevel(params->zoom_factor)
                           : zoom_controller->GetDefaultZoomLevel();
 
-  scoped_refptr<ExtensionZoomRequestClient> client(
-      new ExtensionZoomRequestClient(extension()));
+  auto client = base::MakeRefCounted<ExtensionZoomRequestClient>(extension());
   if (!zoom_controller->SetZoomLevelByClient(zoom_level, client)) {
     // Tried to zoom a tab in disabled mode.
     return RespondNow(Error(tabs_constants::kCannotZoomDisabledTabError));
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index ce5a5c0..dcff38d5 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -234,7 +235,7 @@
             .get();
   }
 
-  scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
+  auto helper = base::MakeRefCounted<WebstoreInstallHelper>(
       this, details().id, details().manifest, icon_url);
 
   // The helper will call us back via OnWebstoreParseSuccess or
diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.cc b/chrome/browser/extensions/chrome_content_verifier_delegate.cc
index 3cf3b28..3c2c9a96 100644
--- a/chrome/browser/extensions/chrome_content_verifier_delegate.cc
+++ b/chrome/browser/extensions/chrome_content_verifier_delegate.cc
@@ -136,18 +136,16 @@
 ChromeContentVerifierDelegate::~ChromeContentVerifierDelegate() {
 }
 
-bool ChromeContentVerifierDelegate::ShouldBeChecked(
+ContentVerifierDelegate::VerifierSourceType
+ChromeContentVerifierDelegate::GetVerifierSourceType(
     const Extension& extension) {
-  // All policy-based extensions should have some checks.
-  return ShouldBeVerified(extension);
+  if (GetVerifyMode(extension) != NONE)
+    return VerifierSourceType::SIGNED_HASHES;
   // TODO(crbug.com/958794): After all preparations enable content checking for
   // all policy-based extension (even for self-hosted ones):
-  // || Manifest::IsPolicyLocation(extension.location());
-}
-
-bool ChromeContentVerifierDelegate::ShouldBeVerified(
-    const Extension& extension) {
-  return GetVerifyMode(extension) != NONE;
+  // if (Manifest::IsPolicyLocation(extension.location()))
+  //   return VerifierSourceType::UNSIGNED_HASHES;
+  return VerifierSourceType::NONE;
 }
 
 ContentVerifierKey ChromeContentVerifierDelegate::GetPublicKey() {
diff --git a/chrome/browser/extensions/chrome_content_verifier_delegate.h b/chrome/browser/extensions/chrome_content_verifier_delegate.h
index d6ee0026..1e365207 100644
--- a/chrome/browser/extensions/chrome_content_verifier_delegate.h
+++ b/chrome/browser/extensions/chrome_content_verifier_delegate.h
@@ -55,8 +55,7 @@
   ~ChromeContentVerifierDelegate() override;
 
   // ContentVerifierDelegate:
-  bool ShouldBeChecked(const Extension& extension) override;
-  bool ShouldBeVerified(const Extension& extension) override;
+  VerifierSourceType GetVerifierSourceType(const Extension& extension) override;
   ContentVerifierKey GetPublicKey() override;
   GURL GetSignatureFetchUrl(const std::string& extension_id,
                             const base::Version& version) override;
@@ -67,8 +66,8 @@
   void Shutdown() override;
 
  private:
-  // Returns what verification mode is appropriate for the given extension, or
-  // NONE if no verification is needed.
+  // Returns what action should be taken if given extension fails verification
+  // in some way, or NONE if no verification is needed.
   Mode GetVerifyMode(const Extension& extension);
 
   content::BrowserContext* context_;
diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc
index 46b80da19..b759304 100644
--- a/chrome/browser/extensions/default_apps.cc
+++ b/chrome/browser/extensions/default_apps.cc
@@ -122,12 +122,16 @@
 
 Provider::Provider(Profile* profile,
                    VisitorInterface* service,
-                   extensions::ExternalLoader* loader,
+                   scoped_refptr<extensions::ExternalLoader> loader,
                    extensions::Manifest::Location crx_location,
                    extensions::Manifest::Location download_location,
                    int creation_flags)
-    : extensions::ExternalProviderImpl(service, loader, profile, crx_location,
-                                       download_location, creation_flags),
+    : extensions::ExternalProviderImpl(service,
+                                       std::move(loader),
+                                       profile,
+                                       crx_location,
+                                       download_location,
+                                       creation_flags),
       profile_(profile),
       is_migration_(false) {
   DCHECK(profile);
diff --git a/chrome/browser/extensions/default_apps.h b/chrome/browser/extensions/default_apps.h
index 10f477b..d98f43cd 100644
--- a/chrome/browser/extensions/default_apps.h
+++ b/chrome/browser/extensions/default_apps.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_EXTENSIONS_DEFAULT_APPS_H_
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "chrome/browser/extensions/external_provider_impl.h"
 #include "extensions/common/manifest.h"
 
@@ -43,7 +44,7 @@
  public:
   Provider(Profile* profile,
            VisitorInterface* service,
-           extensions::ExternalLoader* loader,
+           scoped_refptr<extensions::ExternalLoader> loader,
            extensions::Manifest::Location crx_location,
            extensions::Manifest::Location download_location,
            int creation_flags);
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 168d741..80e3abd 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4862,7 +4862,7 @@
   ExtensionCookieCallback() : result_(false) {}
 
   void SetCookieCallback(net::CanonicalCookie::CookieInclusionStatus result) {
-    result_ = (result == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+    result_ = result.IsInclude();
   }
 
   void GetAllCookiesCallback(const net::CookieStatusList& list,
@@ -4994,8 +4994,7 @@
 void SetCookieSaveData(bool* result_out,
                        base::OnceClosure callback,
                        net::CanonicalCookie::CookieInclusionStatus result) {
-  *result_out =
-      (result == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  *result_out = result.IsInclude();
   std::move(callback).Run();
 }
 
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index fbe84d7..fc7866e 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -105,7 +105,8 @@
 }
 
 void ExtensionSystemImpl::Shared::InitPrefs() {
-  store_factory_ = new ValueStoreFactoryImpl(profile_->GetPath());
+  store_factory_ =
+      base::MakeRefCounted<ValueStoreFactoryImpl>(profile_->GetPath());
 
   // Two state stores. The latter, which contains declarative rules, must be
   // loaded immediately so that the rules are ready before we issue network
@@ -326,7 +327,7 @@
 
 InfoMap* ExtensionSystemImpl::Shared::info_map() {
   if (!extension_info_map_.get())
-    extension_info_map_ = new InfoMap();
+    extension_info_map_ = base::MakeRefCounted<InfoMap>();
   return extension_info_map_.get();
 }
 
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc
index 7e5d418..4c6f975 100644
--- a/chrome/browser/extensions/extension_web_ui.cc
+++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -12,6 +12,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -263,8 +264,7 @@
       image.AsImageSkia().image_reps();
   for (size_t i = 0; i < image_reps.size(); ++i) {
     const gfx::ImageSkiaRep& image_rep = image_reps[i];
-    scoped_refptr<base::RefCountedBytes> bitmap_data(
-        new base::RefCountedBytes());
+    auto bitmap_data = base::MakeRefCounted<base::RefCountedBytes>();
     if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.GetBitmap(), false,
                                           &bitmap_data->data())) {
       favicon_base::FaviconRawBitmapResult bitmap_result;
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 3265e83a..e3c70a38 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -14,6 +14,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/field_trial.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
@@ -593,7 +594,7 @@
     // them as built-in extensions. Extensions (not apps) installed through this
     // path will have type |TYPE_LOGIN_SCREE_EXTENSION| with limited API
     // capabilities.
-    external_loader = new ExternalPolicyLoader(
+    external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
         profile, ExtensionManagementFactory::GetForBrowserContext(profile),
         ExternalPolicyLoader::FORCED);
     auto signin_profile_provider = std::make_unique<ExternalProviderImpl>(
@@ -627,18 +628,18 @@
       NOTREACHED();
     }
   } else {
-    external_loader = new ExternalPolicyLoader(
+    external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
         profile, ExtensionManagementFactory::GetForBrowserContext(profile),
         ExternalPolicyLoader::FORCED);
-    external_recommended_loader = new ExternalPolicyLoader(
+    external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
         profile, ExtensionManagementFactory::GetForBrowserContext(profile),
         ExternalPolicyLoader::RECOMMENDED);
   }
 #else
-  external_loader = new ExternalPolicyLoader(
+  external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
       profile, ExtensionManagementFactory::GetForBrowserContext(profile),
       ExternalPolicyLoader::FORCED);
-  external_recommended_loader = new ExternalPolicyLoader(
+  external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
       profile, ExtensionManagementFactory::GetForBrowserContext(profile),
       ExternalPolicyLoader::RECOMMENDED);
 #endif
@@ -731,8 +732,9 @@
     pref_load_flags |= ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER;
     provider_list->push_back(std::make_unique<ExternalProviderImpl>(
         service,
-        new ExternalPrefLoader(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
-                               pref_load_flags, profile),
+        base::MakeRefCounted<ExternalPrefLoader>(
+            chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, pref_load_flags,
+            profile),
         profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
         bundled_extension_creation_flags));
 
@@ -766,9 +768,9 @@
 #elif defined(OS_LINUX)
   provider_list->push_back(std::make_unique<ExternalProviderImpl>(
       service,
-      new ExternalPrefLoader(chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
-                             ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER,
-                             profile),
+      base::MakeRefCounted<ExternalPrefLoader>(
+          chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
+          ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER, profile),
       profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
       bundled_extension_creation_flags));
 #endif
@@ -784,8 +786,9 @@
 #else
     provider_list->push_back(std::make_unique<ExternalProviderImpl>(
         service,
-        new ExternalPrefLoader(chrome::DIR_EXTERNAL_EXTENSIONS,
-                               check_admin_permissions_on_mac, nullptr),
+        base::MakeRefCounted<ExternalPrefLoader>(
+            chrome::DIR_EXTERNAL_EXTENSIONS, check_admin_permissions_on_mac,
+            nullptr),
         profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
         bundled_extension_creation_flags));
 
@@ -793,8 +796,9 @@
 #if defined(OS_MACOSX) || (defined(OS_LINUX) && BUILDFLAG(CHROMIUM_BRANDING))
     provider_list->push_back(std::make_unique<ExternalProviderImpl>(
         service,
-        new ExternalPrefLoader(chrome::DIR_USER_EXTERNAL_EXTENSIONS,
-                               ExternalPrefLoader::NONE, nullptr),
+        base::MakeRefCounted<ExternalPrefLoader>(
+            chrome::DIR_USER_EXTERNAL_EXTENSIONS, ExternalPrefLoader::NONE,
+            nullptr),
         profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
         Extension::NO_FLAGS));
 #endif
@@ -805,8 +809,8 @@
     // extension installer codeflow.
     provider_list->push_back(std::make_unique<default_apps::Provider>(
         profile, service,
-        new ExternalPrefLoader(chrome::DIR_DEFAULT_APPS,
-                               ExternalPrefLoader::NONE, nullptr),
+        base::MakeRefCounted<ExternalPrefLoader>(
+            chrome::DIR_DEFAULT_APPS, ExternalPrefLoader::NONE, nullptr),
         Manifest::INTERNAL, Manifest::INTERNAL,
         Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
 #endif
@@ -814,8 +818,9 @@
     std::unique_ptr<ExternalProviderImpl> drive_migration_provider(
         new ExternalProviderImpl(
             service,
-            new ExtensionMigrator(profile, extension_misc::kDriveHostedAppId,
-                                  extension_misc::kDocsOfflineExtensionId),
+            base::MakeRefCounted<ExtensionMigrator>(
+                profile, extension_misc::kDriveHostedAppId,
+                extension_misc::kDocsOfflineExtensionId),
             profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
             Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
     drive_migration_provider->set_auto_acknowledge(true);
@@ -823,7 +828,7 @@
   }
 
   provider_list->push_back(std::make_unique<ExternalProviderImpl>(
-      service, new ExternalComponentLoader(profile), profile,
+      service, base::MakeRefCounted<ExternalComponentLoader>(profile), profile,
       Manifest::INVALID_LOCATION, Manifest::EXTERNAL_COMPONENT,
       Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
 }
diff --git a/chrome/browser/extensions/webstore_standalone_installer.cc b/chrome/browser/extensions/webstore_standalone_installer.cc
index 85726d21..d323555 100644
--- a/chrome/browser/extensions/webstore_standalone_installer.cc
+++ b/chrome/browser/extensions/webstore_standalone_installer.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "chrome/browser/extensions/crx_installer.h"
@@ -215,9 +216,9 @@
     return;
   }
 
-  scoped_refptr<WebstoreInstaller> installer =
-      new WebstoreInstaller(profile_, this, GetWebContents(), id_,
-                            std::move(approval), install_source_);
+  auto installer = base::MakeRefCounted<WebstoreInstaller>(
+      profile_, this, GetWebContents(), id_, std::move(approval),
+      install_source_);
   installer->Start();
 }
 
@@ -291,8 +292,8 @@
   // Assume ownership of webstore_data.
   webstore_data_ = std::move(webstore_data);
 
-  scoped_refptr<WebstoreInstallHelper> helper =
-      new WebstoreInstallHelper(this, id_, manifest, icon_url);
+  auto helper = base::MakeRefCounted<WebstoreInstallHelper>(this, id_, manifest,
+                                                            icon_url);
   // The helper will call us back via OnWebstoreParseSuccess() or
   // OnWebstoreParseFailure().
   helper->Start(content::BrowserContext::GetDefaultStoragePartition(profile_)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 779f13709..3c13fd83 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1529,6 +1529,11 @@
     "expiry_milestone": 78
   },
   {
+    "name": "enable-removing-all-third-party-cookies",
+    "owners": [ "dullweber" ],
+    "expiry_milestone": 82
+  },
+  {
     "name": "enable-reopen-tab-in-product-help",
     "owners": [ "collinbaker" ],
     "expiry_milestone": 76
@@ -2464,11 +2469,6 @@
     "expiry_milestone": 85
   },
   {
-    "name": "ntp-zero-suggest",
-    "owners": ["dbeam", "mahmadi"],
-    "expiry_milestone": 85
-  },
-  {
     "name": "oculus-vr",
     "owners": [ "//device/vr/OWNERS", "xr-dev@chromium.org" ],
     "expiry_milestone": 79
@@ -2700,7 +2700,7 @@
   },
   {
     "name": "omnibox-zero-suggestions-on-ntp",
-    "owners": [ "chrome-android-omnibox-team@google.com" ],
+    "owners": [ "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 81
   },
   {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index cf8030d0..6ed1ba9 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -560,6 +560,12 @@
 const char kEnableNoScriptPreviewsDescription[] =
     "Enable disabling JavaScript on some pages on slow networks.";
 
+const char kEnableRemovingAllThirdPartyCookiesName[] =
+    "Enable removing SameSite=None cookies";
+const char kEnableRemovingAllThirdPartyCookiesDescription[] =
+    "Enables UI on chrome://settings/siteData to remove all third-party "
+    "cookies and site data.";
+
 const char kDataReductionProxyServerAlternative1[] = "Use alt. server config 1";
 const char kDataReductionProxyServerAlternative2[] = "Use alt. server config 2";
 const char kDataReductionProxyServerAlternative3[] = "Use alt. server config 3";
@@ -2798,12 +2804,6 @@
     "directly (i.e. not be a \"fake\" box). Search results will show below the "
     "non-fake input (\"realbox\").";
 
-const char kNtpZeroSuggestName[] =
-    "Suggest New Tab Page search results without input";
-const char kNtpZeroSuggestDescription[] =
-    "If enabled, forces on \"Real search box in New Tab Page\" and suggests "
-    "results without any typed input (i.e. on focus).";
-
 const char kEnableImprovedCookieControlsName[] =
     "Enable improved cookie controls UI";
 const char kEnableImprovedCookieControlsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index ce3dafe..72c7bb3d 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -350,6 +350,9 @@
 extern const char kEnableNoScriptPreviewsName[];
 extern const char kEnableNoScriptPreviewsDescription[];
 
+extern const char kEnableRemovingAllThirdPartyCookiesName[];
+extern const char kEnableRemovingAllThirdPartyCookiesDescription[];
+
 extern const char kDataReductionProxyServerAlternative1[];
 extern const char kDataReductionProxyServerAlternative2[];
 extern const char kDataReductionProxyServerAlternative3[];
@@ -1655,9 +1658,6 @@
 extern const char kNtpRealboxName[];
 extern const char kNtpRealboxDescription[];
 
-extern const char kNtpZeroSuggestName[];
-extern const char kNtpZeroSuggestDescription[];
-
 extern const char kEnableImprovedCookieControlsName[];
 extern const char kEnableImprovedCookieControlsDescription[];
 
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
index 202eed8..758a9c5 100644
--- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
+++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
@@ -145,7 +145,10 @@
 
   // If this is set to true not only is the given path blocked, all the children
   // are blocked as well. When this is set to false only the path and its
-  // parents are blocked.
+  // parents are blocked. If a blocked path is a descendent of another blocked
+  // path, then it may override the child-blocking policy of its ancestor. For
+  // example, if /home blocks all children, but /home/downloads does not, then
+  // /home/downloads/file.ext should *not* be blocked.
   bool block_all_children;
 } kBlockedPaths[] = {
     // Don't allow users to share their entire home directory, entire desktop or
@@ -203,6 +206,9 @@
 bool ShouldBlockAccessToPath(const base::FilePath& check_path) {
   DCHECK(!check_path.empty());
   DCHECK(check_path.IsAbsolute());
+
+  base::FilePath nearest_ancestor;
+  bool nearest_ancestor_blocks_all_children = false;
   for (const auto& block : kBlockedPaths) {
     base::FilePath blocked_path;
     if (block.base_path_key != kNoBasePathKey) {
@@ -218,10 +224,14 @@
     if (check_path == blocked_path || check_path.IsParent(blocked_path))
       return true;
 
-    if (block.block_all_children && blocked_path.IsParent(check_path))
-      return true;
+    if (blocked_path.IsParent(check_path) &&
+        (nearest_ancestor.empty() || nearest_ancestor.IsParent(blocked_path))) {
+      nearest_ancestor = blocked_path;
+      nearest_ancestor_blocks_all_children = block.block_all_children;
+    }
   }
-  return false;
+
+  return !nearest_ancestor.empty() && nearest_ancestor_blocks_all_children;
 }
 
 // Returns a callback that calls the passed in |callback| by posting a task to
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
index db3c0541..0c11e70b 100644
--- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
+++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
@@ -365,6 +365,33 @@
 }
 
 TEST_F(ChromeNativeFileSystemPermissionContextTest,
+       ConfirmSensitiveDirectoryAccess_BlockChildrenNested) {
+  base::FilePath user_data_dir = temp_dir_.GetPath().AppendASCII("user");
+  base::ScopedPathOverride user_data_override(chrome::DIR_USER_DATA,
+                                              user_data_dir, true, true);
+  base::FilePath download_dir = user_data_dir.AppendASCII("downloads");
+  base::ScopedPathOverride download_override(chrome::DIR_DEFAULT_DOWNLOADS,
+                                             download_dir, true, true);
+
+  // User Data directory itself should not be allowed.
+  EXPECT_EQ(SensitiveDirectoryResult::kAbort,
+            ConfirmSensitiveDirectoryAccessSync(permission_context(),
+                                                {user_data_dir}));
+  // Parent of User Data directory should also not be allowed.
+  EXPECT_EQ(SensitiveDirectoryResult::kAbort,
+            ConfirmSensitiveDirectoryAccessSync(permission_context(),
+                                                {temp_dir_.GetPath()}));
+  // The nested Download directory itself should not be allowed.
+  EXPECT_EQ(SensitiveDirectoryResult::kAbort,
+            ConfirmSensitiveDirectoryAccessSync(permission_context(),
+                                                {download_dir}));
+  // Paths inside the nested Download directory should be allowed.
+  EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
+            ConfirmSensitiveDirectoryAccessSync(
+                permission_context(), {download_dir.AppendASCII("foo")}));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest,
        ConfirmSensitiveDirectoryAccess_RelativePathBlock) {
   base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home");
   base::ScopedPathOverride home_override(base::DIR_HOME, home_dir, true, true);
diff --git a/chrome/browser/notifications/scheduler/internal/BUILD.gn b/chrome/browser/notifications/scheduler/internal/BUILD.gn
index af7f0c4..fd22666e 100644
--- a/chrome/browser/notifications/scheduler/internal/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/internal/BUILD.gn
@@ -90,6 +90,7 @@
     "proto_conversion_unittest.cc",
     "scheduled_notification_manager_unittest.cc",
     "scheduler_utils_unittest.cc",
+    "stats_unittest.cc",
   ]
 
   deps = [
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
index d37849a..8e0051ce 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
@@ -236,6 +236,8 @@
         entry->type, entry->guid, entry->schedule_params.impression_mapping,
         updated_notification_data->custom_data);
 
+    stats::LogNotificationShow(*updated_notification_data, entry->type);
+
     // Show the notification in UI.
     auto system_data = std::make_unique<DisplayAgent::SystemData>();
     system_data->type = entry->type;
diff --git a/chrome/browser/notifications/scheduler/internal/stats.cc b/chrome/browser/notifications/scheduler/internal/stats.cc
index bf1ffd3..621069d 100644
--- a/chrome/browser/notifications/scheduler/internal/stats.cc
+++ b/chrome/browser/notifications/scheduler/internal/stats.cc
@@ -4,13 +4,19 @@
 
 #include "chrome/browser/notifications/scheduler/internal/stats.h"
 
+#include <string>
+
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/notifications/scheduler/public/notification_data.h"
 
 namespace notifications {
 namespace stats {
 namespace {
 
+const char kIhnrActionButtonEventHistogram[] =
+    "Notifications.Scheduler.IhnrActionButtonEvent";
+
 // Returns the histogram suffix for a client type. Should match suffix
 // NotificationSchedulerClientType in histograms.xml.
 std::string ToHistogramSuffix(SchedulerClientType client_type) {
@@ -26,13 +32,41 @@
   }
 }
 
+// Logs a histogram enumeration with client type suffix.
+template <typename T>
+void LogHistogramEnumWithSuffix(const std::string& name,
+                                T value,
+                                SchedulerClientType client_type) {
+  base::UmaHistogramEnumeration(name, value);
+  auto name_with_suffix = name;
+  name_with_suffix.append(".").append(ToHistogramSuffix(client_type));
+  base::UmaHistogramEnumeration(name_with_suffix, value);
+}
+
 }  // namespace
 
 void LogUserAction(const UserActionData& action_data) {
-  std::string name("Notifications.Scheduler.UserAction");
-  base::UmaHistogramEnumeration(name, action_data.action_type);
-  name.append(".").append(ToHistogramSuffix(action_data.client_type));
-  base::UmaHistogramEnumeration(name, action_data.action_type);
+  // Logs action type.
+  LogHistogramEnumWithSuffix("Notifications.Scheduler.UserAction",
+                             action_data.action_type, action_data.client_type);
+
+  // Logs inline helpful/unhelpful buttons clicks.
+  if (action_data.button_click_info.has_value()) {
+    switch (action_data.button_click_info->type) {
+      case ActionButtonType::kHelpful:
+        LogHistogramEnumWithSuffix(kIhnrActionButtonEventHistogram,
+                                   ActionButtonEvent::kHelpfulClick,
+                                   action_data.client_type);
+        break;
+      case ActionButtonType::kUnhelpful:
+        LogHistogramEnumWithSuffix(kIhnrActionButtonEventHistogram,
+                                   ActionButtonEvent::kUnhelpfulClick,
+                                   action_data.client_type);
+        break;
+      case ActionButtonType::kUnknownAction:
+        break;
+    }
+  }
 }
 
 void LogBackgroundTaskEvent(BackgroundTaskEvent event) {
@@ -91,6 +125,23 @@
       "Notifications.Scheduler.NotificationDb.OperationResult", success);
 }
 
+void LogNotificationShow(const NotificationData& notification_data,
+                         SchedulerClientType client_type) {
+  bool has_ihnr_button = false;
+  for (const auto& button : notification_data.buttons) {
+    if (button.type == ActionButtonType::kHelpful ||
+        button.type == ActionButtonType::kUnhelpful) {
+      has_ihnr_button = true;
+      break;
+    }
+  }
+
+  if (has_ihnr_button) {
+    LogHistogramEnumWithSuffix(kIhnrActionButtonEventHistogram,
+                               ActionButtonEvent::kShown, client_type);
+  }
+}
+
 void LogPngIconConverterEncodeResult(bool success) {
   UMA_HISTOGRAM_BOOLEAN("Notifications.Scheduler.PngIconConverter.EncodeResult",
                         success);
diff --git a/chrome/browser/notifications/scheduler/internal/stats.h b/chrome/browser/notifications/scheduler/internal/stats.h
index b04c5f4..6a570305 100644
--- a/chrome/browser/notifications/scheduler/internal/stats.h
+++ b/chrome/browser/notifications/scheduler/internal/stats.h
@@ -8,6 +8,7 @@
 #include "chrome/browser/notifications/scheduler/public/notification_scheduler_types.h"
 
 namespace notifications {
+struct NotificationData;
 namespace stats {
 
 // Events to track behavior of the background task used by notification
@@ -23,6 +24,19 @@
   kMaxValue = kStopByOS
 };
 
+// Used to log events for inline helpful/unhelful button events. Don't reuse or
+// delete values. Needs to match NotificationSchedulerActionButtonEvent in
+// enums.xml.
+enum class ActionButtonEvent {
+  // The notification is shown with IHNR buttons.
+  kShown = 0,
+  // Clicks on the helpful button.
+  kHelpfulClick = 1,
+  // Clicks on the unhelpful button.
+  kUnhelpfulClick = 2,
+  kMaxValue = kUnhelpfulClick
+};
+
 // Used to log events in impression tracker. Don't reuse or delete values. Needs
 // to match NotificationSchedulerImpressionEvent in enums.xml.
 enum class ImpressionEvent {
@@ -64,6 +78,10 @@
 // Logs notification db operations result except the initialization.
 void LogNotificationDbOperation(bool success);
 
+// Logs metrics before showing the notification.
+void LogNotificationShow(const NotificationData& notification_data,
+                         SchedulerClientType client_type);
+
 // Logs png icon converter encode result.
 void LogPngIconConverterEncodeResult(bool success);
 
diff --git a/chrome/browser/notifications/scheduler/internal/stats_unittest.cc b/chrome/browser/notifications/scheduler/internal/stats_unittest.cc
new file mode 100644
index 0000000..3ea4820
--- /dev/null
+++ b/chrome/browser/notifications/scheduler/internal/stats_unittest.cc
@@ -0,0 +1,83 @@
+// 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/notifications/scheduler/internal/stats.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "chrome/browser/notifications/scheduler/public/notification_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace notifications {
+namespace stats {
+namespace {
+
+const char kIhnrActionButtonEventHistogram[] =
+    "Notifications.Scheduler.IhnrActionButtonEvent";
+
+const char kIhnrActionButtonEventTestHistogram[] =
+    "Notifications.Scheduler.IhnrActionButtonEvent.__Test__";
+
+void TestLogUserAction(const UserActionData& user_action_data,
+                       ActionButtonEvent action_button_event) {
+  base::HistogramTester histograms;
+  LogUserAction(user_action_data);
+  histograms.ExpectBucketCount("Notifications.Scheduler.UserAction",
+                               user_action_data.action_type, 1);
+  histograms.ExpectBucketCount("Notifications.Scheduler.UserAction.__Test__",
+                               user_action_data.action_type, 1);
+  histograms.ExpectBucketCount(kIhnrActionButtonEventHistogram,
+                               action_button_event, 1);
+  histograms.ExpectBucketCount(kIhnrActionButtonEventTestHistogram,
+                               action_button_event, 1);
+}
+
+void TestNotificationShow(const NotificationData& notification_data,
+                          SchedulerClientType client_type,
+                          bool expect_ihnr_histogram) {
+  base::HistogramTester histograms;
+  LogNotificationShow(notification_data, client_type);
+  if (expect_ihnr_histogram) {
+    histograms.ExpectBucketCount(kIhnrActionButtonEventHistogram,
+                                 ActionButtonEvent::kShown, 1);
+    histograms.ExpectBucketCount(kIhnrActionButtonEventTestHistogram,
+                                 ActionButtonEvent::kShown, 1);
+  } else {
+    histograms.ExpectTotalCount(kIhnrActionButtonEventHistogram, 0);
+    histograms.ExpectTotalCount(kIhnrActionButtonEventTestHistogram, 0);
+  }
+}
+
+// Verifies that ihnr buttons clicks are logged.
+TEST(NotificationSchedulerStatsTest, LogUserActionIhnrButton) {
+  UserActionData user_action_data(SchedulerClientType::kTest1,
+                                  UserActionType::kButtonClick, "guid");
+  user_action_data.button_click_info = ButtonClickInfo();
+  user_action_data.button_click_info->type = ActionButtonType::kHelpful;
+  TestLogUserAction(user_action_data, ActionButtonEvent::kHelpfulClick);
+
+  user_action_data.button_click_info->type = ActionButtonType::kUnhelpful;
+  TestLogUserAction(user_action_data, ActionButtonEvent::kUnhelpfulClick);
+}
+
+// Verifies notification show event is logged when there are ihnr buttons.
+TEST(NotificationSchedulerStatsTest, LogNotificationShow) {
+  NotificationData notification_data;
+  notification_data.buttons.emplace_back(NotificationData::Button());
+  // Notification without ihnr buttons.
+  TestNotificationShow(notification_data, SchedulerClientType::kTest1,
+                       false /*expect_ihnr_histogram*/);
+
+  std::vector<ActionButtonType> types{ActionButtonType::kHelpful,
+                                      ActionButtonType::kUnhelpful};
+  for (auto action_button_type : types) {
+    notification_data.buttons.front().type = action_button_type;
+    // Notification with ihnr buttons.
+    TestNotificationShow(notification_data, SchedulerClientType::kTest1,
+                         true /*expect_ihnr_histogram*/);
+  }
+}
+
+}  // namespace
+}  // namespace stats
+}  // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/public/notification_data.cc b/chrome/browser/notifications/scheduler/public/notification_data.cc
index d71479e..f878d83 100644
--- a/chrome/browser/notifications/scheduler/public/notification_data.cc
+++ b/chrome/browser/notifications/scheduler/public/notification_data.cc
@@ -6,7 +6,7 @@
 
 namespace notifications {
 
-NotificationData::Button::Button() = default;
+NotificationData::Button::Button() : type(ActionButtonType::kUnknownAction) {}
 NotificationData::Button::Button(const Button& other) = default;
 
 bool NotificationData::Button::operator==(const Button& other) const {
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 2530afeb..a561f0b 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1185,7 +1185,8 @@
   ASSERT_TRUE(content::ExecuteScript(
       guest_contents,
       "viewer.navigator_.navigate("
-      "    'www.example.com', Navigator.WindowOpenDisposition.CURRENT_TAB);"));
+      "    'www.example.com',"
+      "    PdfNavigator.WindowOpenDisposition.CURRENT_TAB);"));
   navigation_observer.Wait();
 
   EXPECT_FALSE(navigation_observer.last_navigation_url().is_empty());
diff --git a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
index 6c8a806..44d583f7 100644
--- a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
@@ -115,7 +115,7 @@
 
 void RemoveCookieTester::SetCanonicalCookieCallback(
     net::CanonicalCookie::CookieInclusionStatus result) {
-  ASSERT_TRUE(result == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  ASSERT_TRUE(result.IsInclude());
   Notify();
 }
 
diff --git a/chrome/browser/resources/chromeos/camera/src/js/state.js b/chrome/browser/resources/chromeos/camera/src/js/state.js
index a9c67d7..9b22dc1 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/state.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/state.js
@@ -15,6 +15,42 @@
 cca.state = cca.state || {};
 
 /**
+ * @type {!Map<string, Set<!function(boolean)>>}
+ * @private
+ */
+cca.state.observers_ = new Map();
+
+/**
+ * Adds observer function to be called on any state change.
+ * @param {string} state State to be observed.
+ * @param {!function(boolean)} observer Observer function called with newly
+ *     changed value.
+ */
+cca.state.addObserver = function(state, observer) {
+  let observers = cca.state.observers_.get(state);
+  if (observers === undefined) {
+    observers = new Set();
+    cca.state.observers_.set(state, observers);
+  }
+  observers.add(observer);
+};
+
+/**
+ * Removes observer function to be called on state change.
+ * @param {string} state State to remove observer from.
+ * @param {!function(boolean)} observer Observer function to be removed.
+ * @return {boolean} Whether the observer is in the set and is removed
+ *     successfully or not.
+ */
+cca.state.removeObserver = function(state, observer) {
+  const observers = cca.state.observers_.get(state);
+  if (observers === undefined) {
+    return false;
+  }
+  return observers.delete(observer);
+};
+
+/**
  * Checks if the specified state exists.
  * @param {string} state State to be checked.
  * @return {boolean} Whether the state exists.
@@ -29,5 +65,11 @@
  * @param {boolean} val True to set the state on, false otherwise.
  */
 cca.state.set = function(state, val) {
+  const oldVal = cca.state.get(state);
+  if (oldVal == val) {
+    return;
+  }
   document.body.classList.toggle(state, val);
+  const observers = cca.state.observers_.get(state) || [];
+  observers.forEach((f) => f(val));
 };
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index 0a5dea7..89a0223c 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -79,11 +79,19 @@
   externs_list = [ "$externs_path/metrics_private.js" ]
 }
 
+js_library("navigator") {
+  deps = [
+    ":open_pdf_params_parser",
+    ":viewport",
+  ]
+}
+
 js_type_check("pdf_resources") {
   deps = [
     ":browser_api",
     ":gesture_detector",
     ":metrics",
+    ":navigator",
     ":open_pdf_params_parser",
     ":pdf_fitting_type",
     ":pdf_scripting_api",
diff --git a/chrome/browser/resources/pdf/navigator.js b/chrome/browser/resources/pdf/navigator.js
index 0282e725..ca9cf608 100644
--- a/chrome/browser/resources/pdf/navigator.js
+++ b/chrome/browser/resources/pdf/navigator.js
@@ -5,42 +5,24 @@
 'use strict';
 
 /**
- * Creates a new NavigatorDelegate for calling browser-specific functions to
- * do the actual navigating.
- *
- * @param {number} tabId The tab ID of the PDF viewer or -1 if the viewer is
- *    not displayed in a tab.
- * @constructor
+ * NavigatorDelegate for calling browser-specific functions to do the actual
+ * navigating.
  */
-function NavigatorDelegate(tabId) {
-  this.tabId_ = tabId;
-}
+class NavigatorDelegate {
+  /**
+   * @param {number} tabId The tab ID of the PDF viewer or -1 if the viewer is
+   *     not displayed in a tab.
+   */
+  constructor(tabId) {
+    /** @private {number} */
+    this.tabId_ = tabId;
+  }
 
-/**
- * Creates a new Navigator for navigating to links inside or outside the PDF.
- *
- * @param {string} originalUrl The original page URL.
- * @param {Object} viewport The viewport info of the page.
- * @param {Object} paramsParser The object for URL parsing.
- * @param {Object} navigatorDelegate The object with callback functions that
- *    get called when navigation happens in the current tab, a new tab,
- *    and a new window.
- * @constructor
- */
-function Navigator(originalUrl, viewport, paramsParser, navigatorDelegate) {
-  this.originalUrl_ = originalUrl;
-  this.viewport_ = viewport;
-  this.paramsParser_ = paramsParser;
-  this.navigatorDelegate_ = navigatorDelegate;
-}
-
-NavigatorDelegate.prototype = {
   /**
    * Called when navigation should happen in the current tab.
-   *
    * @param {string} url The url to be opened in the current tab.
    */
-  navigateInCurrentTab: function(url) {
+  navigateInCurrentTab(url) {
     // When the PDFviewer is inside a browser tab, prefer the tabs API because
     // it can navigate from one file:// URL to another.
     if (chrome.tabs && this.tabId_ != -1) {
@@ -48,15 +30,14 @@
     } else {
       window.location.href = url;
     }
-  },
+  }
 
   /**
    * Called when navigation should happen in the new tab.
-   *
    * @param {string} url The url to be opened in the new tab.
    * @param {boolean} active Indicates if the new tab should be the active tab.
    */
-  navigateInNewTab: function(url, active) {
+  navigateInNewTab(url, active) {
     // Prefer the tabs API because it guarantees we can just open a new tab.
     // window.open doesn't have this guarantee.
     if (chrome.tabs) {
@@ -64,14 +45,13 @@
     } else {
       window.open(url);
     }
-  },
+  }
 
   /**
    * Called when navigation should happen in the new window.
-   *
    * @param {string} url The url to be opened in the new window.
    */
-  navigateInNewWindow: function(url) {
+  navigateInNewWindow(url) {
     // Prefer the windows API because it guarantees we can just open a new
     // window. window.open with '_blank' argument doesn't have this guarantee.
     if (chrome.windows) {
@@ -80,32 +60,33 @@
       window.open(url, '_blank');
     }
   }
-};
+}
 
-/**
- * Represents options when navigating to a new url. C++ counterpart of
- * the enum is in ui/base/window_open_disposition.h. This enum represents
- * the only values that are passed from Plugin.
- * @enum {number}
- */
-Navigator.WindowOpenDisposition = {
-  CURRENT_TAB: 1,
-  NEW_FOREGROUND_TAB: 3,
-  NEW_BACKGROUND_TAB: 4,
-  NEW_WINDOW: 6,
-  SAVE_TO_DISK: 7
-};
+/** Navigator for navigating to links inside or outside the PDF. */
+class PdfNavigator {
+  /**
+   * @param {string} originalUrl The original page URL.
+   * @param {!Viewport} viewport The viewport info of the page.
+   * @param {!OpenPdfParamsParser} paramsParser The object for URL parsing.
+   * @param {!NavigatorDelegate} navigatorDelegate The object with callback
+   *    functions that get called when navigation happens in the current tab,
+   *    a new tab, and a new window.
+   */
+  constructor(originalUrl, viewport, paramsParser, navigatorDelegate) {
+    this.originalUrl_ = originalUrl;
+    this.viewport_ = viewport;
+    this.paramsParser_ = paramsParser;
+    this.navigatorDelegate_ = navigatorDelegate;
+  }
 
-Navigator.prototype = {
   /**
    * Function to navigate to the given URL. This might involve navigating
    * within the PDF page or opening a new url (in the same tab or a new tab).
-   *
    * @param {string} url The URL to navigate to.
-   * @param {number} disposition The window open disposition when
-   *    navigating to the new URL.
+   * @param {!PdfNavigator.WindowOpenDisposition} disposition The window open
+   *     disposition when navigating to the new URL.
    */
-  navigate: function(url, disposition) {
+  navigate(url, disposition) {
     if (url.length == 0) {
       return;
     }
@@ -133,20 +114,20 @@
     }
 
     switch (disposition) {
-      case Navigator.WindowOpenDisposition.CURRENT_TAB:
+      case PdfNavigator.WindowOpenDisposition.CURRENT_TAB:
         this.paramsParser_.getViewportFromUrlParams(
             url, this.onViewportReceived_.bind(this));
         break;
-      case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
+      case PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
         this.navigatorDelegate_.navigateInNewTab(url, false);
         break;
-      case Navigator.WindowOpenDisposition.NEW_FOREGROUND_TAB:
+      case PdfNavigator.WindowOpenDisposition.NEW_FOREGROUND_TAB:
         this.navigatorDelegate_.navigateInNewTab(url, true);
         break;
-      case Navigator.WindowOpenDisposition.NEW_WINDOW:
+      case PdfNavigator.WindowOpenDisposition.NEW_WINDOW:
         this.navigatorDelegate_.navigateInNewWindow(url);
         break;
-      case Navigator.WindowOpenDisposition.SAVE_TO_DISK:
+      case PdfNavigator.WindowOpenDisposition.SAVE_TO_DISK:
         // TODO(jaepark): Alt + left clicking a link in PDF should
         // download the link.
         this.paramsParser_.getViewportFromUrlParams(
@@ -155,16 +136,15 @@
       default:
         break;
     }
-  },
+  }
 
   /**
    * Called when the viewport position is received.
-   *
    * @param {Object} viewportPosition Dictionary containing the viewport
    *    position.
    * @private
    */
-  onViewportReceived_: function(viewportPosition) {
+  onViewportReceived_(viewportPosition) {
     let originalUrl = this.originalUrl_;
     let hashIndex = originalUrl.search('#');
     if (hashIndex != -1) {
@@ -183,16 +163,16 @@
     } else {
       this.navigatorDelegate_.navigateInCurrentTab(viewportPosition.url);
     }
-  },
+  }
 
   /**
    * Checks if the URL starts with a scheme and is not just a scheme.
-   *
+   * TODO (rbpotter): Update to use URL (here and elsewhere in this file).
    * @param {string} url The input URL
    * @return {boolean} Whether the url is valid.
    * @private
    */
-  isValidUrl_: function(url) {
+  isValidUrl_(url) {
     // Make sure |url| starts with a valid scheme.
     if (!url.startsWith('http://') && !url.startsWith('https://') &&
         !url.startsWith('ftp://') && !url.startsWith('file://') &&
@@ -213,17 +193,16 @@
     }
 
     return true;
-  },
+  }
 
   /**
    * Attempt to figure out what a URL is when there is no scheme.
-   *
    * @param {string} url The input URL
    * @return {string} The URL with a scheme or the original URL if it is not
    *     possible to determine the scheme.
    * @private
    */
-  guessUrlWithoutScheme_: function(url) {
+  guessUrlWithoutScheme_(url) {
     // If the original URL is mailto:, that does not make sense to start with,
     // and neither does adding |url| to it.
     // If the original URL is not a valid URL, this cannot make a valid URL.
@@ -276,4 +255,18 @@
 
     return 'http://' + url;
   }
+}
+
+/**
+ * Represents options when navigating to a new url. C++ counterpart of
+ * the enum is in ui/base/window_open_disposition.h. This enum represents
+ * the only values that are passed from Plugin.
+ * @enum {number}
+ */
+PdfNavigator.WindowOpenDisposition = {
+  CURRENT_TAB: 1,
+  NEW_FOREGROUND_TAB: 3,
+  NEW_BACKGROUND_TAB: 4,
+  NEW_WINDOW: 6,
+  SAVE_TO_DISK: 7
 };
diff --git a/chrome/browser/resources/pdf/open_pdf_params_parser.js b/chrome/browser/resources/pdf/open_pdf_params_parser.js
index aacb7c4..d4a502a 100644
--- a/chrome/browser/resources/pdf/open_pdf_params_parser.js
+++ b/chrome/browser/resources/pdf/open_pdf_params_parser.js
@@ -2,15 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(function() {
-
 'use strict';
 
 /**
  * Parses the open pdf parameters passed in the url to set initial viewport
  * settings for opening the pdf.
  */
-window.OpenPDFParamsParser = class {
+class OpenPdfParamsParser {
   /**
    * @param {function(Object)} postMessageCallback
    *     Function called to fetch information for a named destination.
@@ -206,6 +204,4 @@
     }
     outstandingRequest.callback(outstandingRequest.params);
   }
-};
-
-}());
+}
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index a660cff5..375663f 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -151,7 +151,7 @@
   PDFMetrics.record(PDFMetrics.UserAction.DOCUMENT_OPENED);
 
   // Parse open pdf parameters.
-  this.paramsParser_ = new OpenPDFParamsParser(
+  this.paramsParser_ = new OpenPdfParamsParser(
       message => this.pluginController_.postMessage(message));
   const toolbarEnabled =
       this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar &&
@@ -293,8 +293,8 @@
 
   document.body.addEventListener('navigate', e => {
     const disposition = e.detail.newtab ?
-        Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
-        Navigator.WindowOpenDisposition.CURRENT_TAB;
+        PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB :
+        PdfNavigator.WindowOpenDisposition.CURRENT_TAB;
     this.navigator_.navigate(e.detail.uri, disposition);
   });
 
@@ -324,7 +324,7 @@
       'contextmenu', e => this.handleContextMenuEvent_(e));
 
   const tabId = this.browserApi_.getStreamInfo().tabId;
-  this.navigator_ = new Navigator(
+  this.navigator_ = new PdfNavigator(
       this.originalUrl_, this.viewport_, this.paramsParser_,
       new NavigatorDelegate(tabId));
   this.viewportScroller_ =
@@ -1143,7 +1143,8 @@
   handleNavigate: function(url, disposition) {
     // If in print preview, always open a new tab.
     if (this.isPrintPreview_) {
-      this.navigator_.navigate(url, Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
+      this.navigator_.navigate(
+          url, PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
     } else {
       this.navigator_.navigate(url, disposition);
     }
diff --git a/chrome/browser/resources/print_preview/polymer3/demo.js b/chrome/browser/resources/print_preview/polymer3/demo.js
index 208697c..dc49777 100644
--- a/chrome/browser/resources/print_preview/polymer3/demo.js
+++ b/chrome/browser/resources/print_preview/polymer3/demo.js
@@ -6,6 +6,7 @@
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
+import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.m.js';
 import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
 import 'chrome://resources/cr_elements/icons.m.js';
@@ -49,6 +50,9 @@
       </div>
 
       <iron-icon icon="cr:error"></iron-icon>
+
+      <cr-radio-button>one</cr-radio-button>
+      <cr-radio-button>two</cr-radio-button>
     `;
   }
 
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.html b/chrome/browser/resources/settings/crostini_page/crostini_page.html
index 1949eb2..d241d5ba 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_page.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_page.html
@@ -43,7 +43,7 @@
           <template is="dom-if" if="[[!prefs.crostini.enabled.value]]">
             <div class="separator"></div>
             <cr-button id="enable"
-                disabled="[[!allowCrostini]]"
+                disabled$="[[disableCrostiniInstall_]]"
                 on-click="onEnableTap_"
                 aria-label="$i18n{crostiniPageTitle}"
                 aria-describedby="secondaryText">
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.js b/chrome/browser/resources/settings/crostini_page/crostini_page.js
index 1f2b08a13e..7a74d5b 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_page.js
+++ b/chrome/browser/resources/settings/crostini_page/crostini_page.js
@@ -12,7 +12,7 @@
 Polymer({
   is: 'settings-crostini-page',
 
-  behaviors: [I18nBehavior, PrefsBehavior],
+  behaviors: [I18nBehavior, PrefsBehavior, WebUIListenerBehavior],
 
   properties: {
     /** Preferences state. */
@@ -49,6 +49,27 @@
         return map;
       },
     },
+
+    /**
+     * Whether the install option should be enabled.
+     * @private {boolean}
+     */
+    disableCrostiniInstall_: {
+      type: Boolean,
+    },
+  },
+
+  attached: function() {
+    if (!loadTimeData.getBoolean('allowCrostini')) {
+      this.disableCrostiniInstall_ = true;
+      return;
+    }
+    this.addWebUIListener(
+        'crostini-installer-status-changed', (installerShowing) => {
+          this.disableCrostiniInstall_ = installerShowing;
+        });
+    settings.CrostiniBrowserProxyImpl.getInstance()
+        .requestCrostiniInstallerStatus();
   },
 
   /**
diff --git a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
index dee64f7..56112da 100644
--- a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
+++ b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
@@ -97,6 +97,14 @@
      * @param {string} path The path to the parent cookie.
      */
     removeCookie(path) {}
+
+    /**
+     * Removes all SameSite=None cookies, as well as storage available in
+     * third-party contexts.
+     * Note: on-tree-item-removed will not be sent.
+     * @return {!Promise} To signal completion.
+     */
+    removeAllThirdPartyCookies() {}
   }
 
   /**
@@ -142,6 +150,11 @@
     removeCookie(path) {
       chrome.send('localData.removeCookie', [path]);
     }
+
+    /** @override */
+    removeAllThirdPartyCookies() {
+      return cr.sendWithPromise('localData.removeThirdPartyCookies');
+    }
   }
 
   // The singleton instance_ is replaced with a test version of this wrapper
diff --git a/chrome/browser/resources/settings/site_settings/site_data.html b/chrome/browser/resources/settings/site_settings/site_data.html
index b3c8d9b..9fc485d 100644
--- a/chrome/browser/resources/settings/site_settings/site_data.html
+++ b/chrome/browser/resources/settings/site_settings/site_data.html
@@ -42,6 +42,11 @@
           on-click="onRemoveShowingSitesTap_" hidden$="[[!sites.length]]">
         [[computeRemoveLabel_(filter)]]
       </cr-button>
+      <cr-button disabled$="[[isLoading_]]" id="removeThirdPartyCookies"
+          on-click="onRemoveThirdPartyCookiesTap_"
+          hidden$="[[!enableRemovingAllThirdPartyCookies_]]">
+          $i18n{siteSettingsCookieRemoveAllThirdParty}
+      </cr-button>
     </div>
     <iron-list id="list" items="[[sites]]" preserve-focus
         scroll-target="[[subpageScrollTarget]]" class="cr-separators">
@@ -71,6 +76,26 @@
         </cr-button>
       </div>
     </cr-dialog>
+
+    <!-- Confirm Delete Third Party Cookies dialog -->
+    <cr-dialog id="confirmDeleteThirdPartyDialog" close-text="$i18n{close}"
+        on-close="onConfirmDeleteThirdPartyDialogClosed_">
+      <div slot="title">
+        $i18n{siteSettingsCookieRemoveThirdPartyDialogTitle}
+      </div>
+      <div slot="body">
+        $i18n{siteSettingsCookieRemoveThirdPartyConfirmation}
+      </div>
+      <div slot="button-container">
+        <cr-button class="cancel-button" on-click="onCloseThirdPartyDialog_">
+          $i18n{cancel}
+        </cr-button>
+        <cr-button class="action-button" on-click="onConfirmThirdPartyDelete_">
+          $i18n{siteSettingsCookiesClearThirdParty}
+        </cr-button>
+      </div>
+    </cr-dialog>
+
   </template>
   <script src="site_data.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/site_data.js b/chrome/browser/resources/settings/site_settings/site_data.js
index 06c8e74..644aedc4 100644
--- a/chrome/browser/resources/settings/site_settings/site_data.js
+++ b/chrome/browser/resources/settings/site_settings/site_data.js
@@ -75,6 +75,15 @@
 
     /** @private */
     listBlurred_: Boolean,
+
+    /** @private */
+    enableRemovingAllThirdPartyCookies_: {
+      type: Boolean,
+      value: function() {
+        return loadTimeData.getBoolean('enableRemovingAllThirdPartyCookies') &&
+            (this.sites.length > 0);
+      }
+    },
   },
 
   /** @private {settings.LocalDataBrowserProxy} */
@@ -201,10 +210,20 @@
   },
 
   /** @private */
+  onCloseThirdPartyDialog_: function() {
+    this.$.confirmDeleteThirdPartyDialog.close();
+  },
+
+  /** @private */
   onConfirmDeleteDialogClosed_: function() {
     cr.ui.focusWithoutInk(assert(this.$.removeShowingSites));
   },
 
+  /** @private */
+  onConfirmDeleteThirdPartyDialogClosed_: function() {
+    cr.ui.focusWithoutInk(assert(this.$.removeAllThirdPartyCookies));
+  },
+
   /**
    * Shows a dialog to confirm the deletion of multiple sites.
    * @param {!Event} e
@@ -216,6 +235,16 @@
   },
 
   /**
+   * Shows a dialog to confirm the deletion of cookies available
+   * in third-party contexts and associated site data.
+   * @private
+   */
+  onRemoveThirdPartyCookiesTap_: function(e) {
+    e.preventDefault();
+    this.$.confirmDeleteThirdPartyDialog.showModal();
+  },
+
+  /**
    * Called when deletion for all showing sites has been confirmed.
    * @private
    */
@@ -233,6 +262,18 @@
   },
 
   /**
+   * Called when deletion of all third-party cookies and site data has been
+   * confirmed.
+   * @private
+   */
+  onConfirmThirdPartyDelete_: function() {
+    this.$.confirmDeleteThirdPartyDialog.close();
+    this.browserProxy_.removeAllThirdPartyCookies().then(() => {
+      this.updateSiteList_();
+    });
+  },
+
+  /**
    * @param {!{model: !{item: CookieDataSummaryItem, index: number}}} event
    * @private
    */
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 1916295a..5bc8ce9 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -1354,9 +1354,10 @@
     return std::string();
   }
 
-  std::string email = password_type.is_account_syncing()
-                          ? GetAccountInfo().email
-                          : GetSignedInNonSyncAccount(username()).email;
+  std::string email =
+      password_type.is_account_syncing()
+          ? GetAccountInfo().email
+          : GetSignedInNonSyncAccount(username_for_last_shown_warning()).email;
   return email.empty() ? std::string() : gaia::ExtractDomainName(email);
 }
 
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
index 16908a8c..1cabbe4 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_browsertest.cc
@@ -551,6 +551,8 @@
 
   ReusedPasswordAccountType account_type;
   account_type.set_account_type(ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
+  service->set_reused_password_account_type_for_last_shown_warning(
+      account_type);
 
   base::HistogramTester histograms;
   // Shows interstitial on current web_contents.
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_sync_browsertest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_sync_browsertest.cc
index b73dcac..f88c5f0 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_sync_browsertest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_sync_browsertest.cc
@@ -146,6 +146,8 @@
   reused_password_account_type.set_account_type(
       safe_browsing::ReusedPasswordAccountType::GSUITE);
   reused_password_account_type.set_is_account_syncing(true);
+  service->set_reused_password_account_type_for_last_shown_warning(
+      reused_password_account_type);
   service->ShowInterstitial(web_contents, reused_password_account_type);
   content::WebContents* interstitial_web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index f23b8b6..c04aa723 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -56,6 +56,7 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "ui/gfx/color_analysis.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 
 namespace {
@@ -411,6 +412,7 @@
 
 void InstantService::UpdateThemeInfo() {
   ApplyOrResetCustomBackgroundThemeInfo();
+  SetNtpElementsThemeInfo();
 
   NotifyAboutThemeInfo();
 }
@@ -665,20 +667,13 @@
   // Get theme colors.
   const ui::ThemeProvider& theme_provider =
       ThemeService::GetThemeProviderForProfile(profile_);
-  SkColor background_color =
-      theme_provider.GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
-  SkColor text_color = theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT);
-  SkColor text_color_light =
-      theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT_LIGHT);
 
   // Set colors.
-  theme_info_->background_color = background_color;
-  theme_info_->text_color = text_color;
-  theme_info_->text_color_light = text_color_light;
-
-  int logo_alternate =
-      theme_provider.GetDisplayProperty(ThemeProperties::NTP_LOGO_ALTERNATE);
-  theme_info_->logo_alternate = logo_alternate == 1;
+  theme_info_->background_color =
+      theme_provider.GetColor(ThemeProperties::COLOR_NTP_BACKGROUND);
+  theme_info_->text_color_light =
+      theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT_LIGHT);
+  SetNtpElementsThemeInfo();
 
   if (theme_service->UsingExtensionTheme()) {
     const extensions::Extension* extension =
@@ -1015,3 +1010,33 @@
 void InstantService::SetClockForTesting(base::Clock* clock) {
   clock_ = clock;
 }
+
+void InstantService::SetNtpElementsThemeInfo() {
+  ThemeBackgroundInfo* theme_info = GetInitializedThemeInfo();
+  if (IsCustomBackgroundSet()) {
+    theme_info->text_color = gfx::kGoogleGrey050;
+    theme_info->logo_alternate = true;
+    theme_info->logo_color = ThemeProperties::GetDefaultColor(
+        ThemeProperties::COLOR_NTP_LOGO, false);
+    theme_info->shortcut_color = ThemeProperties::GetDefaultColor(
+        ThemeProperties::COLOR_NTP_SHORTCUT, false);
+  } else {
+    const ui::ThemeProvider& theme_provider =
+        ThemeService::GetThemeProviderForProfile(profile_);
+    theme_info->text_color =
+        theme_provider.GetColor(ThemeProperties::COLOR_NTP_TEXT);
+    theme_info->logo_alternate = theme_provider.GetDisplayProperty(
+                                     ThemeProperties::NTP_LOGO_ALTERNATE) == 1;
+    theme_info->logo_color =
+        theme_provider.GetColor(ThemeProperties::COLOR_NTP_LOGO);
+
+    // For default theme in dark mode use dark shortcuts.
+    if (native_theme_->ShouldUseDarkColors() &&
+        ThemeServiceFactory::GetForProfile(profile_)->UsingDefaultTheme()) {
+      theme_info->shortcut_color = gfx::kGoogleGrey900;
+    } else {
+      theme_info->shortcut_color =
+          theme_provider.GetColor(ThemeProperties::COLOR_NTP_SHORTCUT);
+    }
+  }
+}
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h
index 64f80b0df..8bbfbf6 100644
--- a/chrome/browser/search/instant_service.h
+++ b/chrome/browser/search/instant_service.h
@@ -282,6 +282,10 @@
   // Requests a new background image if it hasn't been updated in >24 hours.
   void RefreshBackgroundIfNeeded();
 
+  // Sets NTP elements theme info that are overridden when custom
+  // background is used.
+  void SetNtpElementsThemeInfo();
+
   Profile* const profile_;
 
   // The process ids associated with Instant processes.
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc
index 13e14062..d818ac3 100644
--- a/chrome/browser/search/instant_service_unittest.cc
+++ b/chrome/browser/search/instant_service_unittest.cc
@@ -10,10 +10,14 @@
 #include "base/path_service.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/search/background/ntp_background_service.h"
 #include "chrome/browser/search/instant_service_observer.h"
 #include "chrome/browser/search/instant_unittest_base.h"
 #include "chrome/browser/search/ntp_features.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/search/instant_types.h"
@@ -22,6 +26,7 @@
 #include "components/ntp_tiles/ntp_tile.h"
 #include "components/ntp_tiles/section_type.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/native_theme/test_native_theme.h"
@@ -772,3 +777,49 @@
   EXPECT_EQ(kImageUrl2, theme_info->custom_background_url);
   EXPECT_TRUE(instant_service_->IsCustomBackgroundSet());
 }
+
+TEST_F(InstantServiceTest, SetNTPElementsThemeInfo) {
+  ThemeBackgroundInfo* theme_info = instant_service_->GetInitializedThemeInfo();
+  SkColor default_text_color =
+      ThemeProperties::GetDefaultColor(ThemeProperties::COLOR_NTP_TEXT, false);
+  SkColor default_logo_color =
+      ThemeProperties::GetDefaultColor(ThemeProperties::COLOR_NTP_LOGO, false);
+  SkColor default_shortcut_color = ThemeProperties::GetDefaultColor(
+      ThemeProperties::COLOR_NTP_SHORTCUT, false);
+
+  ASSERT_FALSE(instant_service_->IsCustomBackgroundSet());
+
+  // Check defaults when no theme and no custom backgrounds is set.
+  EXPECT_EQ(default_text_color, theme_info->text_color);
+  EXPECT_FALSE(theme_info->logo_alternate);
+  EXPECT_EQ(default_logo_color, theme_info->logo_color);
+  EXPECT_EQ(default_shortcut_color, theme_info->shortcut_color);
+
+  // Install colors, theme update should trigger |SetNTPElementsThemeInfo| and
+  // update NTP themed elements info.
+  ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile());
+  content::WindowedNotificationObserver theme_change_observer(
+      chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+      content::Source<ThemeService>(theme_service));
+  theme_service->BuildFromColor(SK_ColorRED);
+  theme_change_observer.Wait();
+
+  theme_info = instant_service_->GetInitializedThemeInfo();
+  EXPECT_NE(default_text_color, theme_info->text_color);
+  EXPECT_TRUE(theme_info->logo_alternate);
+  EXPECT_NE(default_logo_color, theme_info->logo_color);
+  EXPECT_NE(default_shortcut_color, theme_info->shortcut_color);
+
+  // Setting a custom backgrounds should call |SetNTPElementsThemeInfo| and
+  // update NTP themed elements info.
+  const GURL kUrl("https://www.foo.com");
+  instant_service_->AddValidBackdropUrlForTesting(kUrl);
+  instant_service_->SetCustomBackgroundInfo(kUrl, "", "", GURL(), "");
+  ASSERT_TRUE(instant_service_->IsCustomBackgroundSet());
+
+  theme_info = instant_service_->GetInitializedThemeInfo();
+  EXPECT_NE(default_text_color, theme_info->text_color);
+  EXPECT_TRUE(theme_info->logo_alternate);
+  EXPECT_EQ(default_logo_color, theme_info->logo_color);
+  EXPECT_EQ(default_shortcut_color, theme_info->shortcut_color);
+}
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc
index 096bf86..118b4ba 100644
--- a/chrome/browser/search/ntp_features.cc
+++ b/chrome/browser/search/ntp_features.cc
@@ -6,6 +6,7 @@
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "ui/base/ui_base_features.h"
 
 namespace features {
@@ -42,14 +43,9 @@
 const base::Feature kNtpRealbox{"NtpRealbox",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
-// If enabled, forces IsNtpRealboxEnabled() to return true and shows suggestions
-// in the NTP "realbox" without any input (i.e. on focus).
-extern const base::Feature kNtpZeroSuggest{"NtpZeroSuggest",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
-
 bool IsNtpRealboxEnabled() {
   return base::FeatureList::IsEnabled(kNtpRealbox) ||
-         base::FeatureList::IsEnabled(kNtpZeroSuggest);
+         base::FeatureList::IsEnabled(omnibox::kZeroSuggestionsOnNTP);
 }
 
 }  // namespace features
diff --git a/chrome/browser/search/ntp_features.h b/chrome/browser/search/ntp_features.h
index ae098ff..bcb3dc14 100644
--- a/chrome/browser/search/ntp_features.h
+++ b/chrome/browser/search/ntp_features.h
@@ -22,8 +22,9 @@
 
 // Note: only exposed for about:flags. Use IsNtpRealboxEnabled() instead.
 extern const base::Feature kNtpRealbox;
-extern const base::Feature kNtpZeroSuggest;
 
+// Returns true if either kNtpRealbox or omnibox::kZeroSuggestionsOnNTP are
+// enabled.
 bool IsNtpRealboxEnabled();
 
 }  // namespace features
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 28fa932a..439b653f 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -564,8 +564,41 @@
   DISALLOW_COPY_AND_ASSIGN(ControlButtonBackgroundImageSource);
 };
 
+// Returns whether the color is grayscale.
+bool IsColorGrayscale(SkColor color) {
+  constexpr int kChannelTolerance = 9;
+  auto channels = {SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)};
+  const int range = std::max(channels) - std::min(channels);
+  return range < kChannelTolerance;
+}
+
 }  // namespace
 
+namespace internal {  // for testing
+
+// Calculate contrasting color for given |bg_color|. Returns lighter color if
+// the color is very dark and returns darker color otherwise.
+SkColor GetContrastingColorForBackground(SkColor bg_color,
+                                         float luminosity_change) {
+  color_utils::HSL hsl;
+  SkColorToHSL(bg_color, &hsl);
+
+  // If luminosity is 0, it means |bg_color| is black. Use white for black
+  // backgrounds.
+  if (hsl.l == 0)
+    return SK_ColorWHITE;
+
+  // Decrease luminosity, unless color is already dark.
+  if (hsl.l > 0.15)
+    luminosity_change *= -1;
+
+  hsl.l *= 1 + luminosity_change;
+  if (hsl.l >= 0.0f && hsl.l <= 1.0f)
+    return HSLToSkColor(hsl, 255);
+  return bg_color;
+}
+}  // namespace internal
+
 BrowserThemePack::~BrowserThemePack() {
   if (!data_pack_.get()) {
     delete header_;
@@ -1677,18 +1710,53 @@
 }
 
 void BrowserThemePack::GenerateMissingNtpColors() {
-  // Calculate NTP text color based on NTP background.
-  SkColor ntp_background_color;
   gfx::Image image = GetImageNamed(IDR_THEME_NTP_BACKGROUND);
-  if (!image.IsEmpty()) {
-    ntp_background_color = ComputeImageColor(image, image.Height());
-    SetColorIfUnspecified(
-        TP::COLOR_NTP_TEXT,
-        color_utils::GetColorWithMaxContrast(ntp_background_color));
-  } else if (GetColor(TP::COLOR_NTP_BACKGROUND, &ntp_background_color)) {
-    SetColorIfUnspecified(
-        TP::COLOR_NTP_TEXT,
-        color_utils::GetColorWithMaxContrast(ntp_background_color));
+  bool has_background_image = !image.IsEmpty();
+
+  SkColor background_color;
+  bool has_background_color =
+      GetColor(TP::COLOR_NTP_BACKGROUND, &background_color);
+
+  // Calculate NTP text color based on NTP background.
+  SkColor text_color;
+  if (!GetColor(TP::COLOR_NTP_TEXT, &text_color)) {
+    if (has_background_image)
+      has_background_color = ComputeImageColor(image, image.Height());
+
+    if (has_background_image || has_background_color) {
+      SetColor(TP::COLOR_NTP_TEXT,
+               color_utils::GetColorWithMaxContrast(background_color));
+    }
+  }
+
+  // Calculate logo alternate, if not specified.
+  int logo_alternate = 0;
+  if (!GetDisplayProperty(TP::NTP_LOGO_ALTERNATE, &logo_alternate)) {
+    logo_alternate =
+        has_background_image ||
+        (has_background_color && !IsColorGrayscale(background_color));
+    SetDisplayProperty(TP::NTP_LOGO_ALTERNATE, logo_alternate);
+  }
+
+  // For themes that use alternate logo and no NTP background image is present,
+  // set logo color in the same hue as NTP background.
+  if (logo_alternate == 1 && !has_background_image && has_background_color) {
+    SkColor logo_color = color_utils::IsDark(background_color)
+                             ? SK_ColorWHITE
+                             : internal::GetContrastingColorForBackground(
+                                   background_color,
+                                   /*luminosity_change=*/0.3f);
+    SetColor(TP::COLOR_NTP_LOGO, logo_color);
+  }
+
+  // Calculate NTP shortcut color.
+  // Use light color for NTPs with images, and themed color for NTPs with solid
+  // color.
+  if (!has_background_image && has_background_color &&
+      background_color != SK_ColorWHITE) {
+    SetColor(TP::COLOR_NTP_SHORTCUT, internal::GetContrastingColorForBackground(
+                                         background_color,
+                                         /*luminosity_change=*/0.2f));
   }
 }
 
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index 7e326042..8fcf98f2 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -228,7 +228,7 @@
   ASSERT_TRUE(valid_value.get());
   scoped_refptr<Extension> extension(
       Extension::Create(extension_path, extensions::Manifest::INVALID_LOCATION,
-                        *valid_value, Extension::REQUIRE_KEY, &error));
+                        *valid_value, Extension::NO_FLAGS, &error));
   ASSERT_TRUE(extension.get());
   ASSERT_EQ("", error);
   BrowserThemePack::BuildFromExtension(extension.get(), pack);
@@ -1113,3 +1113,91 @@
 
   EXPECT_TRUE(pack_autogenerated->GetColor(TP::COLOR_NTP_TEXT, &ntp_text));
 }
+
+TEST_F(BrowserThemePackTest, TestLogoAndShortcutColors) {
+  // For themes with no background image and no background color, nothing should
+  // be specified.
+  scoped_refptr<BrowserThemePack> theme_minimal(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
+  BuildTestExtensionTheme("theme_minimal", theme_minimal.get());
+  SkColor color;
+  EXPECT_FALSE(theme_minimal->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_FALSE(theme_minimal->GetColor(TP::COLOR_NTP_SHORTCUT, &color));
+
+  // For themes with image logo and shortcut colors shouldn't be set.
+  scoped_refptr<BrowserThemePack> theme_with_image(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
+  BuildTestExtensionTheme("theme_ntp_background_image", theme_with_image.get());
+  EXPECT_FALSE(theme_with_image->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_FALSE(theme_with_image->GetColor(TP::COLOR_NTP_SHORTCUT, &color));
+
+  // // For themes with no image but with colorful logo, the logo color
+  // shouldn't
+  // // be specified but the shortcut color should be set.
+  scoped_refptr<BrowserThemePack> theme_colorful_logo(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
+  BuildTestExtensionTheme("theme_color_ntp_colorful_logo",
+                          theme_colorful_logo.get());
+  EXPECT_FALSE(theme_colorful_logo->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_TRUE(theme_colorful_logo->GetColor(TP::COLOR_NTP_SHORTCUT, &color));
+
+  // For themes with no image and with alternate logo, both logo and shortcut
+  // colors should be set.
+  scoped_refptr<BrowserThemePack> theme_alternate_logo(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::EXTENSION));
+  BuildTestExtensionTheme("theme_color_ntp_white_logo",
+                          theme_alternate_logo.get());
+  EXPECT_TRUE(theme_alternate_logo->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_NE(SK_ColorWHITE, color);
+  EXPECT_TRUE(theme_alternate_logo->GetColor(TP::COLOR_NTP_SHORTCUT, &color));
+
+  // For darker then midpoint themes the logo color should be white.
+  scoped_refptr<BrowserThemePack> dark_theme(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::AUTOGENERATED));
+  BrowserThemePack::BuildFromColor(SkColorSetRGB(120, 120, 120),
+                                   dark_theme.get());
+  EXPECT_TRUE(dark_theme->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_EQ(SK_ColorWHITE, color);
+
+  // For themes with white NTP background the shortcut color shouldn't be set.
+  // The Logo color shouldn't be set either because the colorful logo should be
+  // used on white background.
+  scoped_refptr<BrowserThemePack> white_theme(
+      new BrowserThemePack(CustomThemeSupplier::ThemeType::AUTOGENERATED));
+  BrowserThemePack::BuildFromColor(SK_ColorWHITE, white_theme.get());
+  ASSERT_TRUE(white_theme->GetColor(TP::COLOR_NTP_BACKGROUND, &color));
+  ASSERT_EQ(SK_ColorWHITE, color);
+  EXPECT_FALSE(white_theme->GetColor(TP::COLOR_NTP_LOGO, &color));
+  EXPECT_FALSE(white_theme->GetColor(TP::COLOR_NTP_SHORTCUT, &color));
+}
+
+namespace internal {
+
+// Defined in browser_theme_pack.cc
+SkColor GetContrastingColorForBackground(SkColor bg_color, float change);
+
+TEST(BrowserThemePackInternalTest, TestGetContrastingColor) {
+  const float change = 0.2f;
+
+  // White color for black background.
+  EXPECT_EQ(SK_ColorWHITE,
+            GetContrastingColorForBackground(SK_ColorBLACK, change));
+
+  // Lighter color for too dark colors.
+  SkColor dark_background = SkColorSetARGB(255, 50, 0, 50);
+  EXPECT_LT(color_utils::GetRelativeLuminance(dark_background),
+            color_utils::GetRelativeLuminance(
+                GetContrastingColorForBackground(dark_background, change)));
+
+  // Darker color for light backgrounds.
+  EXPECT_GT(color_utils::GetRelativeLuminance(SK_ColorWHITE),
+            color_utils::GetRelativeLuminance(
+                GetContrastingColorForBackground(SK_ColorWHITE, change)));
+
+  SkColor light_background = SkColorSetARGB(255, 100, 0, 100);
+  EXPECT_GT(color_utils::GetRelativeLuminance(light_background),
+            color_utils::GetRelativeLuminance(
+                GetContrastingColorForBackground(light_background, change)));
+}
+
+}  // namespace internal
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 176776e7..507b5ce2 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -90,6 +90,10 @@
       // TINT_BUTTONS.
       NOTREACHED();
       return gfx::kPlaceholderColor;
+    case ThemeProperties::COLOR_NTP_LOGO:
+      return SkColorSetRGB(0xEE, 0xEE, 0xEE);
+    case ThemeProperties::COLOR_NTP_SHORTCUT:
+      return gfx::kGoogleGrey100;
 
     // Properties not stored in theme pack.
     case ThemeProperties::COLOR_TAB_ALERT_AUDIO:
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 18e69af..0791806 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -140,6 +140,9 @@
     // These colors don't have constant default values. They are derived from
     // the runtime value of other colors.
     COLOR_NTP_TEXT_LIGHT,
+    COLOR_NTP_LOGO,
+    // Color for the background of the most visited/custom link tile.
+    COLOR_NTP_SHORTCUT,
 
 #if defined(OS_WIN)
     // The color of the 1px border around the window on Windows 10.
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 4de56554..9cd514f 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -123,17 +123,6 @@
   }
 }
 
-// Heuristic to determine if color is grayscale. This is used to decide whether
-// to use the colorful or white logo, if a theme fails to specify which.
-bool IsColorGrayscale(SkColor color) {
-  const int kChannelTolerance = 9;
-  int r = SkColorGetR(color);
-  int g = SkColorGetG(color);
-  int b = SkColorGetB(color);
-  int range = std::max(r, std::max(g, b)) - std::min(r, std::min(g, b));
-  return range < kChannelTolerance;
-}
-
 }  // namespace
 
 
@@ -872,14 +861,8 @@
     case ThemeProperties::NTP_BACKGROUND_TILING:
       return ThemeProperties::NO_REPEAT;
 
-    case ThemeProperties::NTP_LOGO_ALTERNATE: {
-      if (UsingDefaultTheme() || UsingSystemTheme())
-        return 0;
-      if (HasCustomImage(IDR_THEME_NTP_BACKGROUND))
-        return 1;
-      return IsColorGrayscale(
-          GetColor(ThemeProperties::COLOR_NTP_BACKGROUND, false)) ? 0 : 1;
-    }
+    case ThemeProperties::NTP_LOGO_ALTERNATE:
+      return 0;
 
     case ThemeProperties::SHOULD_FILL_BACKGROUND_TAB_COLOR:
       return 1;
diff --git a/chrome/browser/ui/android/sms/sms_infobar.cc b/chrome/browser/ui/android/sms/sms_infobar.cc
index 561ebb7..74e75f02a 100644
--- a/chrome/browser/ui/android/sms/sms_infobar.cc
+++ b/chrome/browser/ui/android/sms/sms_infobar.cc
@@ -19,10 +19,11 @@
 // static
 void SmsInfoBar::Create(content::WebContents* web_contents,
                         const url::Origin& origin,
+                        const std::string& one_time_code,
                         base::OnceClosure on_confirm,
                         base::OnceClosure on_cancel) {
   auto delegate = std::make_unique<SmsInfoBarDelegate>(
-      origin, std::move(on_confirm), std::move(on_cancel));
+      origin, one_time_code, std::move(on_confirm), std::move(on_cancel));
   auto infobar =
       std::make_unique<SmsInfoBar>(web_contents, std::move(delegate));
   auto* infobar_service = InfoBarService::FromWebContents(web_contents);
diff --git a/chrome/browser/ui/android/sms/sms_infobar.h b/chrome/browser/ui/android/sms/sms_infobar.h
index f18f73b3..2fe8950 100644
--- a/chrome/browser/ui/android/sms/sms_infobar.h
+++ b/chrome/browser/ui/android/sms/sms_infobar.h
@@ -30,6 +30,7 @@
   // |infobar_service|.
   static void Create(content::WebContents* web_contents,
                      const url::Origin& origin,
+                     const std::string& one_time_code,
                      base::OnceCallback<void()> on_confirm,
                      base::OnceCallback<void()> on_cancel);
 
diff --git a/chrome/browser/ui/android/sms/sms_infobar_delegate.cc b/chrome/browser/ui/android/sms/sms_infobar_delegate.cc
index c8b4f64..85fb392f 100644
--- a/chrome/browser/ui/android/sms/sms_infobar_delegate.cc
+++ b/chrome/browser/ui/android/sms/sms_infobar_delegate.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/android/sms/sms_infobar_delegate.h"
 
 #include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/android/android_theme_resources.h"
@@ -16,10 +17,12 @@
 #include "url/origin.h"
 
 SmsInfoBarDelegate::SmsInfoBarDelegate(const url::Origin& origin,
+                                       const std::string& one_time_code,
                                        base::OnceClosure on_confirm,
                                        base::OnceClosure on_cancel)
     : ConfirmInfoBarDelegate(),
       origin_(origin),
+      one_time_code_(one_time_code),
       on_confirm_(std::move(on_confirm)),
       on_cancel_(std::move(on_cancel)) {}
 
@@ -38,7 +41,7 @@
   base::string16 origin = url_formatter::FormatOriginForSecurityDisplay(
       origin_, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
   return l10n_util::GetStringFUTF16(IDS_SMS_INFOBAR_STATUS_SMS_RECEIVED,
-                                    origin);
+                                    base::UTF8ToUTF16(one_time_code_), origin);
 }
 
 int SmsInfoBarDelegate::GetButtons() const {
diff --git a/chrome/browser/ui/android/sms/sms_infobar_delegate.h b/chrome/browser/ui/android/sms/sms_infobar_delegate.h
index 15c22f4b..61ee2c4a 100644
--- a/chrome/browser/ui/android/sms/sms_infobar_delegate.h
+++ b/chrome/browser/ui/android/sms/sms_infobar_delegate.h
@@ -16,6 +16,7 @@
 class SmsInfoBarDelegate : public ConfirmInfoBarDelegate {
  public:
   SmsInfoBarDelegate(const url::Origin& origin,
+                     const std::string& one_time_code,
                      base::OnceClosure on_confirm,
                      base::OnceClosure on_cancel);
   ~SmsInfoBarDelegate() override;
@@ -33,6 +34,7 @@
 
  private:
   const url::Origin origin_;
+  const std::string one_time_code_;
   base::OnceClosure on_confirm_;
   base::OnceClosure on_cancel_;
   DISALLOW_COPY_AND_ASSIGN(SmsInfoBarDelegate);
diff --git a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.cc b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.cc
index 5c87f93..52f425c9 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.cc
+++ b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller.cc
@@ -50,8 +50,9 @@
 
 const gfx::VectorIcon& WebauthnOfferDialogController::GetStepIllustration(
     ImageColorScheme color_scheme) const {
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
-                                                 : kWebauthnPermissionIcon;
+  return color_scheme == ImageColorScheme::kDark
+             ? kWebauthnOfferDialogHeaderDarkIcon
+             : kWebauthnOfferDialogHeaderIcon;
 }
 
 base::string16 WebauthnOfferDialogController::GetStepTitle() const {
diff --git a/chrome/browser/ui/page_info/page_info.cc b/chrome/browser/ui/page_info/page_info.cc
index cb2368f..f39033a 100644
--- a/chrome/browser/ui/page_info/page_info.cc
+++ b/chrome/browser/ui/page_info/page_info.cc
@@ -311,23 +311,6 @@
 #endif
 };
 
-#if BUILDFLAG(FULL_SAFE_BROWSING)
-PasswordType GetPasswordTypeFromSafeBrowsingStatus(
-    const PageInfo::SafeBrowsingStatus& safe_browsing_status) {
-  switch (safe_browsing_status) {
-    case PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE:
-      return PasswordType::PRIMARY_ACCOUNT_PASSWORD;
-    case PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
-      return PasswordType::OTHER_GAIA_PASSWORD;
-    case PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE:
-      return PasswordType::ENTERPRISE_PASSWORD;
-    default:
-      NOTREACHED();
-      return PasswordType::PASSWORD_TYPE_UNKNOWN;
-  }
-}
-#endif
-
 // Time open histogram prefixes.
 const char kPageInfoTimePrefix[] = "Security.PageInfo.TimeOpen";
 const char kPageInfoTimeActionPrefix[] = "Security.PageInfo.TimeOpen.Action";
@@ -595,9 +578,7 @@
   password_protection_service_->OnUserAction(
       web_contents,
       password_protection_service_
-          ->GetPasswordProtectionReusedPasswordAccountType(
-              GetPasswordTypeFromSafeBrowsingStatus(safe_browsing_status_),
-              password_protection_service_->username()),
+          ->reused_password_account_type_for_last_shown_warning(),
       RequestOutcome::UNKNOWN,
       LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
       /*verdict_token=*/"", safe_browsing::WarningUIType::PAGE_INFO,
@@ -619,9 +600,7 @@
   password_protection_service_->OnUserAction(
       web_contents,
       password_protection_service_
-          ->GetPasswordProtectionReusedPasswordAccountType(
-              GetPasswordTypeFromSafeBrowsingStatus(safe_browsing_status_),
-              password_protection_service_->username()),
+          ->reused_password_account_type_for_last_shown_warning(),
       RequestOutcome::UNKNOWN,
       LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
       /*verdict_token=*/"", safe_browsing::WarningUIType::PAGE_INFO,
@@ -1041,14 +1020,11 @@
   if (!password_protection_service_) {
     return;
   }
-  PasswordType password_type =
-      GetPasswordTypeFromSafeBrowsingStatus(safe_browsing_status_);
   safe_browsing::LogWarningAction(
       safe_browsing::WarningUIType::PAGE_INFO,
       safe_browsing::WarningAction::SHOWN,
       password_protection_service_
-          ->GetPasswordProtectionReusedPasswordAccountType(
-              password_type, password_protection_service_->username()));
+          ->reused_password_account_type_for_last_shown_warning());
 }
 #endif
 
@@ -1090,13 +1066,12 @@
 #if BUILDFLAG(FULL_SAFE_BROWSING)
       *status = PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE;
       // |password_protection_service_| may be null in test.
-      *details = password_protection_service_
-                     ? password_protection_service_->GetWarningDetailText(
-                           password_protection_service_
-                               ->GetPasswordProtectionReusedPasswordAccountType(
-                                   PasswordType::PRIMARY_ACCOUNT_PASSWORD,
-                                   password_protection_service_->username()))
-                     : base::string16();
+      *details =
+          password_protection_service_
+              ? password_protection_service_->GetWarningDetailText(
+                    password_protection_service_
+                        ->reused_password_account_type_for_last_shown_warning())
+              : base::string16();
 #endif
       break;
     case security_state::
@@ -1105,26 +1080,24 @@
       *status =
           PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE;
       // |password_protection_service_| may be null in test.
-      *details = password_protection_service_
-                     ? password_protection_service_->GetWarningDetailText(
-                           password_protection_service_
-                               ->GetPasswordProtectionReusedPasswordAccountType(
-                                   PasswordType::OTHER_GAIA_PASSWORD,
-                                   password_protection_service_->username()))
-                     : base::string16();
+      *details =
+          password_protection_service_
+              ? password_protection_service_->GetWarningDetailText(
+                    password_protection_service_
+                        ->reused_password_account_type_for_last_shown_warning())
+              : base::string16();
 #endif
       break;
     case security_state::MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE:
 #if BUILDFLAG(FULL_SAFE_BROWSING)
       *status = PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE;
       // |password_protection_service_| maybe null in test.
-      *details = password_protection_service_
-                     ? password_protection_service_->GetWarningDetailText(
-                           password_protection_service_
-                               ->GetPasswordProtectionReusedPasswordAccountType(
-                                   PasswordType::ENTERPRISE_PASSWORD,
-                                   password_protection_service_->username()))
-                     : base::string16();
+      *details =
+          password_protection_service_
+              ? password_protection_service_->GetWarningDetailText(
+                    password_protection_service_
+                        ->reused_password_account_type_for_last_shown_warning())
+              : base::string16();
 #endif
       break;
     case security_state::MALICIOUS_CONTENT_STATUS_BILLING:
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/chrome/browser/ui/page_info/page_info_ui.cc
index 8d44ceb..8dca140 100644
--- a/chrome/browser/ui/page_info/page_info_ui.cc
+++ b/chrome/browser/ui/page_info/page_info_ui.cc
@@ -266,22 +266,10 @@
                                        IDS_PAGE_INFO_UNWANTED_SOFTWARE_SUMMARY,
                                        IDS_PAGE_INFO_UNWANTED_SOFTWARE_DETAILS);
     case PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE:
-#if BUILDFLAG(FULL_SAFE_BROWSING)
-      return CreateSecurityDescriptionForPasswordReuse(PasswordType::SYNC_GAIA);
-#endif
-      NOTREACHED();
-      break;
     case PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
-#if BUILDFLAG(FULL_SAFE_BROWSING)
-      return CreateSecurityDescriptionForPasswordReuse(
-          PasswordType::NON_SYNC_GAIA);
-#endif
-      NOTREACHED();
-      break;
     case PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE:
 #if BUILDFLAG(FULL_SAFE_BROWSING)
-      return CreateSecurityDescriptionForPasswordReuse(
-          PasswordType::NON_GAIA_ENTERPRISE);
+      return CreateSecurityDescriptionForPasswordReuse();
 #endif
       NOTREACHED();
       break;
diff --git a/chrome/browser/ui/page_info/page_info_ui.h b/chrome/browser/ui/page_info/page_info_ui.h
index fb402975..c80a7a9 100644
--- a/chrome/browser/ui/page_info/page_info_ui.h
+++ b/chrome/browser/ui/page_info/page_info_ui.h
@@ -54,18 +54,6 @@
     base::string16 details;
   };
 
-  // This enum is used to create the description in the page info bubble when
-  // password reuse is detected.
-  enum PasswordType {
-    UNKNOWN,
-    // If the reused password is associated with a non-GAIA enterprise account.
-    NON_GAIA_ENTERPRISE,
-    // If the reused password is associated with a syncing GAIA account.
-    SYNC_GAIA,
-    // If the reused password is associated with a non-syncing GAIA account.
-    NON_SYNC_GAIA,
-  };
-
   // |CookieInfo| contains information about the cookies from a specific source.
   // A source can for example be a specific origin or an entire wildcard domain.
   struct CookieInfo {
@@ -244,8 +232,7 @@
 #if BUILDFLAG(FULL_SAFE_BROWSING)
   // Creates security description for password reuse case.
   virtual std::unique_ptr<PageInfoUI::SecurityDescription>
-  CreateSecurityDescriptionForPasswordReuse(
-      PasswordType password_type) const = 0;
+  CreateSecurityDescriptionForPasswordReuse() const = 0;
 #endif
 };
 
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index efce4e773..de10efc2 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -106,8 +106,7 @@
 
 #if BUILDFLAG(FULL_SAFE_BROWSING)
   std::unique_ptr<PageInfoUI::SecurityDescription>
-  CreateSecurityDescriptionForPasswordReuse(
-      PasswordType password_type) const override {
+  CreateSecurityDescriptionForPasswordReuse() const override {
     std::unique_ptr<PageInfoUI::SecurityDescription> security_description(
         new PageInfoUI::SecurityDescription());
     security_description->summary_style = SecuritySummaryColor::RED;
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 1e820d7..a470642 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -45,7 +45,6 @@
 #include "chrome/browser/vr/vr_tab_helper.h"
 #include "chrome/common/url_constants.h"
 #include "components/content_settings/core/common/content_settings_types.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_strings.h"
@@ -917,8 +916,7 @@
 
 #if BUILDFLAG(FULL_SAFE_BROWSING)
 std::unique_ptr<PageInfoUI::SecurityDescription>
-PageInfoBubbleView::CreateSecurityDescriptionForPasswordReuse(
-    PasswordType password_type) const {
+PageInfoBubbleView::CreateSecurityDescriptionForPasswordReuse() const {
   std::unique_ptr<PageInfoUI::SecurityDescription> security_description(
       new PageInfoUI::SecurityDescription());
   security_description->summary_style = SecuritySummaryColor::RED;
@@ -926,28 +924,8 @@
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHANGE_PASSWORD_SUMMARY);
   auto* service = safe_browsing::ChromePasswordProtectionService::
       GetPasswordProtectionService(profile_);
-  password_manager::metrics_util::PasswordType metrics_password_type;
-  switch (password_type) {
-    case (PasswordType::NON_GAIA_ENTERPRISE):
-      metrics_password_type =
-          password_manager::metrics_util::PasswordType::ENTERPRISE_PASSWORD;
-      break;
-    case (PasswordType::SYNC_GAIA):
-      metrics_password_type = password_manager::metrics_util::PasswordType::
-          PRIMARY_ACCOUNT_PASSWORD;
-      break;
-    case (PasswordType::NON_SYNC_GAIA):
-      metrics_password_type =
-          password_manager::metrics_util::PasswordType::OTHER_GAIA_PASSWORD;
-      break;
-    default:
-      metrics_password_type =
-          password_manager::metrics_util::PasswordType::PASSWORD_TYPE_UNKNOWN;
-  }
-
   security_description->details = service->GetWarningDetailText(
-      service->GetPasswordProtectionReusedPasswordAccountType(
-          metrics_password_type, service->username()));
+      service->reused_password_account_type_for_last_shown_warning());
   return security_description;
 }
 #endif
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
index 86d8bb80..adc3c93 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -162,8 +162,7 @@
 
 #if BUILDFLAG(FULL_SAFE_BROWSING)
   std::unique_ptr<PageInfoUI::SecurityDescription>
-  CreateSecurityDescriptionForPasswordReuse(
-      PageInfoUI::PasswordType password_type) const override;
+  CreateSecurityDescriptionForPasswordReuse() const override;
 #endif
 
   // Creates the contents of the |site_settings_view_|. The ownership of the
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index 8cdc710..010a925 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -475,6 +475,8 @@
   safe_browsing::ReusedPasswordAccountType reused_password_account_type;
   reused_password_account_type.set_account_type(
       safe_browsing::ReusedPasswordAccountType::NON_GAIA_ENTERPRISE);
+  service->set_reused_password_account_type_for_last_shown_warning(
+      reused_password_account_type);
 
   service->ShowModalWarning(
       contents, safe_browsing::RequestOutcome::UNKNOWN,
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_sync_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_sync_browsertest.cc
index e260d4f..1ea9f9e1 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_sync_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_sync_browsertest.cc
@@ -161,13 +161,15 @@
   // SB_THREAT_TYPE_GAIA_PASSWORD_REUSE.
   safe_browsing::ChromePasswordProtectionService* service = safe_browsing::
       ChromePasswordProtectionService::GetPasswordProtectionService(profile);
-  service->set_username("user@gmail.com");
+  service->set_username_for_last_shown_warning("user@gmail.com");
   content::WebContents* contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   safe_browsing::ReusedPasswordAccountType account_type;
   account_type.set_account_type(
       safe_browsing::ReusedPasswordAccountType::GMAIL);
   account_type.set_is_account_syncing(true);
+  service->set_reused_password_account_type_for_last_shown_warning(
+      account_type);
   service->ShowModalWarning(
       contents, safe_browsing::RequestOutcome::UNKNOWN,
       safe_browsing::LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
index 36ab5f6..994d31c0 100644
--- a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
@@ -26,7 +26,14 @@
     {"simDetectPageErrorTitle", IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_TITLE},
     {"simDetectPageErrorMessage",
      IDS_CELLULAR_SETUP_SIM_DETECT_PAGE_ERROR_MESSAGE},
-    {"provisioningPageTitle", IDS_CELLULAR_SETUP_PROVISIONING_PAGE_TITLE},
+    {"provisioningPageLoadingTitle",
+     IDS_CELLULAR_SETUP_PROVISIONING_PAGE_LOADING_TITLE},
+    {"provisioningPageActiveTitle",
+     IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ACTIVE_TITLE},
+    {"provisioningPageErrorTitle",
+     IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_TITLE},
+    {"provisioningPageErrorMessage",
+     IDS_CELLULAR_SETUP_PROVISIONING_PAGE_ERROR_MESSAGE},
     {"finalPageTitle", IDS_CELLULAR_SETUP_FINAL_PAGE_TITLE},
     {"finalPageMessage", IDS_CELLULAR_SETUP_FINAL_PAGE_MESSAGE},
     {"finalPageErrorTitle", IDS_CELLULAR_SETUP_FINAL_PAGE_ERROR_TITLE},
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index a7af86e..2924ef42 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -378,8 +378,7 @@
       base::BindOnce(&GaiaScreenHandler::OnSetCookieForLoadGaiaWithPartition,
                      weak_factory_.GetWeakPtr(), context, partition_name);
   if (context.gaps_cookie.empty()) {
-    std::move(callback).Run(
-        net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+    std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus());
     return;
   }
 
diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.cc b/chrome/browser/ui/webui/extensions/extension_icon_source.cc
index 11995b5..76e1be5 100644
--- a/chrome/browser/ui/webui/extensions/extension_icon_source.cc
+++ b/chrome/browser/ui/webui/extensions/extension_icon_source.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -45,7 +46,7 @@
 namespace {
 
 scoped_refptr<base::RefCountedMemory> BitmapToMemory(const SkBitmap* image) {
-  base::RefCountedBytes* image_bytes = new base::RefCountedBytes;
+  auto image_bytes = base::MakeRefCounted<base::RefCountedBytes>();
   gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_bytes->data());
   return image_bytes;
 }
diff --git a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
index d765096..b4b7b46 100644
--- a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
+++ b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
@@ -10,7 +10,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "components/safe_browsing/password_protection/metrics_util.h"
 #include "components/safe_browsing/password_protection/password_protection_service.h"
@@ -47,10 +46,8 @@
  public:
   ResetPasswordHandlerImpl(
       content::WebContents* web_contents,
-      PasswordType password_type,
       mojo::InterfaceRequest<mojom::ResetPasswordHandler> request)
       : web_contents_(web_contents),
-        password_type_(password_type),
         binding_(this, std::move(request)) {
     DCHECK(web_contents);
   }
@@ -66,8 +63,7 @@
     if (service) {
       service->OnUserAction(
           web_contents_,
-          service->GetPasswordProtectionReusedPasswordAccountType(
-              password_type_, service->username()),
+          service->reused_password_account_type_for_last_shown_warning(),
           RequestOutcome::UNKNOWN,
           LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
           /*verdict_token=*/"", safe_browsing::WarningUIType::INTERSTITIAL,
@@ -77,7 +73,6 @@
 
  private:
   content::WebContents* web_contents_;
-  PasswordType password_type_;
   mojo::Binding<mojom::ResetPasswordHandler> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(ResetPasswordHandlerImpl);
@@ -133,15 +128,14 @@
 void ResetPasswordUI::BindResetPasswordHandler(
     mojom::ResetPasswordHandlerRequest request) {
   ui_handler_ = std::make_unique<ResetPasswordHandlerImpl>(
-      web_ui()->GetWebContents(), password_type_, std::move(request));
+      web_ui()->GetWebContents(), std::move(request));
 }
 
 base::DictionaryValue ResetPasswordUI::PopulateStrings() const {
   auto* service = safe_browsing::ChromePasswordProtectionService::
       GetPasswordProtectionService(Profile::FromWebUI(web_ui()));
   std::string org_name = service->GetOrganizationName(
-      service->GetPasswordProtectionReusedPasswordAccountType(
-          password_type_, service->username()));
+      service->reused_password_account_type_for_last_shown_warning());
   bool known_password_type =
       password_type_ != PasswordType::PASSWORD_TYPE_UNKNOWN;
 
diff --git a/chrome/browser/ui/webui/settings/change_password_handler.cc b/chrome/browser/ui/webui/settings/change_password_handler.cc
index dffa209..b34815f 100644
--- a/chrome/browser/ui/webui/settings/change_password_handler.cc
+++ b/chrome/browser/ui/webui/settings/change_password_handler.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/safe_browsing/password_protection/metrics_util.h"
 #include "components/safe_browsing/proto/csd.pb.h"
@@ -61,8 +60,7 @@
 void ChangePasswordHandler::HandleChangePassword(const base::ListValue* args) {
   service_->OnUserAction(
       web_ui()->GetWebContents(),
-      service_->GetPasswordProtectionReusedPasswordAccountType(
-          PasswordType::PRIMARY_ACCOUNT_PASSWORD, service_->username()),
+      service_->reused_password_account_type_for_last_shown_warning(),
       RequestOutcome::UNKNOWN,
       LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED, "unused_token",
       safe_browsing::WarningUIType::CHROME_SETTINGS,
@@ -72,12 +70,12 @@
 void ChangePasswordHandler::UpdateChangePasswordCardVisibility() {
   FireWebUIListener(
       "change-password-visibility",
-      base::Value(service_->IsWarningEnabled(
-                      service_->GetPasswordProtectionReusedPasswordAccountType(
-                          PasswordType::PRIMARY_ACCOUNT_PASSWORD,
-                          service_->username())) &&
-                  safe_browsing::ChromePasswordProtectionService::
-                      ShouldShowChangePasswordSettingUI(profile_)));
+      base::Value(
+          service_->IsWarningEnabled(
+              service_
+                  ->reused_password_account_type_for_last_shown_warning()) &&
+          safe_browsing::ChromePasswordProtectionService::
+              ShouldShowChangePasswordSettingUI(profile_)));
 }
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
index d9c0592..25dbe1f 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -20,6 +20,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/same_site_data_remover.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_ui.h"
@@ -130,6 +131,7 @@
 }
 
 void CookiesViewHandler::OnJavascriptDisallowed() {
+  callback_weak_ptr_factory_.InvalidateWeakPtrs();
 }
 
 void CookiesViewHandler::RegisterMessages() {
@@ -164,6 +166,10 @@
       base::BindRepeating(&CookiesViewHandler::HandleRemove,
                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+      "localData.removeThirdPartyCookies",
+      base::BindRepeating(&CookiesViewHandler::HandleRemoveThirdParty,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "localData.reload",
       base::BindRepeating(&CookiesViewHandler::HandleReloadCookies,
                           base::Unretained(this)));
@@ -244,6 +250,13 @@
   }
 }
 
+void CookiesViewHandler::RecreateCookiesTreeModel() {
+  cookies_tree_model_.reset();
+  filter_.clear();
+  sorted_sites_.clear();
+  EnsureCookiesTreeModelCreated();
+}
+
 void CookiesViewHandler::HandleGetCookieDetails(const base::ListValue* args) {
   CHECK(request_.callback_id_.empty());
   CHECK_EQ(2U, args->GetSize());
@@ -306,10 +319,7 @@
   CHECK(args->GetString(0, &request_.callback_id_));
 
   AllowJavascript();
-  cookies_tree_model_.reset();
-  filter_.clear();
-  sorted_sites_.clear();
-  EnsureCookiesTreeModelCreated();
+  RecreateCookiesTreeModel();
 }
 
 void CookiesViewHandler::HandleRemoveAll(const base::ListValue* args) {
@@ -335,6 +345,20 @@
   }
 }
 
+void CookiesViewHandler::HandleRemoveThirdParty(const base::ListValue* args) {
+  CHECK(request_.callback_id_.empty());
+  CHECK_EQ(1U, args->GetSize());
+  CHECK(args->GetString(0, &request_.callback_id_));
+
+  AllowJavascript();
+  Profile* profile = Profile::FromWebUI(web_ui());
+  ClearSameSiteNoneData(
+      base::BindOnce(&CookiesViewHandler::RecreateCookiesTreeModel,
+                     callback_weak_ptr_factory_.GetWeakPtr()),
+      profile,
+      /* clear_storage */ true);
+}
+
 void CookiesViewHandler::HandleRemoveShownItems(const base::ListValue* args) {
   CHECK_EQ(0U, args->GetSize());
 
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
index 574978c..d5a031bf 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h
@@ -49,6 +49,9 @@
   // Creates the CookiesTreeModel if necessary.
   void EnsureCookiesTreeModelCreated();
 
+  // Resets the CookiesTreeModel, the current |filter_|, and the site list.
+  void RecreateCookiesTreeModel();
+
   // Set |filter_| and get a portion (or all) of the list items.
   void HandleGetDisplayList(const base::ListValue* args);
 
@@ -70,6 +73,9 @@
   // Remove selected sites data.
   void HandleRemove(const base::ListValue* args);
 
+  // Removes cookies and site data available in third-party contexts.
+  void HandleRemoveThirdParty(const base::ListValue* args);
+
   // Get children nodes data and pass it to 'CookiesView.loadChildren' to
   // update the WebUI.
   void SendChildren(const CookieTreeNode* parent);
@@ -111,6 +117,9 @@
 
   std::unique_ptr<CookiesTreeModelUtil> model_util_;
 
+  // Used to cancel callbacks when JavaScript becomes disallowed.
+  base::WeakPtrFactory<CookiesViewHandler> callback_weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(CookiesViewHandler);
 };
 
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 433aebc7..ce0599dc 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -41,6 +41,7 @@
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
+#include "components/browsing_data/core/features.h"
 #include "components/google/core/common/google_util.h"
 #include "components/omnibox/common/omnibox_features.h"
 #include "components/password_manager/core/browser/manage_passwords_referrer.h"
@@ -2925,6 +2926,14 @@
      IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_ALL},
     {"siteSettingsCookieRemoveAllShown",
      IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_ALL_SHOWN},
+    {"siteSettingsCookieRemoveAllThirdParty",
+     IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_ALL_THIRD_PARTY},
+    {"siteSettingsCookieRemoveThirdPartyDialogTitle",
+     IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_REMOVE_DIALOG_TITLE},
+    {"siteSettingsCookieRemoveThirdPartyConfirmation",
+     IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_REMOVE_CONFIRMATION},
+    {"siteSettingsCookiesClearThirdParty",
+     IDS_SETTINGS_SITE_SETTINGS_CLEAR_THIRD_PARTY_COOKIES},
     {"siteSettingsCookieRemoveDialogTitle",
      IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_DIALOG_TITLE},
     {"siteSettingsCookieRemoveMultipleConfirmation",
@@ -3043,6 +3052,11 @@
   html_source->AddBoolean(
       "enableNativeFileSystemWriteContentSetting",
       base::FeatureList::IsEnabled(::blink::features::kNativeFileSystemAPI));
+
+  html_source->AddBoolean(
+      "enableRemovingAllThirdPartyCookies",
+      base::FeatureList::IsEnabled(
+          browsing_data::features::kEnableRemovingAllThirdPartyCookies));
 }
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index fcd5d1a..e4ff297 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -236,6 +236,7 @@
     "channel": "stable",
     "contexts": ["webui"],
     "matches": [
+      "chrome://cellular-setup/*",
       "chrome://chrome-signin/*",
       "chrome://discards/*",
       "chrome://hats/*",
diff --git a/chrome/common/instant_mojom_traits.h b/chrome/common/instant_mojom_traits.h
index ee31e8b..93ee65be 100644
--- a/chrome/common/instant_mojom_traits.h
+++ b/chrome/common/instant_mojom_traits.h
@@ -85,4 +85,6 @@
   IPC_STRUCT_TRAITS_MEMBER(color_dark)
   IPC_STRUCT_TRAITS_MEMBER(color_light)
   IPC_STRUCT_TRAITS_MEMBER(color_picked)
+  IPC_STRUCT_TRAITS_MEMBER(logo_color)
+  IPC_STRUCT_TRAITS_MEMBER(shortcut_color)
 IPC_STRUCT_TRAITS_END()
diff --git a/chrome/common/search/instant_types.cc b/chrome/common/search/instant_types.cc
index ee660c4..f94c1be9 100644
--- a/chrome/common/search/instant_types.cc
+++ b/chrome/common/search/instant_types.cc
@@ -33,7 +33,8 @@
          has_theme_image == rhs.has_theme_image &&
          theme_name == rhs.theme_name && color_id == rhs.color_id &&
          color_dark == rhs.color_dark && color_light == rhs.color_light &&
-         color_picked == rhs.color_picked;
+         color_picked == rhs.color_picked && logo_color == rhs.logo_color &&
+         shortcut_color == rhs.shortcut_color;
 }
 
 InstantMostVisitedItem::InstantMostVisitedItem()
diff --git a/chrome/common/search/instant_types.h b/chrome/common/search/instant_types.h
index 331ee75d..99916b21 100644
--- a/chrome/common/search/instant_types.h
+++ b/chrome/common/search/instant_types.h
@@ -127,6 +127,12 @@
   // The picked custom color for Chrome Colors. Valid only if Chrome Colors is
   // set.
   SkColor color_picked = gfx::kPlaceholderColor;
+
+  // Color used for alternative Google logo on NTP.
+  SkColor logo_color = gfx::kPlaceholderColor;
+
+  // Color for NTP shortcut backgrounds.
+  SkColor shortcut_color = gfx::kPlaceholderColor;
 };
 
 struct InstantMostVisitedItem {
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 5a45fb5..203a297 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -1831,6 +1831,35 @@
   return hr;
 }
 
+// Registers OS user - gaia user association in HKEY_LOCAL_MACHINE registry
+// hive.
+HRESULT RegisterAssociation(const base::string16& sid,
+                            const base::string16& id,
+                            const base::string16& email,
+                            const base::string16& token_handle) {
+  // Save token handle.  This handle will be used later to determine if the
+  // the user has changed their password since the account was created.
+  HRESULT hr = SetUserProperty(sid, kUserTokenHandle, token_handle);
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "SetUserProperty(th) hr=" << putHR(hr);
+    return hr;
+  }
+
+  hr = SetUserProperty(sid, kUserId, id);
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "SetUserProperty(id) hr=" << putHR(hr);
+    return hr;
+  }
+
+  hr = SetUserProperty(sid, kUserEmail, email);
+  if (FAILED(hr)) {
+    LOGFN(ERROR) << "SetUserProperty(email) hr=" << putHR(hr);
+    return hr;
+  }
+
+  return S_OK;
+}
+
 HRESULT CGaiaCredentialBase::ReportResult(
     NTSTATUS status,
     NTSTATUS substatus,
@@ -1853,12 +1882,33 @@
     authentication_results_->SetKey(
         kKeyPassword, base::Value(base::UTF16ToUTF8((BSTR)password_)));
 
+    base::string16 gaia_id = GetDictString(*authentication_results_, kKeyId);
+    if (gaia_id.empty()) {
+      LOGFN(ERROR) << "Id is empty";
+      return E_INVALIDARG;
+    }
+
+    base::string16 email = GetDictString(*authentication_results_, kKeyEmail);
+    if (email.empty()) {
+      LOGFN(ERROR) << "Email is empty";
+      return E_INVALIDARG;
+    }
+
+    // Os user - gaia user association is saved in HKEY_LOCAL_MACHINE. So, we
+    // can attempt saving association even before calling forked process. Forked
+    // process will also re-write everything saved here as well as valid token
+    // handle. Token handle is saved as empty here, so that if for any reason
+    // forked process fails to save association, it will enforce re-auth due to
+    // invalid token handle.
+    HRESULT hr = RegisterAssociation(OLE2CW(user_sid_), gaia_id, email, L"");
+    if (FAILED(hr))
+      return hr;
+
     // At this point the user and password stored in authentication_results_
     // should match what is stored in username_ and password_ so the
     // SaveAccountInfo process can be forked.
     CComBSTR status_text;
-    HRESULT hr =
-        ForkSaveAccountInfoStub(*authentication_results_, &status_text);
+    hr = ForkSaveAccountInfoStub(*authentication_results_, &status_text);
     if (FAILED(hr))
       LOGFN(ERROR) << "ForkSaveAccountInfoStub hr=" << putHR(hr);
   }
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc
index d2f3c6b5..dd9509e4 100644
--- a/chrome/renderer/extensions/cast_streaming_native_handler.cc
+++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -18,6 +18,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -403,8 +404,8 @@
 
   v8::Isolate* isolate = context()->v8_context()->GetIsolate();
 
-  scoped_refptr<CastSession> session(new CastSession(
-      context()->web_frame()->GetTaskRunner(blink::TaskType::kInternalMedia)));
+  auto session = base::MakeRefCounted<CastSession>(
+      context()->web_frame()->GetTaskRunner(blink::TaskType::kInternalMedia));
   std::unique_ptr<CastRtpStream> stream1, stream2;
   if ((args[0]->IsNull() || args[0]->IsUndefined()) &&
       (args[1]->IsNull() || args[1]->IsUndefined())) {
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 3042bc8..e585c6bd 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -57,75 +57,6 @@
 #include "url/url_constants.h"
 #include "v8/include/v8.h"
 
-namespace internal {  // for testing.
-
-// Whether NTP background should be considered dark, so the colors of various
-// UI elements can be adjusted. Light text implies dark theme.
-bool IsNtpBackgroundDark(SkColor ntp_text) {
-  return !color_utils::IsDark(ntp_text);
-}
-
-// Calculate contrasting color for given |bg_color|. Returns lighter color if
-// the color is very dark and returns darker color otherwise.
-SkColor GetContrastingColorForBackground(SkColor bg_color,
-                                         float luminosity_change) {
-  color_utils::HSL hsl;
-  SkColorToHSL(bg_color, &hsl);
-
-  // If luminosity is 0, it means |bg_color| is black. Use white for black
-  // backgrounds.
-  if (hsl.l == 0)
-    return SK_ColorWHITE;
-
-  // Decrease luminosity, unless color is already dark.
-  if (hsl.l > 0.15)
-    luminosity_change *= -1;
-
-  hsl.l *= 1 + luminosity_change;
-  if (hsl.l >= 0.0f && hsl.l <= 1.0f)
-    return HSLToSkColor(hsl, 255);
-  return bg_color;
-}
-
-// Use dark icon when in dark mode and no background. Otherwise, use
-// light icon for NTPs with images, and themed icon for NTPs with solid color.
-SkColor GetIconColor(const ThemeBackgroundInfo& theme_info) {
-  bool has_background_image = theme_info.has_theme_image ||
-                              !theme_info.custom_background_url.is_empty();
-  if (has_background_image)
-    return kNTPLightIconColor;
-
-  if (theme_info.using_dark_colors && theme_info.using_default_theme)
-    return kNTPDarkIconColor;
-
-  SkColor bg_color = theme_info.background_color;
-  SkColor icon_color = kNTPLightIconColor;
-  if (!theme_info.using_default_theme && bg_color != SK_ColorWHITE) {
-    icon_color =
-        GetContrastingColorForBackground(bg_color, /*luminosity_change=*/0.2f);
-  }
-
-  return icon_color;
-}
-
-// For themes that use alternate logo and no NTP background image is present,
-// set logo color in the same hue as NTP background.
-SkColor GetLogoColor(const ThemeBackgroundInfo& theme_info) {
-  SkColor logo_color = kNTPLightLogoColor;
-  bool has_background_image = theme_info.has_theme_image ||
-                              !theme_info.custom_background_url.is_empty();
-  if (theme_info.logo_alternate && !has_background_image) {
-    if (color_utils::IsDark(theme_info.background_color))
-      logo_color = SK_ColorWHITE;
-    else
-      logo_color = GetContrastingColorForBackground(theme_info.background_color,
-                                                    /*luminosity_change=*/0.3f);
-  }
-
-  return logo_color;
-}
-}  // namespace internal
-
 namespace {
 
 const char kCSSBackgroundImageFormat[] = "-webkit-image-set("
@@ -307,8 +238,6 @@
   return true;
 }
 
-// TODO(gayane): Move all non-trival logic to |instant_service| and do only
-// mapping here. crbug.com/983717.
 v8::Local<v8::Object> GenerateThemeBackgroundInfo(
     v8::Isolate* isolate,
     const ThemeBackgroundInfo& theme_info) {
@@ -324,12 +253,16 @@
   builder.Set("backgroundColorRgba",
               SkColorToArray(isolate, theme_info.background_color));
 
+  // Theme color for text as an array with the RGBA components in order.
+  // Value is always valid.
+  builder.Set("textColorRgba", SkColorToArray(isolate, theme_info.text_color));
+
   // Theme color for light text as an array with the RGBA components in order.
   // Value is always valid.
   builder.Set("textColorLightRgba",
               SkColorToArray(isolate, theme_info.text_color_light));
 
-  // The theme alternate logo value indicates a white logo when TRUE and a
+  // The theme alternate logo value indicates same color when TRUE and a
   // colorful one when FALSE.
   builder.Set("alternateLogo", theme_info.logo_alternate);
 
@@ -404,17 +337,12 @@
   builder.Set("themeId", theme_info.theme_id);
   builder.Set("themeName", theme_info.theme_name);
 
-  // Assume that a custom background has not been configured and then
-  // override based on the condition below.
-  builder.Set("customBackgroundConfigured", false);
-  SkColor ntp_text = theme_info.text_color;
+  builder.Set("customBackgroundConfigured",
+              !theme_info.custom_background_url.is_empty());
 
   // If a custom background has been set provide the relevant information to the
   // page.
   if (!theme_info.custom_background_url.is_empty()) {
-    ntp_text = SkColorSetARGB(255, 248, 249, 250);  // GG050
-    builder.Set("alternateLogo", true);
-    builder.Set("customBackgroundConfigured", true);
     builder.Set("imageUrl", theme_info.custom_background_url.spec());
     builder.Set("attributionActionUrl",
                 theme_info.custom_background_attribution_action_url.spec());
@@ -428,20 +356,18 @@
     builder.Set("attributionUrl", std::string());
   }
 
-  // Theme color for text as an array with the RGBA components in order.
-  // Value is always valid.
-  builder.Set("textColorRgba", SkColorToArray(isolate, ntp_text));
-
-  // Generate fields for themeing NTP elements.
-  builder.Set("isNtpBackgroundDark", internal::IsNtpBackgroundDark(ntp_text));
+  // Set fields for themeing NTP elements.
+  builder.Set("isNtpBackgroundDark",
+              !color_utils::IsDark(theme_info.text_color));
   builder.Set("useTitleContainer", theme_info.has_theme_image);
 
-  SkColor icon_color = internal::GetIconColor(theme_info);
-  builder.Set("iconBackgroundColor", SkColorToArray(isolate, icon_color));
-  builder.Set("useWhiteAddIcon", color_utils::IsDark(icon_color));
+  // TODO(gayane): Rename icon color to shortcut color in JS for consitancy.
+  builder.Set("iconBackgroundColor",
+              SkColorToArray(isolate, theme_info.shortcut_color));
+  builder.Set("useWhiteAddIcon",
+              color_utils::IsDark(theme_info.shortcut_color));
 
-  builder.Set("logoColor",
-              SkColorToArray(isolate, internal::GetLogoColor(theme_info)));
+  builder.Set("logoColor", SkColorToArray(isolate, theme_info.logo_color));
 
   builder.Set("colorId", theme_info.color_id);
   if (theme_info.color_id != -1) {
diff --git a/chrome/renderer/searchbox/searchbox_extension_unittest.cc b/chrome/renderer/searchbox/searchbox_extension_unittest.cc
deleted file mode 100644
index 0f2d43c..0000000
--- a/chrome/renderer/searchbox/searchbox_extension_unittest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/renderer/searchbox/searchbox_extension.h"
-
-#include "chrome/common/search/instant_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/color_utils.h"
-
-namespace internal {
-
-// Defined in searchbox_extension.cc
-bool IsNtpBackgroundDark(SkColor ntp_text);
-SkColor GetContrastingColorForBackground(SkColor bg_color, float change);
-SkColor GetIconColor(const ThemeBackgroundInfo& theme_info);
-SkColor GetLogoColor(const ThemeBackgroundInfo& theme_info);
-
-TEST(SearchboxExtensionTest, TestIsNtpBackgroundDark) {
-  // Dark font means light background.
-  EXPECT_FALSE(IsNtpBackgroundDark(SK_ColorBLACK));
-
-  // Light font means dark background.
-  EXPECT_TRUE(IsNtpBackgroundDark(SK_ColorWHITE));
-
-  // Light but close to mid point color text implies dark background.
-  EXPECT_TRUE(IsNtpBackgroundDark(SkColorSetARGB(255, 30, 144, 255)));
-}
-
-TEST(SearchboxExtensionTest, TestGetContrastingColor) {
-  const float change = 0.2f;
-
-  // White icon for black background.
-  EXPECT_EQ(SK_ColorWHITE,
-            GetContrastingColorForBackground(SK_ColorBLACK, change));
-
-  // Lighter icon for too dark colors.
-  SkColor dark_background = SkColorSetARGB(255, 50, 0, 50);
-  EXPECT_LT(color_utils::GetRelativeLuminance(dark_background),
-            color_utils::GetRelativeLuminance(
-                GetContrastingColorForBackground(dark_background, change)));
-
-  // Darker icon for light backgrounds.
-  EXPECT_GT(color_utils::GetRelativeLuminance(SK_ColorWHITE),
-            color_utils::GetRelativeLuminance(
-                GetContrastingColorForBackground(SK_ColorWHITE, change)));
-
-  SkColor light_background = SkColorSetARGB(255, 100, 0, 100);
-  EXPECT_GT(color_utils::GetRelativeLuminance(light_background),
-            color_utils::GetRelativeLuminance(
-                GetContrastingColorForBackground(light_background, change)));
-}
-
-TEST(SearchboxExtensionTest, TestGetIconColor) {
-  ThemeBackgroundInfo theme_info;
-  theme_info.using_default_theme = true;
-  theme_info.using_dark_colors = false;
-  theme_info.background_color = SK_ColorRED;
-
-  // Default theme in light mode.
-  EXPECT_EQ(kNTPLightIconColor, GetIconColor(theme_info));
-
-  // Default theme in dark mode.
-  theme_info.using_dark_colors = true;
-  EXPECT_EQ(kNTPDarkIconColor, GetIconColor(theme_info));
-
-  // Default theme with custom background, in dark mode.
-  theme_info.custom_background_url = GURL("https://www.foo.com");
-  EXPECT_EQ(kNTPLightIconColor, GetIconColor(theme_info));
-
-  // Default theme with custom background.
-  theme_info.using_dark_colors = false;
-  EXPECT_EQ(kNTPLightIconColor, GetIconColor(theme_info));
-
-  // Theme with image.
-  theme_info.using_default_theme = false;
-  theme_info.custom_background_url = GURL();
-  theme_info.has_theme_image = true;
-  EXPECT_EQ(kNTPLightIconColor, GetIconColor(theme_info));
-
-  // Theme with image in dark mode.
-  theme_info.using_dark_colors = true;
-  EXPECT_EQ(kNTPLightIconColor, GetIconColor(theme_info));
-
-  SkColor red_icon_color = GetContrastingColorForBackground(SK_ColorRED, 0.2f);
-
-  // Theme with no image, in dark mode.
-  theme_info.has_theme_image = false;
-  EXPECT_EQ(red_icon_color, GetIconColor(theme_info));
-
-  // Theme with no image.
-  theme_info.using_dark_colors = false;
-  EXPECT_EQ(red_icon_color, GetIconColor(theme_info));
-}
-
-TEST(SearchboxExtensionTest, TestGetLogoColor) {
-  ThemeBackgroundInfo theme_info;
-  theme_info.using_default_theme = true;
-  theme_info.logo_alternate = false;
-  theme_info.background_color = SK_ColorWHITE;
-
-  // Default theme.
-  EXPECT_EQ(kNTPLightLogoColor, GetLogoColor(theme_info));
-
-  // Default theme in dark mode.
-  theme_info.using_dark_colors = true;
-  theme_info.background_color = SK_ColorBLACK;
-  EXPECT_EQ(kNTPLightLogoColor, GetLogoColor(theme_info));
-
-  // Default theme with custom background.
-  theme_info.using_dark_colors = false;
-  theme_info.background_color = SK_ColorWHITE;
-  theme_info.custom_background_url = GURL("https://www.foo.com");
-  EXPECT_EQ(kNTPLightLogoColor, GetLogoColor(theme_info));
-
-  // Theme with image.
-  theme_info.using_default_theme = false;
-  theme_info.logo_alternate = true;
-  theme_info.custom_background_url = GURL();
-  theme_info.has_theme_image = true;
-  theme_info.background_color = SK_ColorRED;
-  EXPECT_EQ(kNTPLightLogoColor, GetLogoColor(theme_info));
-
-  // Theme with no image.
-  theme_info.has_theme_image = false;
-  theme_info.background_color = SK_ColorBLACK;
-  EXPECT_EQ(SK_ColorWHITE, GetLogoColor(theme_info));
-
-  // Close to midpoint but still dark color should have white logo.
-  theme_info.background_color = SkColorSetRGB(120, 120, 120);
-  EXPECT_EQ(SK_ColorWHITE, GetLogoColor(theme_info));
-
-  // Light color should have themed logo.
-  theme_info.background_color = SkColorSetRGB(130, 130, 130);
-  EXPECT_NE(kNTPLightLogoColor, GetLogoColor(theme_info));
-  EXPECT_NE(SK_ColorWHITE, GetLogoColor(theme_info));
-  EXPECT_NE(theme_info.background_color, GetLogoColor(theme_info));
-}
-}  // namespace internal
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8c65dd5..875aae1b 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3852,7 +3852,6 @@
       "../common/importer/mock_importer_bridge.h",
       "../common/multi_process_lock_unittest.cc",
       "../renderer/searchbox/search_bouncer_unittest.cc",
-      "../renderer/searchbox/searchbox_extension_unittest.cc",
       "../renderer/searchbox/searchbox_unittest.cc",
       "../test/base/browser_with_test_window_test.cc",
       "../test/base/browser_with_test_window_test.h",
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index eb261f4..9b32776c 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -731,7 +731,11 @@
   if (!found)
     return Status(kNoSuchWindow);
 
-  if (session->overridden_geoposition) {
+  if (session->overridden_geoposition ||
+      session->overridden_network_conditions ||
+      session->headless_download_directory ||
+      session->chrome->IsMobileEmulationEnabled()) {
+    // Connect to new window to apply session configuration
     WebView* web_view;
     Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
     if (status.IsError())
@@ -739,46 +743,25 @@
     status = web_view->ConnectIfNecessary();
     if (status.IsError())
       return status;
-    status = web_view->OverrideGeolocation(*session->overridden_geoposition);
-    if (status.IsError())
-      return status;
-  }
 
-  if (session->overridden_network_conditions) {
-    WebView* web_view;
-    Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
-    if (status.IsError())
-      return status;
-    status = web_view->ConnectIfNecessary();
-    if (status.IsError())
-      return status;
-    status = web_view->OverrideNetworkConditions(
-        *session->overridden_network_conditions);
-    if (status.IsError())
-      return status;
-  }
-  if (session->headless_download_directory) {
-    WebView* web_view;
-    Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
-    if (status.IsError())
-      return status;
-    status = web_view->ConnectIfNecessary();
-    if (status.IsError())
-      return status;
-    status = web_view->OverrideDownloadDirectoryIfNeeded(
-        *session->headless_download_directory);
-    if (status.IsError())
-      return status;
-  }
-
-  if (session->chrome->IsMobileEmulationEnabled()) {
-    WebView* web_view;
-    Status status = session->chrome->GetWebViewById(web_view_id, &web_view);
-    if (status.IsError())
-      return status;
-    status = web_view->ConnectIfNecessary();
-    if (status.IsError())
-      return status;
+    // apply type specific configurations:
+    if (session->overridden_geoposition) {
+      status = web_view->OverrideGeolocation(*session->overridden_geoposition);
+      if (status.IsError())
+        return status;
+    }
+    if (session->overridden_network_conditions) {
+      status = web_view->OverrideNetworkConditions(
+          *session->overridden_network_conditions);
+      if (status.IsError())
+        return status;
+    }
+    if (session->headless_download_directory) {
+      status = web_view->OverrideDownloadDirectoryIfNeeded(
+          *session->headless_download_directory);
+      if (status.IsError())
+        return status;
+    }
   }
 
   status = session->chrome->ActivateWebView(web_view_id);
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
index 7849b5dd1..04590fe 100644
--- a/chrome/test/data/autofill/captured_sites/testcases.json
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
@@ -128,7 +128,7 @@
     { "site_name": "moma", "expectation":"PASS" },
     { "site_name": "monoprice", "expectation":"PASS" },
     { "site_name": "palmettostatearmory", "expectation":"PASS" },
-    { "site_name": "pandora", "expectation":"PASS" },
+    { "site_name": "pandora", "expectation":"FAIL", "bug_number":996478 },
     { "site_name": "sephora", "expectation":"PASS" },
     { "site_name": "ticketmaster_uk", "expectation":"PASS" },
     { "site_name": "vitacost", "expectation":"PASS" },
@@ -149,7 +149,7 @@
     { "site_name": "north_face", "expectation":"FAIL", "bug_number":996478 },
     { "site_name": "oshkosh", "expectation":"FAIL", "bug_number":996478 },
     { "site_name": "partycity", "expectation":"PASS" },
-    { "site_name": "payless", "expectation":"PASS" },
+    { "site_name": "payless", "expectation":"FAIL", "bug_number":996478 },
     { "site_name": "petco", "expectation":"PASS" },
     { "site_name": "represent", "expectation":"PASS" },
     { "site_name": "tillys", "expectation":"PASS" },
diff --git a/chrome/test/data/pdf/navigator_test.js b/chrome/test/data/pdf/navigator_test.js
index e6959f63..fbfc89b8c 100644
--- a/chrome/test/data/pdf/navigator_test.js
+++ b/chrome/test/data/pdf/navigator_test.js
@@ -2,28 +2,32 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function MockNavigatorDelegate() {
-  this.navigateInCurrentTabCalled = false;
-  this.navigateInNewTabCalled = false;
-  this.navigateInNewWindowCalled = false;
-  this.url = undefined;
-}
+class MockNavigatorDelegate {
+  constructor() {
+    this.navigateInCurrentTabCalled = false;
+    this.navigateInNewTabCalled = false;
+    this.navigateInNewWindowCalled = false;
+    this.url = undefined;
+  }
 
-MockNavigatorDelegate.prototype = {
-  navigateInCurrentTab: function(url) {
+  /** @param {?string} url */
+  navigateInCurrentTab(url) {
     this.navigateInCurrentTabCalled = true;
     this.url = url || '<called, but no url set>';
-  },
-  navigateInNewTab: function(url) {
+  }
+
+  /** @param {?string} url */
+  navigateInNewTab(url) {
     this.navigateInNewTabCalled = true;
     this.url = url || '<called, but no url set>';
+  }
 
-  },
-  navigateInNewWindow: function(url) {
+  navigateInNewWindow(url) {
     this.navigateInNewWindowCalled = true;
     this.url = url || '<called, but no url set>';
-  },
-  reset: function() {
+  }
+
+  reset() {
     this.navigateInCurrentTabCalled = false;
     this.navigateInNewTabCalled = false;
     this.navigateInNewWindowCalled = false;
@@ -53,13 +57,13 @@
     return;
   }
   switch (disposition) {
-    case Navigator.WindowOpenDisposition.CURRENT_TAB:
+    case PdfNavigator.WindowOpenDisposition.CURRENT_TAB:
       chrome.test.assertTrue(navigatorDelegate.navigateInCurrentTabCalled);
       break;
-    case Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
+    case PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB:
       chrome.test.assertTrue(navigatorDelegate.navigateInNewTabCalled);
       break;
-    case Navigator.WindowOpenDisposition.NEW_WINDOW:
+    case PdfNavigator.WindowOpenDisposition.NEW_WINDOW:
       chrome.test.assertTrue(navigatorDelegate.navigateInNewWindowCalled);
       break;
     default:
@@ -78,23 +82,23 @@
   var viewport = new Viewport(mockWindow, mockSizer, 0, 1, 0);
   viewport.setViewportChangedCallback(mockViewportChangedCallback.callback);
 
-  var paramsParser = new OpenPDFParamsParser(function(name) {
+  var paramsParser = new OpenPdfParamsParser(function(name) {
     paramsParser.onNamedDestinationReceived(-1);
   });
 
   var navigatorDelegate = new MockNavigatorDelegate();
-  var navigator = new Navigator(originalUrl, viewport, paramsParser,
-                                navigatorDelegate);
+  var navigator =
+      new PdfNavigator(originalUrl, viewport, paramsParser, navigatorDelegate);
 
-  doNavigationUrlTest(navigator, url,
-      Navigator.WindowOpenDisposition.CURRENT_TAB, expectedResultUrl,
-      mockViewportChangedCallback, navigatorDelegate);
-  doNavigationUrlTest(navigator, url,
-      Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB, expectedResultUrl,
-      mockViewportChangedCallback, navigatorDelegate);
-  doNavigationUrlTest(navigator, url,
-      Navigator.WindowOpenDisposition.NEW_WINDOW, expectedResultUrl,
-      mockViewportChangedCallback, navigatorDelegate);
+  doNavigationUrlTest(
+      navigator, url, PdfNavigator.WindowOpenDisposition.CURRENT_TAB,
+      expectedResultUrl, mockViewportChangedCallback, navigatorDelegate);
+  doNavigationUrlTest(
+      navigator, url, PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB,
+      expectedResultUrl, mockViewportChangedCallback, navigatorDelegate);
+  doNavigationUrlTest(
+      navigator, url, PdfNavigator.WindowOpenDisposition.NEW_WINDOW,
+      expectedResultUrl, mockViewportChangedCallback, navigatorDelegate);
 }
 
 var tests = [
@@ -109,7 +113,7 @@
     var viewport = new Viewport(mockWindow, mockSizer, 0, 1, 0);
     viewport.setViewportChangedCallback(mockCallback.callback);
 
-    var paramsParser = new OpenPDFParamsParser(function(message) {
+    var paramsParser = new OpenPdfParamsParser(function(message) {
       if (message.namedDestination == 'US')
         paramsParser.onNamedDestinationReceived(0);
       else if (message.namedDestination == 'UY')
@@ -120,8 +124,8 @@
     var url = "http://xyz.pdf";
 
     var navigatorDelegate = new MockNavigatorDelegate();
-    var navigator = new Navigator(url, viewport, paramsParser,
-                                  navigatorDelegate);
+    var navigator =
+        new PdfNavigator(url, viewport, paramsParser, navigatorDelegate);
 
     var documentDimensions = new MockDocumentDimensions();
     documentDimensions.addPage(100, 100);
@@ -132,8 +136,8 @@
 
     mockCallback.reset();
     // This should move viewport to page 0.
-    navigator.navigate(url + "#US",
-        Navigator.WindowOpenDisposition.CURRENT_TAB);
+    navigator.navigate(
+        url + '#US', PdfNavigator.WindowOpenDisposition.CURRENT_TAB);
     chrome.test.assertTrue(mockCallback.wasCalled);
     chrome.test.assertEq(0, viewport.position.x);
     chrome.test.assertEq(0, viewport.position.y);
@@ -142,8 +146,8 @@
     navigatorDelegate.reset();
     // This should open "http://xyz.pdf#US" in a new tab. So current tab
     // viewport should not update and viewport position should remain same.
-    navigator.navigate(url + "#US",
-        Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
+    navigator.navigate(
+        url + '#US', PdfNavigator.WindowOpenDisposition.NEW_BACKGROUND_TAB);
     chrome.test.assertFalse(mockCallback.wasCalled);
     chrome.test.assertTrue(navigatorDelegate.navigateInNewTabCalled);
     chrome.test.assertEq(0, viewport.position.x);
@@ -151,8 +155,8 @@
 
     mockCallback.reset();
     // This should move viewport to page 2.
-    navigator.navigate(url + "#UY",
-        Navigator.WindowOpenDisposition.CURRENT_TAB);
+    navigator.navigate(
+        url + '#UY', PdfNavigator.WindowOpenDisposition.CURRENT_TAB);
     chrome.test.assertTrue(mockCallback.wasCalled);
     chrome.test.assertEq(0, viewport.position.x);
     chrome.test.assertEq(300, viewport.position.y);
@@ -162,8 +166,8 @@
     // #ABC is not a named destination in the page so viewport should not
     // update and viewport position should remain same. As this link will open
     // in the same tab.
-    navigator.navigate(url + "#ABC",
-        Navigator.WindowOpenDisposition.CURRENT_TAB);
+    navigator.navigate(
+        url + '#ABC', PdfNavigator.WindowOpenDisposition.CURRENT_TAB);
     chrome.test.assertFalse(mockCallback.wasCalled);
     chrome.test.assertTrue(navigatorDelegate.navigateInCurrentTabCalled);
     chrome.test.assertEq(0, viewport.position.x);
diff --git a/chrome/test/data/pdf/params_parser_test.js b/chrome/test/data/pdf/params_parser_test.js
index 5bb91a5..e50fb20 100644
--- a/chrome/test/data/pdf/params_parser_test.js
+++ b/chrome/test/data/pdf/params_parser_test.js
@@ -7,7 +7,7 @@
    * Test named destinations.
    */
   function testParamsParser() {
-    var paramsParser = new OpenPDFParamsParser(function(message) {
+    var paramsParser = new OpenPdfParamsParser(function(message) {
       chrome.test.assertEq('getNamedDestination', message.type);
       if (message.namedDestination == 'RU')
         paramsParser.onNamedDestinationReceived(26);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index dea642f..e73457b 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -161,6 +161,7 @@
   data = [
     "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_button_tests.m.js",
     "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_icon_button_tests.m.js",
+    "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_radio_button_test.m.js",
     "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toast_test.m.js",
     "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_view_manager_test.m.js",
     "$root_gen_dir/chrome/test/data/webui/mock_timer.m.js",
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn
index a093bf9d..89c0b9b 100644
--- a/chrome/test/data/webui/cr_elements/BUILD.gn
+++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -11,6 +11,7 @@
     "cr_icon_button_tests.js",
     "cr_icon_button_focus_tests.js",
     "cr_input_test.js",
+    "cr_radio_button_test.js",
     "cr_toast_test.js",
     "cr_toggle_test.js",
     "cr_view_manager_test.js",
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 080800d..caca528d 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -488,7 +488,6 @@
 
   /** @override */
   extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([
-    '../test_util.js',
     'cr_radio_button_test.js',
   ]),
 };
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
index ae60676..2c6d0d7c 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
@@ -66,6 +66,18 @@
 });
 
 // eslint-disable-next-line no-var
+var CrElementsRadioButtonV3Test = class extends CrElementsV3BrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://test?module=cr_elements/cr_radio_button_test.m.js';
+  }
+};
+
+TEST_F('CrElementsRadioButtonV3Test', 'All', function() {
+  mocha.run();
+});
+
+// eslint-disable-next-line no-var
 var CrElementsToastV3Test = class extends CrElementsV3BrowserTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/cr_elements/cr_radio_button_test.js b/chrome/test/data/webui/cr_elements/cr_radio_button_test.js
index d6ea3a8..80b86378 100644
--- a/chrome/test/data/webui/cr_elements/cr_radio_button_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_radio_button_test.js
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
+// clang-format on
+
 suite('cr-radio-button', function() {
   let radioButton;
 
diff --git a/chrome/test/data/webui/print_preview/destination_store_test.js b/chrome/test/data/webui/print_preview/destination_store_test.js
index 5c308f5a..f206e58 100644
--- a/chrome/test/data/webui/print_preview/destination_store_test.js
+++ b/chrome/test/data/webui/print_preview/destination_store_test.js
@@ -16,6 +16,7 @@
     UnreachableRecentCloudPrinter: 'unreachable recent cloud printer',
     RecentSaveAsPdf: 'recent save as pdf',
     MultipleRecentDestinationsAccounts: 'multiple recent destinations accounts',
+    LoadAndSelectDestination: 'select loaded destination',
   };
 
   const suiteName = 'DestinationStoreTest';
@@ -402,6 +403,65 @@
             loadedPrintersAccount2[0].id);
       });
     });
+
+    /**
+     * Tests that if the user has a single valid recent destination the
+     * destination is automatically reselected.
+     */
+    test(assert(TestNames.LoadAndSelectDestination), function() {
+      destinations = print_preview_test_utils.getDestinations(
+          nativeLayer, localDestinations);
+      initialSettings.printerName = '';
+      const id1 = 'ID1';
+      const name1 = 'One';
+      let destination = null;
+
+      return setInitialSettings()
+          .then(function(args) {
+            assertEquals(
+                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
+                args.destinationId);
+            assertEquals(print_preview.PrinterType.LOCAL, args.type);
+            assertEquals(
+                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
+                destinationStore.selectedDestination.id);
+            // Update destination with ID 1 so that it has policies.
+            const localDestinationInfo = {deviceName: id1, printerName: name1};
+            if (cr.isChromeOS) {
+              localDestinationInfo.policies = {
+                allowedColorModes: 0x1,
+                defaultColorMode: 0x1
+              };
+            }
+            nativeLayer.setLocalDestinationCapabilities({
+              printer: localDestinationInfo,
+              capabilities: print_preview_test_utils.getCddTemplate(id1, name1),
+            });
+            destinationStore.startLoadAllDestinations();
+            return nativeLayer.whenCalled('getPrinters');
+          })
+          .then(() => {
+            destination =
+                destinationStore.destinations().find(d => d.id === id1);
+            // No capabilities or policies yet.
+            assertFalse(!!destination.capabilities);
+            if (cr.isChromeOS) {
+              assertEquals(null, destination.policies);
+            }
+            destinationStore.selectDestination(destination);
+            return nativeLayer.whenCalled('getPrinterCapabilities');
+          })
+          .then(() => {
+            assertEquals(destination, destinationStore.selectedDestination);
+            // Capabilities are updated.
+            assertTrue(!!destination.capabilities);
+            // TODO (https://crbug.com/998103): Ensure that the destination
+            // policies are actually set.
+            if (cr.isChromeOS) {
+              assertEquals(null, destination.policies);
+            }
+          });
+    });
   });
 
   return {
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 ea088e16..86e949a 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
@@ -246,18 +246,24 @@
     const origin = cr.isChromeOS ? print_preview.DestinationOrigin.CROS :
                                    print_preview.DestinationOrigin.LOCAL;
     // Five destinations. FooDevice is the system default.
-    [{id: 'ID1', name: 'One'}, {id: 'ID2', name: 'Two'},
-     {id: 'ID3', name: 'Three'}, {id: 'ID4', name: 'Four'},
-     {id: 'FooDevice', name: 'FooName'}]
+    [{deviceName: 'ID1', printerName: 'One'},
+     {deviceName: 'ID2', printerName: 'Two'},
+     {deviceName: 'ID3', printerName: 'Three'},
+     {deviceName: 'ID4', printerName: 'Four'},
+     {deviceName: 'FooDevice', printerName: 'FooName'}]
         .forEach((info, index) => {
           const destination = new print_preview.Destination(
-              info.id, print_preview.DestinationType.LOCAL, origin, info.name,
+              info.deviceName, print_preview.DestinationType.LOCAL, origin,
+              info.printerName,
               print_preview.DestinationConnectionStatus.ONLINE);
           if (nativeLayer) {
-            nativeLayer.setLocalDestinationCapabilities(
-                print_preview_test_utils.getCddTemplate(info.id, info.name));
+            nativeLayer.setLocalDestinationCapabilities({
+              printer: info,
+              capabilities: print_preview_test_utils.getCddTemplate(
+                  info.deviceName, info.printerName),
+            });
           }
-          localDestinations.push({printerName: info.name, deviceName: info.id});
+          localDestinations.push(info);
           destinations.push(destination);
         });
     return destinations;
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index 0b8ce81..e90dcf0 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -697,6 +697,12 @@
           destination_store_test.TestNames.KioskModeSelectsFirstPrinter);
     });
 
+TEST_F(
+    'PrintPreviewDestinationStoreTest', 'LoadAndSelectDestination', function() {
+      this.runMochaTest(
+          destination_store_test.TestNames.LoadAndSelectDestination);
+    });
+
 GEN('#if defined(OS_CHROMEOS)');
 TEST_F('PrintPreviewDestinationStoreTest', 'NoPrintersShowsError', function() {
   this.runMochaTest(destination_store_test.TestNames.NoPrintersShowsError);
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
index 9a2ceb1..e24ddc5b 100644
--- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -51,6 +51,7 @@
       const button = crostiniPage.$$('#enable');
       assertTrue(!!button);
       assertFalse(!!crostiniPage.$$('.subpage-arrow'));
+      assertFalse(button.disabled);
 
       button.click();
       Polymer.dom.flush();
@@ -60,6 +61,26 @@
 
       assertTrue(!!crostiniPage.$$('.subpage-arrow'));
     });
+
+    test('ButtonDisabledDuringInstall', function() {
+      const button = crostiniPage.$$('#enable');
+      assertTrue(!!button);
+      return flushAsync()
+          .then(() => {
+            assertFalse(button.disabled);
+            cr.webUIListenerCallback('crostini-installer-status-changed', true);
+            flushAsync();
+          })
+          .then(() => {
+            assertTrue(button.disabled);
+            cr.webUIListenerCallback(
+                'crostini-installer-status-changed', false);
+            flushAsync();
+          })
+          .then(() => {
+            assertFalse(button.disabled);
+          });
+    });
   });
 
   suite('SubPageDetails', function() {
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index 4c3d0c1..5a61f3e 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -225,8 +225,7 @@
   }
 };
 
-// TODO(crbug.com/962114): Disabled due to flakes on linux-chromeos-rel.
-TEST_F('OSSettingsCrostiniPageTest', 'DISABLED_AllJsTests', () => {
+TEST_F('OSSettingsCrostiniPageTest', 'All', () => {
   mocha.run();
 });
 
diff --git a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
index 293e133..238ee56 100644
--- a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
+++ b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
@@ -20,6 +20,7 @@
       'getNumCookiesString',
       'reloadCookies',
       'removeCookie',
+      'removeThirdPartyCookies',
     ]);
 
     /** @private {?CookieList} */
@@ -99,4 +100,9 @@
   removeCookie(path) {
     this.methodCalled('removeCookie', path);
   }
+
+  /** @override */
+  removeThirdPartyCookies() {
+    this.methodCalled('removeThirdPartyCookies');
+  }
 }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 632274a..8def6ff 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-12404.0.0
\ No newline at end of file
+12465.0.0
\ No newline at end of file
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn
index 3a7beb2d..1fcd2d3 100644
--- a/components/browsing_data/core/BUILD.gn
+++ b/components/browsing_data/core/BUILD.gn
@@ -23,6 +23,8 @@
     "counters/passwords_counter.h",
     "counters/sync_tracker.cc",
     "counters/sync_tracker.h",
+    "features.cc",
+    "features.h",
     "history_notice_utils.cc",
     "history_notice_utils.h",
     "pref_names.cc",
diff --git a/components/browsing_data/core/features.cc b/components/browsing_data/core/features.cc
new file mode 100644
index 0000000..e57c1192
--- /dev/null
+++ b/components/browsing_data/core/features.cc
@@ -0,0 +1,14 @@
+// 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/browsing_data/core/features.h"
+
+namespace browsing_data {
+namespace features {
+
+const base::Feature kEnableRemovingAllThirdPartyCookies{
+    "EnableRemovingAllThirdPartyCookies", base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace features
+}  // namespace browsing_data
diff --git a/components/browsing_data/core/features.h b/components/browsing_data/core/features.h
new file mode 100644
index 0000000..6543d408
--- /dev/null
+++ b/components/browsing_data/core/features.h
@@ -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.
+
+#ifndef COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
+#define COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace browsing_data {
+namespace features {
+
+// Enable removal of all third-party cookies and site data.
+extern const base::Feature kEnableRemovingAllThirdPartyCookies;
+
+}  // namespace features
+}  // namespace browsing_data
+
+#endif  // COMPONENTS_BROWSING_DATA_CORE_FEATURES_H_
diff --git a/components/language/content/browser/test_utils.cc b/components/language/content/browser/test_utils.cc
index ca19235..e922745 100644
--- a/components/language/content/browser/test_utils.cc
+++ b/components/language/content/browser/test_utils.cc
@@ -39,8 +39,8 @@
 
 void MockIpGeoLocationProvider::CreateGeolocation(
     const net::MutablePartialNetworkTrafficAnnotationTag& /* unused */,
-    device::mojom::GeolocationRequest request) {
-  mock_geo_location_->BindGeoLocation(std::move(request));
+    mojo::PendingReceiver<device::mojom::Geolocation> receiver) {
+  mock_geo_location_->BindGeoLocation(std::move(receiver));
 }
 
 }  // namespace language
diff --git a/components/language/content/browser/test_utils.h b/components/language/content/browser/test_utils.h
index 74310cab..9755c61 100644
--- a/components/language/content/browser/test_utils.h
+++ b/components/language/content/browser/test_utils.h
@@ -51,7 +51,7 @@
 
   void CreateGeolocation(
       const net::MutablePartialNetworkTrafficAnnotationTag& /* unused */,
-      device::mojom::GeolocationRequest request) override;
+      mojo::PendingReceiver<device::mojom::Geolocation> receiver) override;
 
  private:
   MockGeoLocation* mock_geo_location_;
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc
index 12cb741..707c48df 100644
--- a/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -190,7 +190,9 @@
   }
   if (CanShowInterstitial(reason, reused_password_account_type,
                           main_frame_url)) {
-    username_ = username;
+    username_for_last_shown_warning_ = username;
+    reused_password_account_type_for_last_shown_warning_ =
+        reused_password_account_type;
     ShowInterstitial(web_contents, reused_password_account_type);
   }
 }
@@ -251,7 +253,8 @@
 
     if (ShouldShowModalWarning(request->trigger_type(), password_type,
                                response->verdict_type())) {
-      username_ = request->username();
+      username_for_last_shown_warning_ = request->username();
+      reused_password_account_type_for_last_shown_warning_ = password_type;
       ShowModalWarning(request->web_contents(), request->request_outcome(),
                        response->verdict_type(), response->verdict_token(),
                        password_type);
@@ -364,7 +367,7 @@
             safe_browsing::LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
         IsSupportedPasswordTypeForModalWarning(
             GetPasswordProtectionReusedPasswordAccountType(
-                request->password_type(), username()))) {
+                request->password_type(), username_for_last_shown_warning()))) {
       return std::make_unique<PasswordProtectionNavigationThrottle>(
           navigation_handle, request, /*is_warning_showing=*/false);
     }
diff --git a/components/safe_browsing/password_protection/password_protection_service.h b/components/safe_browsing/password_protection/password_protection_service.h
index da0b1b6..45247a0 100644
--- a/components/safe_browsing/password_protection/password_protection_service.h
+++ b/components/safe_browsing/password_protection/password_protection_service.h
@@ -203,8 +203,7 @@
   // Converts from password_manager::metrics_util::PasswordType
   // to PasswordReuseEvent::ReusedPasswordAccountType. |username| is only
   // used if |password_type| is OTHER_GAIA_PASSWORD because it needs to be
-  // compared to the list of signed in accounts. If |username| is empty, it
-  // uses |username_|.
+  // compared to the list of signed in accounts.
   ReusedPasswordAccountType GetPasswordProtectionReusedPasswordAccountType(
       PasswordType password_type,
       const std::string& username) const;
@@ -221,9 +220,26 @@
   bool IsSupportedPasswordTypeForModalWarning(
       ReusedPasswordAccountType password_type) const;
 
-  const std::string& username() const { return username_; }
+  const ReusedPasswordAccountType&
+  reused_password_account_type_for_last_shown_warning() const {
+    return reused_password_account_type_for_last_shown_warning_;
+  }
 #if defined(UNIT_TEST)
-  void set_username(const std::string& username) { username_ = username; }
+  void set_reused_password_account_type_for_last_shown_warning(
+      ReusedPasswordAccountType
+          reused_password_account_type_for_last_shown_warning) {
+    reused_password_account_type_for_last_shown_warning_ =
+        reused_password_account_type_for_last_shown_warning;
+  }
+#endif
+
+  const std::string& username_for_last_shown_warning() const {
+    return username_for_last_shown_warning_;
+  }
+#if defined(UNIT_TEST)
+  void set_username_for_last_shown_warning(const std::string& username) {
+    username_for_last_shown_warning_ = username;
+  }
 #endif
 
   virtual AccountInfo GetAccountInfo() const = 0;
@@ -388,10 +404,14 @@
       service_manager::InterfaceProvider* provider,
       mojom::PhishingDetectorPtr* phishing_detector);
 
-  // TODO(bdea): Store ReusedPasswordAccountType here instead.
   // The username of the account which password has been reused on. It is only
   // set once a modal warning or interstitial is verified to be shown.
-  std::string username_ = "";
+  std::string username_for_last_shown_warning_ = "";
+
+  // The last ReusedPasswordAccountType that was shown a warning or
+  // interstitial.
+  ReusedPasswordAccountType
+      reused_password_account_type_for_last_shown_warning_;
 
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
 
diff --git a/components/signin/core/browser/consistency_cookie_manager_unittest.cc b/components/signin/core/browser/consistency_cookie_manager_unittest.cc
index 2c386dc0..b0cbd10 100644
--- a/components/signin/core/browser/consistency_cookie_manager_unittest.cc
+++ b/components/signin/core/browser/consistency_cookie_manager_unittest.cc
@@ -30,15 +30,14 @@
       net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
   return arg.Name() == "CHROME_ID_CONSISTENCY_STATE" && arg.Value() == value &&
          arg.IncludeForRequestURL(GaiaUrls::GetInstance()->gaia_url(),
-                                  cookie_options) ==
-             net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+                                  cookie_options)
+             .IsInclude();
 }
 
 MATCHER(SetPermittedInContext, "") {
   const net::CanonicalCookie& cookie = testing::get<0>(arg);
   const net::CookieOptions& cookie_options = testing::get<1>(arg);
-  return cookie.IsSetPermittedInContext(cookie_options) ==
-         net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  return cookie.IsSetPermittedInContext(cookie_options).IsInclude();
 }
 
 class MockCookieManager
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
index e5a3146..6c4607cc 100644
--- a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
+++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -196,8 +196,10 @@
       cookie_manager->SetCanonicalCookie(
           cookie, "https", options,
           mojo::WrapCallbackWithDefaultInvokeIfNotRun(
-              std::move(callback), net::CanonicalCookie::CookieInclusionStatus::
-                                       EXCLUDE_UNKNOWN_ERROR));
+              std::move(callback),
+              net::CanonicalCookie::CookieInclusionStatus(
+                  net::CanonicalCookie::CookieInclusionStatus::
+                      EXCLUDE_UNKNOWN_ERROR)));
     } else {
       LOG(ERROR) << "Duplicate cookie found: " << cookie.Name() << " "
                  << cookie.Domain();
@@ -210,8 +212,7 @@
     const std::string& cookie_domain,
     net::CanonicalCookie::CookieInclusionStatus status) {
   cookies_to_set_.erase(std::make_pair(cookie_name, cookie_domain));
-  bool success =
-      (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  bool success = status.IsInclude();
   if (!success) {
     LOG(ERROR) << "Failed to set cookie " << cookie_name
                << " for domain=" << cookie_domain << ".";
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
index b1c2fe04..3fb516a 100644
--- a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
+++ b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -139,7 +139,7 @@
     const std::string&,
     const net::CookieOptions&,
     network::mojom::CookieManager::SetCanonicalCookieCallback callback) {
-  std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus());
 }
 
 class MockCookieManager
diff --git a/components/ui_devtools/BUILD.gn b/components/ui_devtools/BUILD.gn
index 958af71..b01fc30 100644
--- a/components/ui_devtools/BUILD.gn
+++ b/components/ui_devtools/BUILD.gn
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/buildflag_header.gni")
+import("//components/ui_devtools/devtools.gni")
+
 _inspector_protocol = "//third_party/inspector_protocol"
 import("$_inspector_protocol/inspector_protocol.gni")
 
@@ -60,6 +63,11 @@
   outputs = _protocol_generated
 }
 
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+  flags = [ "USE_VIZ_DEVTOOLS=$use_viz_devtools" ]
+}
+
 component("ui_devtools") {
   sources = rebase_path(_protocol_generated, ".", target_gen_dir)
   sources += [
@@ -111,6 +119,7 @@
   ]
 
   public_deps = [
+    ":buildflags",
     "//services/network/public/cpp",
     "//services/network/public/mojom",
     "//services/service_manager/public/cpp",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index ab963de..1707297 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -42,11 +42,6 @@
 const base::Feature kRecordSkPicture{"RecordSkPicture",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
-bool IsSurfaceSynchronizationEnabled() {
-  // TODO(crbug.com/985009): Delete function after all callers are removed.
-  return true;
-}
-
 bool IsVizDisplayCompositorEnabled() {
 #if defined(OS_MACOSX) || defined(OS_WIN)
   // We can't remove the feature switch yet because OOP-D isn't enabled on all
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index a4e8bc7..337dd335 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -17,7 +17,6 @@
 VIZ_COMMON_EXPORT extern const base::Feature kRecordSkPicture;
 VIZ_COMMON_EXPORT extern const base::Feature kVizDisplayCompositor;
 
-VIZ_COMMON_EXPORT bool IsSurfaceSynchronizationEnabled();
 VIZ_COMMON_EXPORT bool IsVizDisplayCompositorEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingSurfaceLayerEnabled();
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn
index 1be7501..fe68a699 100644
--- a/components/viz/host/BUILD.gn
+++ b/components/viz/host/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//components/ui_devtools/devtools.gni")
 import("//components/viz/viz.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
@@ -41,6 +40,7 @@
 
   deps = [
     "//base",
+    "//components/ui_devtools:buildflags",
     "//components/viz/common",
     "//gpu/ipc/client",
     "//gpu/ipc/common",
@@ -64,10 +64,6 @@
   if (is_mac) {
     deps += [ "//ui/accelerated_widget_mac" ]
   }
-
-  if (use_viz_devtools) {
-    defines += [ "USE_VIZ_DEVTOOLS" ]
-  }
 }
 
 viz_source_set("unit_tests") {
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS
index fd63620..e135e148 100644
--- a/components/viz/host/DEPS
+++ b/components/viz/host/DEPS
@@ -2,6 +2,7 @@
 
 include_rules = [
   "+components/discardable_memory/public/mojom",
+  "+components/ui_devtools/buildflags.h",
   "+components/viz/common/features.h",
   "-components/viz/common/switches.h",
   "+media/base/video_types.h",
diff --git a/components/viz/host/gpu_host_impl.cc b/components/viz/host/gpu_host_impl.cc
index 6ef2f1f..b2442ed8 100644
--- a/components/viz/host/gpu_host_impl.cc
+++ b/components/viz/host/gpu_host_impl.cc
@@ -193,7 +193,7 @@
   viz_main_->CreateFrameSinkManager(std::move(params));
 }
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 void GpuHostImpl::ConnectVizDevTools(mojom::VizDevToolsParamsPtr params) {
   viz_main_->CreateVizDevTools(std::move(params));
 }
diff --git a/components/viz/host/gpu_host_impl.h b/components/viz/host/gpu_host_impl.h
index ad8fce1d..c3c80f5c 100644
--- a/components/viz/host/gpu_host_impl.h
+++ b/components/viz/host/gpu_host_impl.h
@@ -20,6 +20,7 @@
 #include "base/sequence_checker.h"
 #include "build/build_config.h"
 #include "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom.h"
+#include "components/ui_devtools/buildflags.h"
 #include "components/viz/host/viz_host_export.h"
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/config/gpu_domain_guilt.h"
@@ -152,7 +153,7 @@
   void ConnectFrameSinkManager(mojom::FrameSinkManagerRequest request,
                                mojom::FrameSinkManagerClientPtrInfo client);
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   // Connects to Viz DevTools running in the Viz service.
   void ConnectVizDevTools(mojom::VizDevToolsParamsPtr params);
 #endif
diff --git a/components/viz/service/main/BUILD.gn b/components/viz/service/main/BUILD.gn
index 91aca4f..e4f4444f 100644
--- a/components/viz/service/main/BUILD.gn
+++ b/components/viz/service/main/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import("//build/config/ui.gni")
-import("//components/ui_devtools/devtools.gni")
 import("//testing/test.gni")
 
 source_set("main") {
@@ -50,8 +49,4 @@
   if (is_chromeos) {
     deps += [ "//media/gpu" ]
   }
-
-  if (use_viz_devtools) {
-    defines += [ "USE_VIZ_DEVTOOLS" ]
-  }
 }
diff --git a/components/viz/service/main/viz_compositor_thread_runner.h b/components/viz/service/main/viz_compositor_thread_runner.h
index 7909be3..b45c4517 100644
--- a/components/viz/service/main/viz_compositor_thread_runner.h
+++ b/components/viz/service/main/viz_compositor_thread_runner.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_VIZ_SERVICE_MAIN_VIZ_COMPOSITOR_THREAD_RUNNER_H_
 
 #include "base/callback.h"
+#include "components/ui_devtools/buildflags.h"
 #include "services/viz/privileged/mojom/viz_main.mojom.h"
 
 namespace base {
@@ -42,7 +43,7 @@
       gpu::CommandBufferTaskExecutor* task_executor,
       GpuServiceImpl* gpu_service) = 0;
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   virtual void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) = 0;
 #endif
 
diff --git a/components/viz/service/main/viz_compositor_thread_runner_impl.cc b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
index 316b503..59b6ff4a 100644
--- a/components/viz/service/main/viz_compositor_thread_runner_impl.cc
+++ b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -29,7 +29,7 @@
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
 #include "ui/gfx/switches.h"
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 #include "components/ui_devtools/css_agent.h"
 #include "components/ui_devtools/devtools_server.h"
 #include "components/ui_devtools/viz/dom_agent_viz.h"
@@ -119,7 +119,7 @@
                                 base::Unretained(gpu_service)));
 }
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 void VizCompositorThreadRunnerImpl::CreateVizDevTools(
     mojom::VizDevToolsParamsPtr params) {
   // It is safe to use Unretained(this) because |this| owns the |task_runner_|,
@@ -198,13 +198,13 @@
       mojom::FrameSinkManagerClientPtr(
           std::move(params->frame_sink_manager_client)));
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   if (pending_viz_dev_tools_params_)
     InitVizDevToolsOnCompositorThread(std::move(pending_viz_dev_tools_params_));
 #endif
 }
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 void VizCompositorThreadRunnerImpl::CreateVizDevToolsOnCompositorThread(
     mojom::VizDevToolsParamsPtr params) {
   if (!frame_sink_manager_) {
@@ -250,7 +250,7 @@
         server_shared_bitmap_manager_.get());
   }
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   devtools_server_.reset();
 #endif
   frame_sink_manager_.reset();
diff --git a/components/viz/service/main/viz_compositor_thread_runner_impl.h b/components/viz/service/main/viz_compositor_thread_runner_impl.h
index 3a822d8..2cbcce4 100644
--- a/components/viz/service/main/viz_compositor_thread_runner_impl.h
+++ b/components/viz/service/main/viz_compositor_thread_runner_impl.h
@@ -11,6 +11,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
+#include "components/ui_devtools/buildflags.h"
 #include "components/viz/service/main/viz_compositor_thread_runner.h"
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 
@@ -49,7 +50,7 @@
   void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params,
                               gpu::CommandBufferTaskExecutor* task_executor,
                               GpuServiceImpl* gpu_service) override;
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) override;
 #endif
   void CleanupForShutdown(base::OnceClosure cleanup_finished_callback) override;
@@ -59,7 +60,7 @@
       mojom::FrameSinkManagerParamsPtr params,
       gpu::CommandBufferTaskExecutor* task_executor,
       GpuServiceImpl* gpu_service);
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   void CreateVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
   void InitVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
 #endif
@@ -70,7 +71,7 @@
   std::unique_ptr<ServerSharedBitmapManager> server_shared_bitmap_manager_;
   std::unique_ptr<OutputSurfaceProvider> output_surface_provider_;
   std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_;
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   std::unique_ptr<ui_devtools::UiDevToolsServer> devtools_server_;
 
   // If the FrameSinkManager is not ready yet, then we stash the pending
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index 8bd77bc4..36760c6 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -15,6 +15,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "build/build_config.h"
+#include "components/ui_devtools/buildflags.h"
 #include "components/viz/service/gl/gpu_service_impl.h"
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/config/gpu_finch_features.h"
@@ -275,7 +276,7 @@
 }
 
 void VizMainImpl::CreateVizDevTools(mojom::VizDevToolsParamsPtr params) {
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   viz_compositor_thread_runner_->CreateVizDevTools(std::move(params));
 #endif
 }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 6a856cba..5adeccac 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2670,7 +2670,6 @@
       "gpu/viz_devtools_connector.cc",
       "gpu/viz_devtools_connector.h",
     ]
-    defines += [ "USE_VIZ_DEVTOOLS" ]
   }
 
   if (use_mpris) {
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 9db52a1..b64cb71 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -315,6 +315,11 @@
   RunHtmlTest(FILE_PATH_LITERAL("area-crash.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityAreaSerializationCrash) {
+  RunHtmlTest(FILE_PATH_LITERAL("area-serialization-crash.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAName) {
   RunHtmlTest(FILE_PATH_LITERAL("a-name.html"));
 }
diff --git a/content/browser/browsing_data/browsing_data_test_utils.cc b/content/browser/browsing_data/browsing_data_test_utils.cc
index 3f80d1e..8d9f84e 100644
--- a/content/browser/browsing_data/browsing_data_test_utils.cc
+++ b/content/browser/browsing_data/browsing_data_test_utils.cc
@@ -43,7 +43,7 @@
                                false, same_site, net::COOKIE_PRIORITY_LOW),
           "https", options,
           base::BindLambdaForTesting([&](CookieInclusionStatus result) {
-            result_out = (result == CookieInclusionStatus::INCLUDE);
+            result_out = result.IsInclude();
             run_loop.Quit();
           }));
   run_loop.Run();
diff --git a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
index 100c149..f6156fa 100644
--- a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
+++ b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -306,9 +306,9 @@
   // Callback handler for AddCookie().
   static void AddCookieCallback(
       base::OnceClosure callback,
-      net::CanonicalCookie::CookieInclusionStatus success) {
+      net::CanonicalCookie::CookieInclusionStatus status) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    ASSERT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE, success);
+    ASSERT_TRUE(status.IsInclude());
     std::move(callback).Run();
   }
 
diff --git a/content/browser/browsing_data/same_site_data_remover_impl_unittest.cc b/content/browser/browsing_data/same_site_data_remover_impl_unittest.cc
index 227f7c82b..1cf5359 100644
--- a/content/browser/browsing_data/same_site_data_remover_impl_unittest.cc
+++ b/content/browser/browsing_data/same_site_data_remover_impl_unittest.cc
@@ -208,8 +208,7 @@
       "https", options,
       base::BindLambdaForTesting(
           [&](net::CanonicalCookie::CookieInclusionStatus result) {
-            result_out = (result ==
-                          net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+            result_out = result.IsInclude();
             run_loop1.Quit();
           }));
   run_loop1.Run();
@@ -227,8 +226,7 @@
       "https", options,
       base::BindLambdaForTesting(
           [&](net::CanonicalCookie::CookieInclusionStatus result) {
-            result_out = (result ==
-                          net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+            result_out = result.IsInclude();
             run_loop2.Quit();
           }));
   run_loop2.Run();
diff --git a/content/browser/cookie_store/cookie_change_subscription.cc b/content/browser/cookie_store/cookie_change_subscription.cc
index 9ef5974e..4d61fbf 100644
--- a/content/browser/cookie_store/cookie_change_subscription.cc
+++ b/content/browser/cookie_store/cookie_change_subscription.cc
@@ -174,8 +174,7 @@
   net_options.set_same_site_cookie_context(
       net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
 
-  return cookie.IncludeForRequestURL(url_, net_options) ==
-         net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  return cookie.IncludeForRequestURL(url_, net_options).IsInclude();
 }
 
 }  // namespace content
diff --git a/content/browser/cookie_store/cookie_store_manager_unittest.cc b/content/browser/cookie_store/cookie_store_manager_unittest.cc
index a2c8653..2a5b2d9 100644
--- a/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -328,9 +328,8 @@
     cookie_manager_->SetCanonicalCookie(
         cookie, "https", options,
         base::BindLambdaForTesting(
-            [&](net::CanonicalCookie::CookieInclusionStatus service_success) {
-              success = (service_success ==
-                         net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+            [&](net::CanonicalCookie::CookieInclusionStatus service_status) {
+              success = service_status.IsInclude();
               run_loop.Quit();
             }));
     run_loop.Run();
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 7b8fffa2..97d492e 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -569,87 +569,120 @@
   return signed_exchange_errors;
 }
 
+// TODO(crbug.com/993843): Make this return an array of reasons, not just the
+// first one.
 base::Optional<Network::SetCookieBlockedReason>
 GetProtocolBlockedSetCookieReason(
     net::CanonicalCookie::CookieInclusionStatus status) {
-  switch (status) {
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
-      return Network::SetCookieBlockedReasonEnum::SecureOnly;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
-      return Network::SetCookieBlockedReasonEnum::SameSiteStrict;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
-      return Network::SetCookieBlockedReasonEnum::SameSiteLax;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED:
-      return Network::SetCookieBlockedReasonEnum::SameSiteExtended;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-      return Network::SetCookieBlockedReasonEnum::
-          SameSiteUnspecifiedTreatedAsLax;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE:
-      return Network::SetCookieBlockedReasonEnum::SameSiteNoneInsecure;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
-      return Network::SetCookieBlockedReasonEnum::UserPreferences;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
-      return Network::SetCookieBlockedReasonEnum::SyntaxError;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_NONCOOKIEABLE_SCHEME:
-      return Network::SetCookieBlockedReasonEnum::SchemeNotSupported;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
-      return Network::SetCookieBlockedReasonEnum::OverwriteSecure;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
-      return Network::SetCookieBlockedReasonEnum::InvalidDomain;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
-      return Network::SetCookieBlockedReasonEnum::InvalidPrefix;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
-      return Network::SetCookieBlockedReasonEnum::UnknownError;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_OVERWRITE_HTTP_ONLY:
-    case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-      return base::nullopt;
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) {
+    return Network::SetCookieBlockedReasonEnum::SecureOnly;
   }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_STRICT)) {
+    return Network::SetCookieBlockedReasonEnum::SameSiteStrict;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) {
+    return Network::SetCookieBlockedReasonEnum::SameSiteLax;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_EXTENDED)) {
+    return Network::SetCookieBlockedReasonEnum::SameSiteExtended;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::
+              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
+    return Network::SetCookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_NONE_INSECURE)) {
+    return Network::SetCookieBlockedReasonEnum::SameSiteNoneInsecure;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_USER_PREFERENCES)) {
+    return Network::SetCookieBlockedReasonEnum::UserPreferences;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_FAILURE_TO_STORE)) {
+    return Network::SetCookieBlockedReasonEnum::SyntaxError;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_NONCOOKIEABLE_SCHEME)) {
+    return Network::SetCookieBlockedReasonEnum::SchemeNotSupported;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_OVERWRITE_SECURE)) {
+    return Network::SetCookieBlockedReasonEnum::OverwriteSecure;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_INVALID_DOMAIN)) {
+    return Network::SetCookieBlockedReasonEnum::InvalidDomain;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_INVALID_PREFIX)) {
+    return Network::SetCookieBlockedReasonEnum::InvalidPrefix;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) {
+    return Network::SetCookieBlockedReasonEnum::UnknownError;
+  }
+
+  // EXCLUDE_HTTP_ONLY, EXCLUDE_NOT_ON_PATH, EXCLUDE_DOMAIN_MISMATCH,
+  // EXCLUDE_OVERWRITE_HTTP_ONLY, or no exclusion reasons.
+  return base::nullopt;
 }
 
+// TODO(crbug.com/993843): Make this return an array of reasons, not just the
+// first one.
 base::Optional<Network::CookieBlockedReason> GetProtocolBlockedCookieReason(
     net::CanonicalCookie::CookieInclusionStatus status) {
-  switch (status) {
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
-      return Network::CookieBlockedReasonEnum::SecureOnly;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
-      return Network::CookieBlockedReasonEnum::NotOnPath;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
-      return Network::CookieBlockedReasonEnum::DomainMismatch;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
-      return Network::CookieBlockedReasonEnum::SameSiteStrict;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
-      return Network::CookieBlockedReasonEnum::SameSiteLax;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED:
-      return Network::CookieBlockedReasonEnum::SameSiteExtended;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-      return Network::CookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE:
-      return Network::CookieBlockedReasonEnum::SameSiteNoneInsecure;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
-      return Network::CookieBlockedReasonEnum::UserPreferences;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
-      return Network::CookieBlockedReasonEnum::UnknownError;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_NONCOOKIEABLE_SCHEME:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_OVERWRITE_HTTP_ONLY:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
-    case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-      return base::nullopt;
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) {
+    return Network::CookieBlockedReasonEnum::SecureOnly;
   }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH)) {
+    return Network::CookieBlockedReasonEnum::NotOnPath;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_DOMAIN_MISMATCH)) {
+    return Network::CookieBlockedReasonEnum::DomainMismatch;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_STRICT)) {
+    return Network::CookieBlockedReasonEnum::SameSiteStrict;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)) {
+    return Network::CookieBlockedReasonEnum::SameSiteLax;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_EXTENDED)) {
+    return Network::CookieBlockedReasonEnum::SameSiteExtended;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::
+              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX)) {
+    return Network::CookieBlockedReasonEnum::SameSiteUnspecifiedTreatedAsLax;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_SAMESITE_NONE_INSECURE)) {
+    return Network::CookieBlockedReasonEnum::SameSiteNoneInsecure;
+  }
+  if (status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_USER_PREFERENCES)) {
+    return Network::CookieBlockedReasonEnum::UserPreferences;
+  }
+  if (status.HasExclusionReason(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)) {
+    return Network::CookieBlockedReasonEnum::UnknownError;
+  }
+
+  // EXCLUDE_FAILURE_TO_STORE, EXCLUDE_NONCOOKIEABLE_SCHEME,
+  // EXCLUDE_OVERWRITE_SECURE, EXCLUDE_INVALID_DOMAIN, EXCLUDE_INVALID_PREFIX,
+  // EXCLUDE_OVERWRITE_HTTP_ONLY, EXCLUDE_HTTP_ONLY, or no exclusion reasons.
+  return base::nullopt;
 }
 
 std::unique_ptr<Array<Network::BlockedSetCookieWithReason>>
@@ -680,28 +713,7 @@
   std::unique_ptr<Array<Network::BlockedCookieWithReason>> protocol_list =
       std::make_unique<Array<Network::BlockedCookieWithReason>>();
 
-  bool samesite_by_default_enabled =
-      net::cookie_util::IsSameSiteByDefaultCookiesEnabled();
-  bool must_be_secure_enabled =
-      net::cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled();
-
   for (const net::CookieWithStatus& cookie : net_list) {
-    // These CookieInclusionStatus values will be passed to us from network
-    // service even if the cookies were actually included - the actual
-    // inclusion depends on these flags. If the flags are disabled, then don't
-    // forward them to the frontend because they were not actually blocked.
-    if (!samesite_by_default_enabled) {
-      if (cookie.status == net::CanonicalCookie::CookieInclusionStatus::
-                               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
-        continue;
-      }
-      if (!must_be_secure_enabled &&
-          cookie.status == net::CanonicalCookie::CookieInclusionStatus::
-                               EXCLUDE_SAMESITE_NONE_INSECURE) {
-        continue;
-      }
-    }
-
     base::Optional<Network::CookieBlockedReason> blocked_reason =
         GetProtocolBlockedCookieReason(cookie.status);
     if (!blocked_reason.has_value())
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 67d9773..0acd629 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -7301,10 +7301,10 @@
 
 void RenderFrameHostImpl::AddSameSiteCookieDeprecationMessage(
     const std::string& cookie_url,
-    net::CanonicalCookie::CookieInclusionStatus status) {
+    net::CanonicalCookie::CookieInclusionStatus::WarningReason warning) {
   std::string deprecation_message;
-  if (status == net::CanonicalCookie::CookieInclusionStatus::
-                    EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
+  if (warning == net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+                     WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT) {
     if (!ShouldAddCookieSameSiteDeprecationMessage(
             cookie_url, &cookie_no_samesite_deprecation_url_hashes_)) {
       return;
@@ -7318,9 +7318,8 @@
         "Application>Storage>Cookies and see more details at "
         "https://www.chromestatus.com/feature/5088147346030592 and "
         "https://www.chromestatus.com/feature/5633521622188032.";
-  }
-  if (status == net::CanonicalCookie::CookieInclusionStatus::
-                    EXCLUDE_SAMESITE_NONE_INSECURE) {
+  } else if (warning == net::CanonicalCookie::CookieInclusionStatus::
+                            WarningReason::WARN_SAMESITE_NONE_INSECURE) {
     if (!ShouldAddCookieSameSiteDeprecationMessage(
             cookie_url,
             &cookie_samesite_none_insecure_deprecation_url_hashes_)) {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index f225592..3f4af7d 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1000,7 +1000,7 @@
   // TODO(crbug.com/977040): Remove when no longer needed.
   void AddSameSiteCookieDeprecationMessage(
       const std::string& cookie_url,
-      net::CanonicalCookie::CookieInclusionStatus status);
+      net::CanonicalCookie::CookieInclusionStatus::WarningReason warning);
 
   // Notify the scheduler that this frame used a feature which impacts the
   // scheduling policy (e.g. whether the frame can be frozen or put into the
diff --git a/content/browser/geolocation/geolocation_service_impl.cc b/content/browser/geolocation/geolocation_service_impl.cc
index 77d51d8e..42b9a4d 100644
--- a/content/browser/geolocation/geolocation_service_impl.cc
+++ b/content/browser/geolocation/geolocation_service_impl.cc
@@ -68,7 +68,7 @@
 }
 
 void GeolocationServiceImpl::CreateGeolocation(
-    mojo::InterfaceRequest<device::mojom::Geolocation> request,
+    mojo::PendingReceiver<device::mojom::Geolocation> receiver,
     bool user_gesture,
     CreateGeolocationCallback callback) {
   if (!render_frame_host_->IsFeatureEnabled(
@@ -87,19 +87,19 @@
       // There is an assumption here that the GeolocationServiceImplContext will
       // outlive the GeolocationServiceImpl.
       base::Bind(&GeolocationServiceImpl::CreateGeolocationWithPermissionStatus,
-                 base::Unretained(this), base::Passed(&request),
+                 base::Unretained(this), base::Passed(&receiver),
                  base::Passed(&scoped_callback)));
 }
 
 void GeolocationServiceImpl::CreateGeolocationWithPermissionStatus(
-    device::mojom::GeolocationRequest request,
+    mojo::PendingReceiver<device::mojom::Geolocation> receiver,
     CreateGeolocationCallback callback,
     blink::mojom::PermissionStatus permission_status) {
   std::move(callback).Run(permission_status);
   if (permission_status != blink::mojom::PermissionStatus::GRANTED)
     return;
 
-  geolocation_context_->BindGeolocation(std::move(request));
+  geolocation_context_->BindGeolocation(std::move(receiver));
 }
 
 }  // namespace content
diff --git a/content/browser/geolocation/geolocation_service_impl.h b/content/browser/geolocation/geolocation_service_impl.h
index 247a0ca..d737f1d 100644
--- a/content/browser/geolocation/geolocation_service_impl.h
+++ b/content/browser/geolocation/geolocation_service_impl.h
@@ -59,14 +59,15 @@
   // Creates a Geolocation instance.
   // This may not be called a second time until the Geolocation instance has
   // been created.
-  void CreateGeolocation(device::mojom::GeolocationRequest request,
-                         bool user_gesture,
-                         CreateGeolocationCallback callback) override;
+  void CreateGeolocation(
+      mojo::PendingReceiver<device::mojom::Geolocation> receiver,
+      bool user_gesture,
+      CreateGeolocationCallback callback) override;
 
  private:
   // Creates the Geolocation Service.
   void CreateGeolocationWithPermissionStatus(
-      device::mojom::GeolocationRequest request,
+      mojo::PendingReceiver<device::mojom::Geolocation> receiver,
       CreateGeolocationCallback callback,
       blink::mojom::PermissionStatus permission_status);
 
diff --git a/content/browser/gpu/DEPS b/content/browser/gpu/DEPS
index b235dbb..e1056a3 100644
--- a/content/browser/gpu/DEPS
+++ b/content/browser/gpu/DEPS
@@ -1,3 +1,7 @@
+include_rules = [
+  "+components/ui_devtools/buildflags.h",
+]
+
 # TODO(crbug.com/734668): Dependencies on ozone should be removed, as content
 # embedded in mus won't be able to talk to the native ozone.
 specific_include_rules = {
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 350e8aa..8ecb551 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -880,7 +880,7 @@
   gpu_host_ = std::make_unique<viz::GpuHostImpl>(
       this, std::move(viz_main_pending_remote), std::move(params));
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableVizDevTools)) {
     // Start creating a socket for the Viz DevTools server. If it is created
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 5523fa59..555bfed 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -20,6 +20,7 @@
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/ui_devtools/buildflags.h"
 #include "components/viz/host/gpu_host_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_child_process_host_delegate.h"
@@ -40,7 +41,7 @@
 #include "services/viz/privileged/mojom/viz_main.mojom.h"
 #include "url/gurl.h"
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
 #include "content/browser/gpu/viz_devtools_connector.h"
 #endif
 
@@ -242,7 +243,7 @@
 
   std::unique_ptr<viz::GpuHostImpl> gpu_host_;
 
-#if defined(USE_VIZ_DEVTOOLS)
+#if BUILDFLAG(USE_VIZ_DEVTOOLS)
   std::unique_ptr<VizDevToolsConnector> devtools_connector_;
 #endif
 
diff --git a/content/browser/native_file_system/native_file_system_file_writer_impl.cc b/content/browser/native_file_system/native_file_system_file_writer_impl.cc
index 1fa8505..b1b65fb 100644
--- a/content/browser/native_file_system/native_file_system_file_writer_impl.cc
+++ b/content/browser/native_file_system/native_file_system_file_writer_impl.cc
@@ -75,13 +75,15 @@
     const BindingContext& context,
     const storage::FileSystemURL& url,
     const storage::FileSystemURL& swap_url,
-    const SharedHandleState& handle_state)
+    const SharedHandleState& handle_state,
+    bool has_transient_user_activation)
     : NativeFileSystemHandleBase(manager,
                                  context,
                                  url,
                                  handle_state,
                                  /*is_directory=*/false),
-      swap_url_(swap_url) {
+      swap_url_(swap_url),
+      has_transient_user_activation_(has_transient_user_activation) {
   DCHECK_EQ(swap_url.type(), url.type());
 }
 
diff --git a/content/browser/native_file_system/native_file_system_file_writer_impl.h b/content/browser/native_file_system/native_file_system_file_writer_impl.h
index 0d2878f..079a188 100644
--- a/content/browser/native_file_system/native_file_system_file_writer_impl.h
+++ b/content/browser/native_file_system/native_file_system_file_writer_impl.h
@@ -41,7 +41,8 @@
                                  const BindingContext& context,
                                  const storage::FileSystemURL& url,
                                  const storage::FileSystemURL& swap_url,
-                                 const SharedHandleState& handle_state);
+                                 const SharedHandleState& handle_state,
+                                 bool has_transient_user_activation);
   ~NativeFileSystemFileWriterImpl() override;
 
   const storage::FileSystemURL& swap_url() const { return swap_url_; }
@@ -65,6 +66,9 @@
   void ComputeHashForSwapFileForTesting(HashCallback callback) {
     ComputeHashForSwapFile(std::move(callback));
   }
+  bool HasTransientUserActivationForTesting() const {
+    return has_transient_user_activation_;
+  }
 
  private:
   // State that is kept for the duration of a write operation, to keep track of
@@ -128,6 +132,10 @@
 
   bool skip_quarantine_service_for_testing_ = false;
 
+  // Keeps track of user activation state at creation time for SafeBrowsing
+  // checks.
+  bool has_transient_user_activation_ = false;
+
   base::WeakPtr<NativeFileSystemHandleBase> AsWeakPtr() override;
 
   base::WeakPtrFactory<NativeFileSystemFileWriterImpl> weak_factory_{this};
diff --git a/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc b/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc
index c47a5fd..12d0f94 100644
--- a/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc
+++ b/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc
@@ -93,7 +93,8 @@
             /*frame_id=*/MSG_ROUTING_NONE),
         test_file_url_, test_swap_url_,
         NativeFileSystemManagerImpl::SharedHandleState(
-            permission_grant_, permission_grant_, std::move(fs)));
+            permission_grant_, permission_grant_, std::move(fs)),
+        /*has_transient_user_activation=*/false);
     handle_->set_skip_quarantine_service_for_testing();
   }
 
diff --git a/content/browser/native_file_system/native_file_system_manager_impl.cc b/content/browser/native_file_system/native_file_system_manager_impl.cc
index 97219de3..22d66e7 100644
--- a/content/browser/native_file_system/native_file_system_manager_impl.cc
+++ b/content/browser/native_file_system/native_file_system_manager_impl.cc
@@ -95,6 +95,16 @@
                                    std::move(callback_runner));
 }
 
+bool HasTransientUserActivation(int render_process_id, int frame_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  RenderFrameHost* rfh = RenderFrameHost::FromID(render_process_id, frame_id);
+
+  if (!rfh)
+    return false;
+
+  return rfh->HasTransientUserActivation();
+}
+
 }  // namespace
 
 NativeFileSystemManagerImpl::SharedHandleState::SharedHandleState(
@@ -318,10 +328,16 @@
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> result;
-  writer_receivers_.Add(std::make_unique<NativeFileSystemFileWriterImpl>(
-                            this, binding_context, url, swap_url, handle_state),
-                        result.InitWithNewPipeAndPassReceiver());
+  mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter>
+      writer_receiver = result.InitWithNewPipeAndPassReceiver();
 
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {BrowserThread::UI},
+      base::BindOnce(&HasTransientUserActivation, binding_context.process_id,
+                     binding_context.frame_id),
+      base::BindOnce(&NativeFileSystemManagerImpl::CreateFileWriterImpl,
+                     weak_factory_.GetWeakPtr(), binding_context, url, swap_url,
+                     handle_state, std::move(writer_receiver)));
   return result;
 }
 
@@ -602,4 +618,18 @@
       url.base_name);
 }
 
+void NativeFileSystemManagerImpl::CreateFileWriterImpl(
+    const BindingContext& binding_context,
+    const storage::FileSystemURL& url,
+    const storage::FileSystemURL& swap_url,
+    const SharedHandleState& handle_state,
+    mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter>
+        writer_receiver,
+    bool has_transient_user_activation) {
+  writer_receivers_.Add(std::make_unique<NativeFileSystemFileWriterImpl>(
+                            this, binding_context, url, swap_url, handle_state,
+                            has_transient_user_activation),
+                        std::move(writer_receiver));
+}
+
 }  // namespace content
diff --git a/content/browser/native_file_system/native_file_system_manager_impl.h b/content/browser/native_file_system/native_file_system_manager_impl.h
index d602de8..8cf9077 100644
--- a/content/browser/native_file_system/native_file_system_manager_impl.h
+++ b/content/browser/native_file_system/native_file_system_manager_impl.h
@@ -227,6 +227,15 @@
       const base::FilePath& file_path,
       NativeFileSystemPermissionContext::UserAction user_action);
 
+  void CreateFileWriterImpl(
+      const BindingContext& binding_context,
+      const storage::FileSystemURL& url,
+      const storage::FileSystemURL& swap_url,
+      const SharedHandleState& handle_state,
+      mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter>
+          writer_receiver,
+      bool has_transient_user_activation);
+
   const scoped_refptr<storage::FileSystemContext> context_;
   const scoped_refptr<ChromeBlobStorageContext> blob_context_;
   std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 4346db50..4512ee4 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -967,7 +967,6 @@
                                          ->GetGpuMemoryBufferManager();
   params.pipes.compositor_frame_sink_associated_info = std::move(sink_info);
   params.pipes.client_request = std::move(client_request);
-  params.enable_surface_synchronization = true;
   params.hit_test_data_provider =
       std::make_unique<viz::HitTestDataProviderDrawQuad>(
           false /* should_ask_for_child_region */,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 7c3c2bbd..6006e243 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -374,9 +374,8 @@
       GetSiteInstance()->GetSiteURL().SchemeIs(kGuestScheme);
   params->inside_portal = delegate_->IsPortal();
 
-  bool needs_ack = false;
-  GetWidget()->GetVisualProperties(&params->visual_properties, &needs_ack);
-  GetWidget()->SetInitialVisualProperties(params->visual_properties, needs_ack);
+  params->visual_properties = GetWidget()->GetVisualProperties();
+  GetWidget()->SetInitialVisualProperties(params->visual_properties);
 
   // The RenderView is owned by this process. This call must be accompanied by a
   // DestroyView [see destructor] or else there will be a leak in the renderer
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 3925586..f036c84 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -764,26 +764,24 @@
 }
 #endif
 
-bool RenderWidgetHostImpl::GetVisualProperties(
-    VisualProperties* visual_properties,
-    bool* needs_ack) {
+VisualProperties RenderWidgetHostImpl::GetVisualProperties() {
   // This is only called while the RenderWidgetHost is attached to a delegate
   // still.
   DCHECK(delegate_);
 
-  *visual_properties = VisualProperties();
+  VisualProperties visual_properties;
 
-  GetScreenInfo(&visual_properties->screen_info);
+  GetScreenInfo(&visual_properties.screen_info);
 
-  visual_properties->is_fullscreen_granted =
+  visual_properties.is_fullscreen_granted =
       delegate_->IsFullscreenForCurrentTab();
-  visual_properties->display_mode = delegate_->GetDisplayMode(this);
-  visual_properties->zoom_level = delegate_->GetPendingPageZoomLevel();
+  visual_properties.display_mode = delegate_->GetDisplayMode(this);
+  visual_properties.zoom_level = delegate_->GetPendingPageZoomLevel();
 
   RenderViewHostDelegateView* rvh_delegate_view = delegate_->GetDelegateView();
   DCHECK(rvh_delegate_view);
 
-  visual_properties->browser_controls_shrink_blink_size =
+  visual_properties.browser_controls_shrink_blink_size =
       rvh_delegate_view->DoBrowserControlsShrinkRendererSize();
 
   float top_controls_height = rvh_delegate_view->GetTopControlsHeight();
@@ -794,126 +792,54 @@
   // in DIPs then.
   if (!IsUseZoomForDSFEnabled()) {
     browser_controls_dsf_multiplier =
-        visual_properties->screen_info.device_scale_factor;
+        visual_properties.screen_info.device_scale_factor;
   }
-  visual_properties->top_controls_height =
+  visual_properties.top_controls_height =
       top_controls_height / browser_controls_dsf_multiplier;
-  visual_properties->bottom_controls_height =
+  visual_properties.bottom_controls_height =
       bottom_controls_height / browser_controls_dsf_multiplier;
 
-  visual_properties->auto_resize_enabled = auto_resize_enabled_;
-  visual_properties->min_size_for_auto_resize = min_size_for_auto_resize_;
-  visual_properties->max_size_for_auto_resize = max_size_for_auto_resize_;
+  visual_properties.auto_resize_enabled = auto_resize_enabled_;
+  visual_properties.min_size_for_auto_resize = min_size_for_auto_resize_;
+  visual_properties.max_size_for_auto_resize = max_size_for_auto_resize_;
 
-  visual_properties->page_scale_factor = page_scale_factor_;
-  visual_properties->is_pinch_gesture_active = is_pinch_gesture_active_;
+  visual_properties.page_scale_factor = page_scale_factor_;
+  visual_properties.is_pinch_gesture_active = is_pinch_gesture_active_;
 
   if (view_) {
-    visual_properties->new_size = view_->GetRequestedRendererSize();
-    visual_properties->capture_sequence_number =
+    visual_properties.new_size = view_->GetRequestedRendererSize();
+    visual_properties.capture_sequence_number =
         view_->GetCaptureSequenceNumber();
-    visual_properties->compositor_viewport_pixel_size =
+    visual_properties.compositor_viewport_pixel_size =
         view_->GetCompositorViewportPixelSize();
-    visual_properties->visible_viewport_size = view_->GetVisibleViewportSize();
+    visual_properties.visible_viewport_size = view_->GetVisibleViewportSize();
     // TODO(ccameron): GetLocalSurfaceId is not synchronized with the device
     // scale factor of the surface. Fix this.
     viz::LocalSurfaceIdAllocation local_surface_id_allocation =
         view_->GetLocalSurfaceIdAllocation();
     if (local_surface_id_allocation.IsValid()) {
-      visual_properties->local_surface_id_allocation =
+      visual_properties.local_surface_id_allocation =
           local_surface_id_allocation;
     }
   }
 
   if (screen_orientation_type_for_testing_) {
-    visual_properties->screen_info.orientation_type =
+    visual_properties.screen_info.orientation_type =
         *screen_orientation_type_for_testing_;
   }
 
   if (screen_orientation_angle_for_testing_) {
-    visual_properties->screen_info.orientation_angle =
+    visual_properties.screen_info.orientation_angle =
         *screen_orientation_angle_for_testing_;
   }
 
-  const bool size_changed =
-      !old_visual_properties_ ||
-      old_visual_properties_->auto_resize_enabled !=
-          visual_properties->auto_resize_enabled ||
-      (old_visual_properties_->auto_resize_enabled &&
-       (old_visual_properties_->min_size_for_auto_resize !=
-            visual_properties->min_size_for_auto_resize ||
-        old_visual_properties_->max_size_for_auto_resize !=
-            visual_properties->max_size_for_auto_resize)) ||
-      (!old_visual_properties_->auto_resize_enabled &&
-       (old_visual_properties_->new_size != visual_properties->new_size ||
-        (old_visual_properties_->compositor_viewport_pixel_size.IsEmpty() &&
-         !visual_properties->compositor_viewport_pixel_size.IsEmpty())));
-
-  viz::LocalSurfaceIdAllocation old_parent_local_surface_id_allocation =
-      old_visual_properties_
-          ? old_visual_properties_->local_surface_id_allocation.value_or(
-                viz::LocalSurfaceIdAllocation())
-          : viz::LocalSurfaceIdAllocation();
-  const viz::LocalSurfaceId& old_parent_local_surface_id =
-      old_parent_local_surface_id_allocation.local_surface_id();
-
-  viz::LocalSurfaceIdAllocation new_parent_local_surface_id_allocation =
-      visual_properties->local_surface_id_allocation.value_or(
-          viz::LocalSurfaceIdAllocation());
-  const viz::LocalSurfaceId& new_parent_local_surface_id =
-      new_parent_local_surface_id_allocation.local_surface_id();
-
-  const bool parent_local_surface_id_changed =
-      !old_visual_properties_ ||
-      old_parent_local_surface_id.parent_sequence_number() !=
-          new_parent_local_surface_id.parent_sequence_number() ||
-      old_parent_local_surface_id.embed_token() !=
-          new_parent_local_surface_id.embed_token();
-
-  const bool zoom_changed =
-      !old_visual_properties_ ||
-      old_visual_properties_->zoom_level != visual_properties->zoom_level;
-
-  bool dirty =
-      zoom_changed || size_changed || parent_local_surface_id_changed ||
-      old_visual_properties_->screen_info != visual_properties->screen_info ||
-      old_visual_properties_->compositor_viewport_pixel_size !=
-          visual_properties->compositor_viewport_pixel_size ||
-      old_visual_properties_->is_fullscreen_granted !=
-          visual_properties->is_fullscreen_granted ||
-      old_visual_properties_->display_mode != visual_properties->display_mode ||
-      old_visual_properties_->top_controls_height !=
-          visual_properties->top_controls_height ||
-      old_visual_properties_->browser_controls_shrink_blink_size !=
-          visual_properties->browser_controls_shrink_blink_size ||
-      old_visual_properties_->bottom_controls_height !=
-          visual_properties->bottom_controls_height ||
-      old_visual_properties_->visible_viewport_size !=
-          visual_properties->visible_viewport_size ||
-      old_visual_properties_->capture_sequence_number !=
-          visual_properties->capture_sequence_number ||
-      old_visual_properties_->page_scale_factor !=
-          visual_properties->page_scale_factor ||
-      old_visual_properties_->is_pinch_gesture_active !=
-          visual_properties->is_pinch_gesture_active;
-
-  // We should throttle sending updated VisualProperties to the renderer to
-  // the rate of commit. This ensures we don't overwhelm the renderer with
-  // visual updates faster than it can keep up.  |needs_ack| corresponds to
-  // cases where a commit is expected.
-  *needs_ack = g_check_for_pending_visual_properties_ack &&
-               !visual_properties->auto_resize_enabled &&
-               !visual_properties->new_size.IsEmpty() &&
-               !visual_properties->compositor_viewport_pixel_size.IsEmpty() &&
-               visual_properties->local_surface_id_allocation && size_changed;
-
-  return dirty;
+  return visual_properties;
 }
 
 void RenderWidgetHostImpl::SetInitialVisualProperties(
-    const VisualProperties& visual_properties,
-    bool needs_ack) {
-  visual_properties_ack_pending_ = needs_ack;
+    const VisualProperties& visual_properties) {
+  visual_properties_ack_pending_ =
+      DoesVisualPropertiesNeedAck(old_visual_properties_, visual_properties);
   old_visual_properties_ =
       std::make_unique<VisualProperties>(visual_properties);
 }
@@ -941,9 +867,11 @@
   }
 
   auto visual_properties = std::make_unique<VisualProperties>();
-  bool needs_ack = false;
-  if (!GetVisualProperties(visual_properties.get(), &needs_ack))
+  *visual_properties = GetVisualProperties();
+  if (!StoredVisualPropertiesNeedsUpdate(old_visual_properties_,
+                                         *visual_properties))
     return false;
+
   visual_properties->scroll_focused_node_into_view =
       scroll_focused_node_into_view;
 
@@ -995,7 +923,8 @@
         "WidgetMsg_SynchronizeVisualProperties", "local_surface_id",
         visual_properties->local_surface_id_allocation->local_surface_id()
             .ToString());
-    visual_properties_ack_pending_ = needs_ack;
+    visual_properties_ack_pending_ =
+        DoesVisualPropertiesNeedAck(old_visual_properties_, *visual_properties);
     if (delegate() && visible_viewport_size_changed) {
       delegate()->NotifyVisibleViewportSizeChanged(
           visual_properties->visible_viewport_size);
@@ -2303,6 +2232,100 @@
   }
 }
 
+// static
+bool RenderWidgetHostImpl::DidVisualPropertiesSizeChange(
+    const VisualProperties& old_visual_properties,
+    const VisualProperties& new_visual_properties) {
+  return old_visual_properties.auto_resize_enabled !=
+             new_visual_properties.auto_resize_enabled ||
+         (old_visual_properties.auto_resize_enabled &&
+          (old_visual_properties.min_size_for_auto_resize !=
+               new_visual_properties.min_size_for_auto_resize ||
+           old_visual_properties.max_size_for_auto_resize !=
+               new_visual_properties.max_size_for_auto_resize)) ||
+         (!old_visual_properties.auto_resize_enabled &&
+          (old_visual_properties.new_size != new_visual_properties.new_size ||
+           (old_visual_properties.compositor_viewport_pixel_size.IsEmpty() &&
+            !new_visual_properties.compositor_viewport_pixel_size.IsEmpty())));
+}
+
+// static
+bool RenderWidgetHostImpl::DoesVisualPropertiesNeedAck(
+    const std::unique_ptr<VisualProperties>& old_visual_properties,
+    const VisualProperties& new_visual_properties) {
+  // We should throttle sending updated VisualProperties to the renderer to
+  // the rate of commit. This ensures we don't overwhelm the renderer with
+  // visual updates faster than it can keep up.  |needs_ack| corresponds to
+  // cases where a commit is expected.
+  bool is_acking_applicable =
+      g_check_for_pending_visual_properties_ack &&
+      !new_visual_properties.auto_resize_enabled &&
+      !new_visual_properties.new_size.IsEmpty() &&
+      !new_visual_properties.compositor_viewport_pixel_size.IsEmpty() &&
+      new_visual_properties.local_surface_id_allocation;
+
+  // If acking is applicable, then check if there has been an
+  // |old_visual_properties| stored which would indicate an update has been
+  // sent. If so, then acking is defined by size changing.
+  return is_acking_applicable &&
+         (!old_visual_properties ||
+          DidVisualPropertiesSizeChange(*old_visual_properties,
+                                        new_visual_properties));
+}
+
+// static
+bool RenderWidgetHostImpl::StoredVisualPropertiesNeedsUpdate(
+    const std::unique_ptr<VisualProperties>& old_visual_properties,
+    const VisualProperties& new_visual_properties) {
+  if (!old_visual_properties)
+    return true;
+
+  const viz::LocalSurfaceId& old_parent_local_surface_id =
+      old_visual_properties->local_surface_id_allocation
+          .value_or(viz::LocalSurfaceIdAllocation())
+          .local_surface_id();
+
+  viz::LocalSurfaceIdAllocation new_parent_local_surface_id_allocation =
+      new_visual_properties.local_surface_id_allocation.value_or(
+          viz::LocalSurfaceIdAllocation());
+  const viz::LocalSurfaceId& new_parent_local_surface_id =
+      new_parent_local_surface_id_allocation.local_surface_id();
+
+  const bool parent_local_surface_id_changed =
+      old_parent_local_surface_id.parent_sequence_number() !=
+          new_parent_local_surface_id.parent_sequence_number() ||
+      old_parent_local_surface_id.embed_token() !=
+          new_parent_local_surface_id.embed_token();
+
+  return DidVisualPropertiesSizeChange(*old_visual_properties,
+                                       new_visual_properties) ||
+         parent_local_surface_id_changed ||
+         old_visual_properties->zoom_level !=
+             new_visual_properties.zoom_level ||
+         old_visual_properties->screen_info !=
+             new_visual_properties.screen_info ||
+         old_visual_properties->compositor_viewport_pixel_size !=
+             new_visual_properties.compositor_viewport_pixel_size ||
+         old_visual_properties->is_fullscreen_granted !=
+             new_visual_properties.is_fullscreen_granted ||
+         old_visual_properties->display_mode !=
+             new_visual_properties.display_mode ||
+         old_visual_properties->top_controls_height !=
+             new_visual_properties.top_controls_height ||
+         old_visual_properties->browser_controls_shrink_blink_size !=
+             new_visual_properties.browser_controls_shrink_blink_size ||
+         old_visual_properties->bottom_controls_height !=
+             new_visual_properties.bottom_controls_height ||
+         old_visual_properties->visible_viewport_size !=
+             new_visual_properties.visible_viewport_size ||
+         old_visual_properties->capture_sequence_number !=
+             new_visual_properties.capture_sequence_number ||
+         old_visual_properties->page_scale_factor !=
+             new_visual_properties.page_scale_factor ||
+         old_visual_properties->is_pinch_gesture_active !=
+             new_visual_properties.is_pinch_gesture_active;
+}
+
 void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
   SetCursor(cursor);
 }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index ef6276238..032d433 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -594,15 +594,13 @@
   // Allows the main frame's page scale state to be tracked.
   void SetPageScaleState(float page_scale_factor, bool is_pinch_gesture_active);
 
-  // Fills in the |visual_properties| struct.
-  // Returns |false| if the update is redundant, |true| otherwise.
-  bool GetVisualProperties(VisualProperties* visual_properties,
-                           bool* needs_ack);
+  // Generates a filled in VisualProperties struct representing the current
+  // properties of this widget.
+  VisualProperties GetVisualProperties();
 
   // Sets the |visual_properties| that were sent to the renderer bundled with
   // the request to create a new RenderWidget.
-  void SetInitialVisualProperties(const VisualProperties& visual_properties,
-                                  bool needs_ack);
+  void SetInitialVisualProperties(const VisualProperties& visual_properties);
 
   // Pushes updated visual properties to the renderer as well as whether the
   // focused node should be scrolled into view.
@@ -897,6 +895,24 @@
   // Called when visual properties have changed in the renderer.
   void DidUpdateVisualProperties(const cc::RenderFrameMetadata& metadata);
 
+  // Returns true if the |new_visual_properties| differs from
+  // |old_page_visual_properties| in a way that indicates a size changed.
+  static bool DidVisualPropertiesSizeChange(
+      const VisualProperties& old_visual_properties,
+      const VisualProperties& new_visual_properties);
+
+  // Returns true if the new visual properties requires an ack from a
+  // synchronization message.
+  static bool DoesVisualPropertiesNeedAck(
+      const std::unique_ptr<VisualProperties>& old_visual_properties,
+      const VisualProperties& new_visual_properties);
+
+  // Returns true if |old_visual_properties| is out of sync with
+  // |new_visual_properties|.
+  static bool StoredVisualPropertiesNeedsUpdate(
+      const std::unique_ptr<VisualProperties>& old_visual_properties,
+      const VisualProperties& new_visual_properties);
+
   // Give key press listeners a chance to handle this key press. This allow
   // widgets that don't have focus to still handle key presses.
   bool KeyPressListenersHandleEvent(const NativeWebKeyboardEvent& event);
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 289a616..3573e84 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -549,10 +549,8 @@
   }
 
   void SetInitialVisualProperties() {
-    VisualProperties visual_properties;
-    bool needs_ack = false;
-    host_->GetVisualProperties(&visual_properties, &needs_ack);
-    host_->SetInitialVisualProperties(visual_properties, needs_ack);
+    VisualProperties visual_properties = host_->GetVisualProperties();
+    host_->SetInitialVisualProperties(visual_properties);
   }
 
   virtual void ConfigureView(TestView* view) {
@@ -1578,9 +1576,7 @@
   view_->SetBounds(bounds);
   view_->SetMockCompositorViewportPixelSize(compositor_viewport_pixel_size);
 
-  VisualProperties visual_properties;
-  bool needs_ack = false;
-  host_->GetVisualProperties(&visual_properties, &needs_ack);
+  VisualProperties visual_properties = host_->GetVisualProperties();
   EXPECT_EQ(bounds.size(), visual_properties.new_size);
   EXPECT_EQ(compositor_viewport_pixel_size,
             visual_properties.compositor_viewport_pixel_size);
diff --git a/content/browser/sms/sms_browsertest.cc b/content/browser/sms/sms_browsertest.cc
index 3a187766..2e1262e 100644
--- a/content/browser/sms/sms_browsertest.cc
+++ b/content/browser/sms/sms_browsertest.cc
@@ -101,11 +101,11 @@
 
   shell()->web_contents()->SetDelegate(&delegate_);
 
-  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-      .WillOnce(Invoke([&](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
-        std::move(on_confirm).Run();
-      }));
+  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+      .WillOnce(
+          Invoke([&](RenderFrameHost*, const url::Origin&, const std::string&,
+                     base::OnceClosure on_confirm,
+                     base::OnceClosure) { std::move(on_confirm).Run(); }));
 
   auto* provider = new NiceMock<MockSmsProvider>();
   BrowserMainLoop::GetInstance()->SetSmsProviderForTesting(
@@ -120,7 +120,7 @@
   )";
 
   EXPECT_CALL(*provider, Retrieve()).WillOnce(Invoke([&provider, &url]() {
-    provider->NotifyReceive(url::Origin::Create(url), "hello");
+    provider->NotifyReceive(url::Origin::Create(url), "", "hello");
   }));
 
   // Wait for UKM to be recorded to avoid race condition.
@@ -143,11 +143,11 @@
 
   shell()->web_contents()->SetDelegate(&delegate_);
 
-  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-      .WillOnce(Invoke([&](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
-        std::move(on_confirm).Run();
-      }));
+  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+      .WillOnce(
+          Invoke([&](RenderFrameHost*, const url::Origin&, const std::string&,
+                     base::OnceClosure on_confirm,
+                     base::OnceClosure) { std::move(on_confirm).Run(); }));
 
   auto* provider = new NiceMock<MockSmsProvider>();
   BrowserMainLoop::GetInstance()->SetSmsProviderForTesting(
@@ -181,7 +181,7 @@
   ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                         ukm_loop2.QuitClosure());
 
-  provider->NotifyReceive(url::Origin::Create(url), "hello");
+  provider->NotifyReceive(url::Origin::Create(url), "", "hello");
 
   EXPECT_EQ("hello", EvalJs(shell(), "first"));
 
@@ -324,10 +324,10 @@
     base::RunLoop loop;
     base::RunLoop ukm_loop;
 
-    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-        .WillOnce(
-            Invoke([&loop](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
+    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+        .WillOnce(Invoke(
+            [&loop](RenderFrameHost*, const url::Origin&, const std::string&,
+                    base::OnceClosure on_confirm, base::OnceClosure) {
               std::move(on_confirm).Run();
               loop.Quit();
             }));
@@ -336,7 +336,7 @@
     ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                           ukm_loop.QuitClosure());
 
-    provider->NotifyReceive(url::Origin::Create(url), "hello1");
+    provider->NotifyReceive(url::Origin::Create(url), "", "hello1");
 
     loop.Run();
     ukm_loop.Run();
@@ -354,10 +354,10 @@
     base::RunLoop loop;
     base::RunLoop ukm_loop;
 
-    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-        .WillOnce(
-            Invoke([&loop](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
+    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+        .WillOnce(Invoke(
+            [&loop](RenderFrameHost*, const url::Origin&, const std::string&,
+                    base::OnceClosure on_confirm, base::OnceClosure) {
               std::move(on_confirm).Run();
               loop.Quit();
             }));
@@ -366,7 +366,7 @@
     ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                           ukm_loop.QuitClosure());
 
-    provider->NotifyReceive(url::Origin::Create(url), "hello2");
+    provider->NotifyReceive(url::Origin::Create(url), "", "hello2");
 
     loop.Run();
     ukm_loop.Run();
@@ -424,17 +424,17 @@
   {
     base::RunLoop loop;
     base::RunLoop ukm_loop;
-    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-        .WillOnce(
-            Invoke([&loop](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
+    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+        .WillOnce(Invoke(
+            [&loop](RenderFrameHost*, const url::Origin&, const std::string&,
+                    base::OnceClosure on_confirm, base::OnceClosure) {
               std::move(on_confirm).Run();
               loop.Quit();
             }));
     // Wait for UKM to be recorded to avoid race condition.
     ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                           ukm_loop.QuitClosure());
-    provider->NotifyReceive(url::Origin::Create(url1), "hello1");
+    provider->NotifyReceive(url::Origin::Create(url1), "", "hello1");
     loop.Run();
     ukm_loop.Run();
   }
@@ -446,17 +446,17 @@
   {
     base::RunLoop loop;
     base::RunLoop ukm_loop;
-    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
-        .WillOnce(
-            Invoke([&loop](RenderFrameHost*, const url::Origin&,
-                           base::OnceClosure on_confirm, base::OnceClosure) {
+    EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
+        .WillOnce(Invoke(
+            [&loop](RenderFrameHost*, const url::Origin&, const std::string&,
+                    base::OnceClosure on_confirm, base::OnceClosure) {
               std::move(on_confirm).Run();
               loop.Quit();
             }));
     // Wait for UKM to be recorded to avoid race condition.
     ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName,
                                           ukm_loop.QuitClosure());
-    provider->NotifyReceive(url::Origin::Create(url2), "hello2");
+    provider->NotifyReceive(url::Origin::Create(url2), "", "hello2");
     loop.Run();
     ukm_loop.Run();
   }
@@ -495,7 +495,7 @@
 
   shell()->Close();
 
-  provider->NotifyReceive(url::Origin::Create(url), "hello");
+  provider->NotifyReceive(url::Origin::Create(url), "", "hello");
 
   ExpectNoOutcomeUKM();
 }
@@ -513,16 +513,17 @@
   base::RunLoop loop;
   base::RunLoop ukm_loop;
 
-  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _))
+  EXPECT_CALL(delegate_, CreateSmsPrompt(_, _, _, _, _))
       .WillOnce(Invoke([&loop](RenderFrameHost*, const url::Origin&,
-                               base::OnceClosure, base::OnceClosure on_cancel) {
+                               const std::string&, base::OnceClosure,
+                               base::OnceClosure on_cancel) {
         // Simulates the user pressing "cancel".
         std::move(on_cancel).Run();
         loop.Quit();
       }));
 
   EXPECT_CALL(*provider, Retrieve()).WillOnce(Invoke([&provider, &url]() {
-    provider->NotifyReceive(url::Origin::Create(url), "hello");
+    provider->NotifyReceive(url::Origin::Create(url), "", "hello");
   }));
 
   // Wait for UKM to be recorded to avoid race condition.
diff --git a/content/browser/sms/sms_parser.cc b/content/browser/sms/sms_parser.cc
index 68d85ef..902f02b 100644
--- a/content/browser/sms/sms_parser.cc
+++ b/content/browser/sms/sms_parser.cc
@@ -16,9 +16,16 @@
 namespace content {
 
 constexpr base::StringPiece kToken = "For: ";
+constexpr base::StringPiece kOneTimeCode = "otp";
+
+SmsParser::Result::Result(const url::Origin& origin,
+                          const std::string& one_time_code)
+    : origin(std::move(origin)), one_time_code(one_time_code) {}
+
+SmsParser::Result::~Result() {}
 
 // static
-base::Optional<url::Origin> SmsParser::Parse(base::StringPiece sms) {
+base::Optional<SmsParser::Result> SmsParser::Parse(base::StringPiece sms) {
   size_t found = sms.rfind(kToken);
 
   if (found == base::StringPiece::npos) {
@@ -29,15 +36,18 @@
 
   GURL gurl(url);
 
-  if (!gurl.is_valid()) {
+  if (!gurl.is_valid())
     return base::nullopt;
-  }
 
-  if (!(gurl.SchemeIs(url::kHttpsScheme) || net::IsLocalhost(gurl))) {
+  if (!(gurl.SchemeIs(url::kHttpsScheme) || net::IsLocalhost(gurl)))
     return base::nullopt;
-  }
 
-  return url::Origin::Create(gurl);
+  std::string one_time_code;
+
+  if (!net::GetValueForKeyInQuery(gurl, kOneTimeCode.data(), &one_time_code))
+    return base::nullopt;
+
+  return Result(url::Origin::Create(gurl), one_time_code);
 }
 
 }  // namespace content
diff --git a/content/browser/sms/sms_parser.h b/content/browser/sms/sms_parser.h
index f70372c1..8c8bf60 100644
--- a/content/browser/sms/sms_parser.h
+++ b/content/browser/sms/sms_parser.h
@@ -7,10 +7,7 @@
 
 #include "base/optional.h"
 #include "content/common/content_export.h"
-
-namespace url {
-class Origin;
-}
+#include "url/origin.h"
 
 namespace content {
 
@@ -19,7 +16,15 @@
 // Returns an empty result if the formatting doesn't match.
 class CONTENT_EXPORT SmsParser {
  public:
-  static base::Optional<url::Origin> Parse(base::StringPiece sms);
+  struct CONTENT_EXPORT Result {
+    Result(const url::Origin& origin, const std::string& one_time_code);
+    ~Result();
+
+    const url::Origin origin;
+    const std::string one_time_code;
+  };
+
+  static base::Optional<Result> Parse(base::StringPiece sms);
 };
 
 }  // namespace content
diff --git a/content/browser/sms/sms_parser_unittest.cc b/content/browser/sms/sms_parser_unittest.cc
index fa0f443..045151b9 100644
--- a/content/browser/sms/sms_parser_unittest.cc
+++ b/content/browser/sms/sms_parser_unittest.cc
@@ -11,6 +11,20 @@
 
 namespace content {
 
+namespace {
+
+url::Origin ParseOrigin(const std::string& message) {
+  base::Optional<SmsParser::Result> result = SmsParser::Parse(message);
+  return result->origin;
+}
+
+std::string ParseOTP(const std::string& message) {
+  base::Optional<SmsParser::Result> result = SmsParser::Parse(message);
+  return result->one_time_code;
+}
+
+}  // namespace
+
 TEST(SmsParserTest, NoToken) {
   ASSERT_FALSE(SmsParser::Parse("foo"));
 }
@@ -39,152 +53,93 @@
   ASSERT_FALSE(SmsParser::Parse("For: mailto:goto@chromium.org"));
 }
 
-TEST(SmsParserTest, Basic) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("For: https://example.com");
+TEST(SmsParserTest, MissingOneTimeCodeParameter) {
+  ASSERT_FALSE(SmsParser::Parse("For: https://example.com"));
+}
 
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+TEST(SmsParserTest, Basic) {
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("For: https://example.com?otp=123"));
 }
 
 TEST(SmsParserTest, Realistic) {
-  base::Optional<url::Origin> origin = SmsParser::Parse(
-      "<#> Your OTP is 1234ABC.\nFor: https://example.com?s3LhKBB0M33");
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("<#> Your OTP is 1234ABC.\nFor: "
+                        "https://example.com?otp=123&s3LhKBB0M33"));
+}
 
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+TEST(SmsParserTest, OneTimeCode) {
+  auto result = SmsParser::Parse("For: https://example.com?otp=123");
+  ASSERT_EQ("123", (*result).one_time_code);
 }
 
 TEST(SmsParserTest, LocalhostForDevelopment) {
-  ASSERT_EQ(SmsParser::Parse("For: http://localhost:8080"),
-            url::Origin::Create(GURL("http://localhost:8080")));
-  ASSERT_EQ(SmsParser::Parse("For: http://localhost:80"),
-            url::Origin::Create(GURL("http://localhost:80")));
-  ASSERT_EQ(SmsParser::Parse("For: http://localhost"),
-            url::Origin::Create(GURL("http://localhost")));
+  ASSERT_EQ(url::Origin::Create(GURL("http://localhost:8080")),
+            ParseOrigin("For: http://localhost:8080?otp=123"));
+  ASSERT_EQ(url::Origin::Create(GURL("http://localhost:80")),
+            ParseOrigin("For: http://localhost:80?otp=123"));
+  ASSERT_EQ(url::Origin::Create(GURL("http://localhost")),
+            ParseOrigin("For: http://localhost?otp=123"));
   ASSERT_FALSE(SmsParser::Parse("For: localhost"));
 }
 
 TEST(SmsParserTest, Paths) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("For: https://example.com/foobar");
-
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("For: https://example.com/foobar?otp=123"));
 }
 
 TEST(SmsParserTest, Message) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("hello world\nFor: https://example.com");
-
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("hello world\nFor: https://example.com?otp=123"));
 }
 
 TEST(SmsParserTest, Whitespace) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("hello world\nFor: https://example.com ");
-
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("hello world\nFor: https://example.com?otp=123 "));
 }
 
 TEST(SmsParserTest, Newlines) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("hello world\nFor: https://example.com\n");
-
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+  ASSERT_EQ(url::Origin::Create(GURL("https://example.com")),
+            ParseOrigin("hello world\nFor: https://example.com?otp=123\n"));
 }
 
 TEST(SmsParserTest, TwoTokens) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("For: https://a.com For: https://b.com");
-
-  GURL url("https://b.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+  ASSERT_EQ(url::Origin::Create(GURL("https://b.com")),
+            ParseOrigin("For: https://a.com For: https://b.com?otp=123"));
 }
 
 TEST(SmsParserTest, DifferentPorts) {
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com:8443/");
-
-    GURL url("https://a.com");
-    ASSERT_NE(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com:8443/");
-
-    GURL url("https://a.com:443");
-    ASSERT_NE(origin, url::Origin::Create(url));
-  }
+  ASSERT_NE(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://a.com:8443/?otp=123"));
+  ASSERT_NE(url::Origin::Create(GURL("https://a.com:443")),
+            ParseOrigin("For: https://a.com:8443/?otp=123"));
 }
 
 TEST(SmsParserTest, ImplicitPort) {
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com:443/");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com:8443/");
-
-    GURL url("https://a.com");
-    ASSERT_NE(origin, url::Origin::Create(url));
-  }
+  ASSERT_EQ(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://a.com:443/?otp=123"));
+  ASSERT_NE(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://a.com:8443/?otp=123"));
 }
 
 TEST(SmsParserTest, Redirector) {
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com/redirect?https://b.com");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com/redirect?https:%2f%2fb.com");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://a.com/redirect#https:%2f%2fb.com");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
+  ASSERT_EQ(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://a.com/redirect?otp=123&https://b.com"));
+  ASSERT_EQ(
+      url::Origin::Create(GURL("https://a.com")),
+      ParseOrigin("For: https://a.com/redirect?&otp=123&https:%2f%2fb.com"));
+  ASSERT_EQ(
+      url::Origin::Create(GURL("https://a.com")),
+      ParseOrigin("For: https://a.com/redirect?otp=123#https:%2f%2fb.com"));
 }
 
 TEST(SmsParserTest, UsernameAndPassword) {
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://b.com@a.com/");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://b.com:c.com@a.com/");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
-  {
-    base::Optional<url::Origin> origin =
-        SmsParser::Parse("For: https://b.com:noodle@a.com:443/");
-
-    GURL url("https://a.com");
-    ASSERT_EQ(origin, url::Origin::Create(url));
-  }
+  ASSERT_EQ(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://b.com@a.com/?otp=123"));
+  ASSERT_EQ(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://b.com:c.com@a.com/?otp=123"));
+  ASSERT_EQ(url::Origin::Create(GURL("https://a.com")),
+            ParseOrigin("For: https://b.com:noodle@a.com:443/?otp=123"));
 }
 
 TEST(SmsParserTest, HarmlessOriginsButInvalid) {
@@ -192,11 +147,38 @@
 }
 
 TEST(SmsParserTest, AppHash) {
-  base::Optional<url::Origin> origin =
-      SmsParser::Parse("<#> Hello World\nFor: https://example.com?s3LhKBB0M33");
+  ASSERT_EQ(
+      url::Origin::Create(GURL("https://example.com")),
+      ParseOrigin(
+          "<#> Hello World\nFor: https://example.com?otp=123&s3LhKBB0M33"));
+}
 
-  GURL url("https://example.com");
-  ASSERT_EQ(origin, url::Origin::Create(url));
+TEST(SmsParserTest, OneTimeCodeCharRanges) {
+  ASSERT_EQ("cannot-contain-hashes",
+            ParseOTP("For: https://example.com?otp=cannot-contain-hashes#yes"));
+  ASSERT_EQ(
+      "can-contain-numbers-like-123",
+      ParseOTP("For: https://example.com?otp=can-contain-numbers-like-123"));
+  ASSERT_EQ(
+      "can-contain-utf8-like-🤷",
+      ParseOTP("For: https://example.com?otp=can-contain-utf8-like-🤷"));
+  ASSERT_EQ(
+      "can-contain-chars-like-*^$@",
+      ParseOTP("For: https://example.com?otp=can-contain-chars-like-*^$@"));
+  ASSERT_EQ(
+      "human-readable-words-like-sillyface",
+      ParseOTP(
+          "For: https://example.com?otp=human-readable-words-like-sillyface"));
+  ASSERT_EQ(
+      "works-with-more-params",
+      ParseOTP("For: https://example.com?otp=works-with-more-params&foo=bar"));
+  ASSERT_EQ(
+      "works-with-more-params",
+      ParseOTP("For: https://example.com?foo=bar&otp=works-with-more-params"));
+  ASSERT_EQ(
+      "can-it-be-super-lengthy-like-a-lot",
+      ParseOTP(
+          "For: https://example.com?otp=can-it-be-super-lengthy-like-a-lot"));
 }
 
 }  // namespace content
diff --git a/content/browser/sms/sms_provider.cc b/content/browser/sms/sms_provider.cc
index 13ecffa2..8627b1f 100644
--- a/content/browser/sms/sms_provider.cc
+++ b/content/browser/sms/sms_provider.cc
@@ -38,16 +38,16 @@
 }
 
 void SmsProvider::NotifyReceive(const std::string& sms) {
-  base::Optional<url::Origin> origin = SmsParser::Parse(sms);
-  if (origin) {
-    NotifyReceive(*origin, sms);
-  }
+  base::Optional<SmsParser::Result> result = SmsParser::Parse(sms);
+  if (result)
+    NotifyReceive(result->origin, result->one_time_code, sms);
 }
 
 void SmsProvider::NotifyReceive(const url::Origin& origin,
+                                const std::string& one_time_code,
                                 const std::string& sms) {
   for (Observer& obs : observers_) {
-    bool handled = obs.OnReceive(origin, sms);
+    bool handled = obs.OnReceive(origin, one_time_code, sms);
     if (handled) {
       break;
     }
diff --git a/content/browser/sms/sms_provider.h b/content/browser/sms/sms_provider.h
index 6502afd..c8d1373f 100644
--- a/content/browser/sms/sms_provider.h
+++ b/content/browser/sms/sms_provider.h
@@ -27,7 +27,9 @@
    public:
     // Receive an |sms| from an origin. Return true if the message is
     // handled, which stops its propagation to other observers.
-    virtual bool OnReceive(const url::Origin&, const std::string& sms) = 0;
+    virtual bool OnReceive(const url::Origin&,
+                           const std::string& one_time_code,
+                           const std::string& sms) = 0;
   };
 
   SmsProvider();
@@ -41,7 +43,9 @@
 
   void AddObserver(Observer*);
   void RemoveObserver(const Observer*);
-  void NotifyReceive(const url::Origin&, const std::string& sms);
+  void NotifyReceive(const url::Origin&,
+                     const std::string& one_time_code,
+                     const std::string& sms);
   void NotifyReceive(const std::string& sms);
   bool HasObservers();
 
diff --git a/content/browser/sms/sms_provider_android_unittest.cc b/content/browser/sms/sms_provider_android_unittest.cc
index 48cc382a..2fd4b61f 100644
--- a/content/browser/sms/sms_provider_android_unittest.cc
+++ b/content/browser/sms/sms_provider_android_unittest.cc
@@ -16,6 +16,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::android::AttachCurrentThread;
+using ::testing::_;
 using ::testing::NiceMock;
 using url::Origin;
 
@@ -28,7 +29,10 @@
   MockObserver() = default;
   ~MockObserver() override = default;
 
-  MOCK_METHOD2(OnReceive, bool(const Origin&, const std::string& sms));
+  MOCK_METHOD3(OnReceive,
+               bool(const Origin&,
+                    const std::string& one_time_code,
+                    const std::string& sms));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockObserver);
@@ -73,21 +77,22 @@
 }  // namespace
 
 TEST_F(SmsProviderAndroidTest, Retrieve) {
-  std::string test_url = "https://www.google.com";
+  std::string test_url = "https://www.google.com?otp=123";
   std::string expected_sms = "Hi \nFor: " + test_url;
 
   EXPECT_CALL(*observer(),
-              OnReceive(Origin::Create(GURL(test_url)), expected_sms));
+              OnReceive(Origin::Create(GURL(test_url)), _, expected_sms));
   provider().Retrieve();
   TriggerSms(expected_sms);
 }
 
 TEST_F(SmsProviderAndroidTest, IgnoreBadSms) {
-  std::string test_url = "https://www.google.com";
+  std::string test_url = "https://www.google.com?otp=123";
   std::string good_sms = "Hi \nFor: " + test_url;
   std::string bad_sms = "Hi \nFor: http://b.com";
 
-  EXPECT_CALL(*observer(), OnReceive(Origin::Create(GURL(test_url)), good_sms));
+  EXPECT_CALL(*observer(),
+              OnReceive(Origin::Create(GURL(test_url)), _, good_sms));
 
   provider().Retrieve();
   TriggerSms(bad_sms);
diff --git a/content/browser/sms/sms_service.cc b/content/browser/sms/sms_service.cc
index 84072d34..19876bd 100644
--- a/content/browser/sms/sms_service.cc
+++ b/content/browser/sms/sms_service.cc
@@ -75,7 +75,9 @@
   sms_provider_->Retrieve();
 }
 
-bool SmsService::OnReceive(const url::Origin& origin, const std::string& sms) {
+bool SmsService::OnReceive(const url::Origin& origin,
+                           const std::string& one_time_code,
+                           const std::string& sms) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (origin_ != origin)
     return false;
@@ -92,15 +94,19 @@
   sms_ = sms;
   receive_time_ = base::TimeTicks::Now();
 
+  OpenInfoBar(one_time_code);
+
+  return true;
+}
+
+void SmsService::OpenInfoBar(const std::string& one_time_code) {
   WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host());
 
   web_contents->GetDelegate()->CreateSmsPrompt(
-      render_frame_host(), origin_,
+      render_frame_host(), origin_, one_time_code,
       base::BindOnce(&SmsService::OnConfirm, weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&SmsService::OnCancel, weak_ptr_factory_.GetWeakPtr()));
-
-  return true;
 }
 
 void SmsService::Process(blink::mojom::SmsStatus status,
diff --git a/content/browser/sms/sms_service.h b/content/browser/sms/sms_service.h
index 561b2df7..694ce7c 100644
--- a/content/browser/sms/sms_service.h
+++ b/content/browser/sms/sms_service.h
@@ -46,12 +46,15 @@
   ~SmsService() override;
 
   // content::SmsProvider::Observer:
-  bool OnReceive(const url::Origin&, const std::string& message) override;
+  bool OnReceive(const url::Origin&,
+                 const std::string& one_time_code,
+                 const std::string& sms) override;
 
   // blink::mojom::SmsReceiver:
   void Receive(base::TimeDelta timeout, ReceiveCallback) override;
 
  private:
+  void OpenInfoBar(const std::string& one_time_code);
   void Process(blink::mojom::SmsStatus, base::Optional<std::string> sms);
   void CleanUp();
 
diff --git a/content/browser/sms/sms_service_unittest.cc b/content/browser/sms/sms_service_unittest.cc
index e68f667..f69937d 100644
--- a/content/browser/sms/sms_service_unittest.cc
+++ b/content/browser/sms/sms_service_unittest.cc
@@ -78,9 +78,9 @@
   NiceMock<MockSmsProvider>* provider() { return &provider_; }
 
   void CreateSmsPrompt(RenderFrameHost* rfh, bool confirm) {
-    EXPECT_CALL(*delegate(), CreateSmsPrompt(rfh, _, _, _))
+    EXPECT_CALL(*delegate(), CreateSmsPrompt(rfh, _, _, _, _))
         .WillOnce(Invoke([=](RenderFrameHost*, const Origin& origin,
-                             base::OnceClosure on_confirm,
+                             const std::string&, base::OnceClosure on_confirm,
                              base::OnceClosure on_cancel) {
           if (confirm) {
             // Simulates user clicking the "Enter code" button to verify
@@ -97,7 +97,7 @@
   }
 
   void NotifyReceive(const GURL& url, const string& message) {
-    provider_.NotifyReceive(Origin::Create(url), message);
+    provider_.NotifyReceive(Origin::Create(url), "", message);
   }
 
  private:
@@ -431,9 +431,9 @@
     service.NotifyReceive(GURL(kTestUrl), "hi");
   }));
 
-  EXPECT_CALL(*service.delegate(), CreateSmsPrompt(main_rfh(), _, _, _))
-      .WillOnce(Invoke([&](RenderFrameHost*, const Origin&, base::OnceClosure,
-                           base::OnceClosure on_cancel) {
+  EXPECT_CALL(*service.delegate(), CreateSmsPrompt(main_rfh(), _, _, _, _))
+      .WillOnce(Invoke([&](RenderFrameHost*, const Origin&, const std::string&,
+                           base::OnceClosure, base::OnceClosure on_cancel) {
         // Simulates the user pressing "Cancel".
         std::move(on_cancel).Run();
       }));
diff --git a/content/browser/sms/test/mock_sms_web_contents_delegate.h b/content/browser/sms/test/mock_sms_web_contents_delegate.h
index ef66f10..f2822cd 100644
--- a/content/browser/sms/test/mock_sms_web_contents_delegate.h
+++ b/content/browser/sms/test/mock_sms_web_contents_delegate.h
@@ -16,9 +16,10 @@
   MockSmsWebContentsDelegate();
   ~MockSmsWebContentsDelegate() override;
 
-  MOCK_METHOD4(CreateSmsPrompt,
+  MOCK_METHOD5(CreateSmsPrompt,
                void(RenderFrameHost*,
                     const url::Origin&,
+                    const std::string&,
                     base::OnceCallback<void()> on_confirm,
                     base::OnceCallback<void()> on_cancel));
 
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc
index 418dd84..fea528f 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -26,7 +26,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace content {
@@ -44,10 +44,10 @@
 void SpeechRecognitionDispatcherHost::Create(
     int render_process_id,
     int render_frame_id,
-    blink::mojom::SpeechRecognizerRequest request) {
-  mojo::MakeStrongBinding(std::make_unique<SpeechRecognitionDispatcherHost>(
-                              render_process_id, render_frame_id),
-                          std::move(request));
+    mojo::PendingReceiver<blink::mojom::SpeechRecognizer> receiver) {
+  mojo::MakeSelfOwnedReceiver(std::make_unique<SpeechRecognitionDispatcherHost>(
+                                  render_process_id, render_frame_id),
+                              std::move(receiver));
 }
 
 SpeechRecognitionDispatcherHost::~SpeechRecognitionDispatcherHost() {}
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.h b/content/browser/speech/speech_recognition_dispatcher_host.h
index 2137385c..e373c23 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -14,7 +14,7 @@
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/speech_recognition_event_listener.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "third_party/blink/public/mojom/speech/speech_recognizer.mojom.h"
 
 namespace network {
@@ -34,9 +34,10 @@
  public:
   SpeechRecognitionDispatcherHost(int render_process_id, int render_frame_id);
   ~SpeechRecognitionDispatcherHost() override;
-  static void Create(int render_process_id,
-                     int render_frame_id,
-                     blink::mojom::SpeechRecognizerRequest request);
+  static void Create(
+      int render_process_id,
+      int render_frame_id,
+      mojo::PendingReceiver<blink::mojom::SpeechRecognizer> receiver);
   base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
 
   // blink::mojom::SpeechRecognizer implementation
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 8d1c6e1..ffedfdb 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -351,18 +351,24 @@
                                             excluded_cookie.cookie.IsSecure())
             .possibly_invalid_spec();
 
-    if (excluded_cookie.status ==
-        net::CanonicalCookie::CookieInclusionStatus::
-            EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX) {
-      samesite_treated_as_lax_cookies = true;
+    net::CanonicalCookie::CookieInclusionStatus::WarningReason warning =
+        excluded_cookie.status.warning();
+    switch (warning) {
+      case net::CanonicalCookie::CookieInclusionStatus::
+          WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT:
+        samesite_treated_as_lax_cookies = true;
+        break;
+      case net::CanonicalCookie::CookieInclusionStatus::
+          WARN_SAMESITE_NONE_INSECURE:
+        samesite_none_insecure_cookies = true;
+        break;
+      // TODO(crbug.com/990439): Add messages for Lax-Allow-Unsafe intervention.
+      default:
+        break;
     }
-    if (excluded_cookie.status == net::CanonicalCookie::CookieInclusionStatus::
-                                      EXCLUDE_SAMESITE_NONE_INSECURE) {
-      samesite_none_insecure_cookies = true;
-    }
+
     if (emit_messages) {
-      root_frame_host->AddSameSiteCookieDeprecationMessage(
-          cookie_url, excluded_cookie.status);
+      root_frame_host->AddSameSiteCookieDeprecationMessage(cookie_url, warning);
     }
   }
 
@@ -388,32 +394,28 @@
   }
 
   for (const auto& cookie_and_status : cookie_list) {
-    switch (cookie_and_status.status) {
-      case net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_USER_PREFERENCES:
-        for (const GlobalFrameRoutingId& id : destinations) {
-          WebContents* web_contents = GetWebContentsForStoragePartition(
-              id.child_id, id.frame_routing_id);
-          if (!web_contents)
-            continue;
-          web_contents->OnCookieChange(url, site_for_cookies,
-                                       cookie_and_status.cookie,
-                                       /* blocked_by_policy =*/true);
-        }
-        break;
-      case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-        for (const GlobalFrameRoutingId& id : destinations) {
-          WebContents* web_contents = GetWebContentsForStoragePartition(
-              id.child_id, id.frame_routing_id);
-          if (!web_contents)
-            continue;
-          web_contents->OnCookieChange(url, site_for_cookies,
-                                       cookie_and_status.cookie,
-                                       /* blocked_by_policy =*/false);
-        }
-        break;
-      default:
-        break;
+    if (cookie_and_status.status.HasExclusionReason(
+            net::CanonicalCookie::CookieInclusionStatus::
+                EXCLUDE_USER_PREFERENCES)) {
+      for (const GlobalFrameRoutingId& id : destinations) {
+        WebContents* web_contents =
+            GetWebContentsForStoragePartition(id.child_id, id.frame_routing_id);
+        if (!web_contents)
+          continue;
+        web_contents->OnCookieChange(url, site_for_cookies,
+                                     cookie_and_status.cookie,
+                                     /* blocked_by_policy =*/true);
+      }
+    } else if (cookie_and_status.status.IsInclude()) {
+      for (const GlobalFrameRoutingId& id : destinations) {
+        WebContents* web_contents =
+            GetWebContentsForStoragePartition(id.child_id, id.frame_routing_id);
+        if (!web_contents)
+          continue;
+        web_contents->OnCookieChange(url, site_for_cookies,
+                                     cookie_and_status.cookie,
+                                     /* blocked_by_policy =*/false);
+      }
     }
   }
 }
@@ -431,16 +433,12 @@
 
   net::CookieList accepted, blocked;
   for (auto& cookie_and_status : cookie_list) {
-    switch (cookie_and_status.status) {
-      case net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_USER_PREFERENCES:
-        blocked.push_back(std::move(cookie_and_status.cookie));
-        break;
-      case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-        accepted.push_back(std::move(cookie_and_status.cookie));
-        break;
-      default:
-        break;
+    if (cookie_and_status.status.HasExclusionReason(
+            net::CanonicalCookie::CookieInclusionStatus::
+                EXCLUDE_USER_PREFERENCES)) {
+      blocked.push_back(std::move(cookie_and_status.cookie));
+    } else if (cookie_and_status.status.IsInclude()) {
+      accepted.push_back(std::move(cookie_and_status.cookie));
     }
   }
 
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index ca8d1bde..d07c963 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -178,7 +178,7 @@
   }
 
   void SetCookieCallback(CanonicalCookie::CookieInclusionStatus result) {
-    ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, result);
+    ASSERT_TRUE(result.IsInclude());
     await_completion_.Notify();
   }
 
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 7de3810..d2b7833 100644
--- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -724,8 +724,9 @@
   }
 };
 
+// The test cert has expired. crbug.com/999419
 IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerRealCertVerifierBrowserTest,
-                       Basic) {
+                       DISABLED_Basic) {
   InstallMockCertChainInterceptor();
   InstallUrlInterceptor(GURL("https://test.example.org/test/"),
                         "content/test/data/sxg/fallback.html");
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index c9ab16e..0951c26 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -574,6 +574,9 @@
   if (base::FeatureList::IsEnabled(blink::features::kStorageAccessAPI)) {
     WebRuntimeFeatures::EnableFeatureFromString("StorageAccessAPI", true);
   }
+
+  WebRuntimeFeatures::EnablePointerLockOptions(
+      base::FeatureList::IsEnabled(features::kPointerLockOptions));
 }
 
 }  // namespace
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 5aa89ae..e6881a1c 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -149,6 +149,7 @@
 void WebContentsDelegate::CreateSmsPrompt(
     RenderFrameHost* host,
     const url::Origin& origin,
+    const std::string& one_time_code,
     base::OnceCallback<void()> on_confirm,
     base::OnceCallback<void()> on_cancel) {}
 
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 01db385..70afb53 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -411,6 +411,7 @@
   // Creates an info bar for the user to control the receiving of the SMS.
   virtual void CreateSmsPrompt(RenderFrameHost*,
                                const url::Origin&,
+                               const std::string& one_time_code,
                                base::OnceCallback<void()> on_confirm,
                                base::OnceCallback<void()> on_cancel);
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index cafa5c3..1dda5be 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -737,8 +737,8 @@
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Start streaming scripts on script preload.
-const base::Feature kScriptStreamingOnPreload{
-    "ScriptStreamingOnPreload", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kScriptStreamingOnPreload{"ScriptStreamingOnPreload",
+                                              base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether the Trusted Types API is available.
 const base::Feature kTrustedDOMTypes{"TrustedDOMTypes",
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index d11106b..0e207a0 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1834,9 +1834,8 @@
       *cc.get(), url.scheme(), options,
       base::BindOnce(
           [](bool* result, base::RunLoop* run_loop,
-             net::CanonicalCookie::CookieInclusionStatus success) {
-            *result = (success ==
-                       net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+             net::CanonicalCookie::CookieInclusionStatus set_cookie_status) {
+            *result = set_cookie_status.IsInclude();
             run_loop->Quit();
           },
           &result, &run_loop));
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 33810df2..88a1726 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1857,7 +1857,6 @@
     // Set it to be our thread's task runner instead.
     params.compositor_task_runner = main_thread_compositor_task_runner_;
   }
-  params.enable_surface_synchronization = true;
   if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
     params.hit_test_data_provider =
         std::make_unique<viz::HitTestDataProviderDrawQuad>(
@@ -1951,14 +1950,12 @@
   if (GetContentClient()->UsingSynchronousCompositing()) {
     RenderWidget* widget = RenderWidget::FromRoutingID(widget_routing_id);
     if (widget) {
-      // TODO(ericrk): Remove this check when SurfaceSynchronization is always
-      // enabled, and collapse with non-webview registration below.
-      if (features::IsSurfaceSynchronizationEnabled()) {
-        frame_sink_provider_->RegisterRenderFrameMetadataObserver(
-            widget_routing_id,
-            std::move(render_frame_metadata_observer_client_request),
-            std::move(render_frame_metadata_observer_ptr));
-      }
+      // TODO(ericrk): Collapse with non-webview registration below.
+      frame_sink_provider_->RegisterRenderFrameMetadataObserver(
+          widget_routing_id,
+          std::move(render_frame_metadata_observer_client_request),
+          std::move(render_frame_metadata_observer_ptr));
+
       std::move(callback).Run(std::make_unique<SynchronousLayerTreeFrameSink>(
           std::move(context_provider), std::move(worker_context_provider),
           compositor_task_runner_, GetGpuMemoryBufferManager(),
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index f15823dd..4a64f4e0 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -191,17 +191,29 @@
 
 class WebWidgetLockTarget : public content::MouseLockDispatcher::LockTarget {
  public:
-  explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
-      : webwidget_(webwidget) {}
+  explicit WebWidgetLockTarget(RenderWidget* render_widget)
+      : render_widget_(render_widget) {}
 
   void OnLockMouseACK(bool succeeded) override {
+    // TODO(https://crbug.com/995981): Once RenderWidget and WebWidget lifetimes
+    // are synchronized, we should remove these conditionals.
+    WebWidget* web_widget = render_widget_->GetWebWidget();
+    if (!web_widget)
+      return;
+
     if (succeeded)
-      webwidget_->DidAcquirePointerLock();
+      web_widget->DidAcquirePointerLock();
     else
-      webwidget_->DidNotAcquirePointerLock();
+      web_widget->DidNotAcquirePointerLock();
   }
 
-  void OnMouseLockLost() override { webwidget_->DidLosePointerLock(); }
+  void OnMouseLockLost() override {
+    WebWidget* web_widget = render_widget_->GetWebWidget();
+    if (!web_widget)
+      return;
+
+    web_widget->DidLosePointerLock();
+  }
 
   bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override {
     // The WebWidget handles mouse lock in Blink's handleInputEvent().
@@ -209,7 +221,8 @@
   }
 
  private:
-  blink::WebWidget* webwidget_;
+  // The RenderWidget owns this instance and is guaranteed to outlive it.
+  RenderWidget* render_widget_;
 };
 
 class ScopedUkmRafAlignedInputTimer {
@@ -559,8 +572,7 @@
   show_callback_ = std::move(show_callback);
 
   webwidget_internal_ = web_widget;
-  webwidget_mouse_lock_target_.reset(
-      new WebWidgetLockTarget(webwidget_internal_));
+  webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(this));
   mouse_lock_dispatcher_.reset(new RenderWidgetMouseLockDispatcher(this));
 
   RenderThread::Get()->AddRoute(routing_id_, this);
@@ -697,11 +709,14 @@
 void RenderWidget::OnClose() {
   DCHECK(popup_ || pepper_fullscreen_);
 
-  // It is always safe to synchronously destroy this object from an IPC message.
-  // That's because the IPC message is asynchronous, which means it can never be
-  // called from a nested context.
   PrepareForClose();
-  Close(base::WrapUnique(this));
+
+  // IPCs can be invoked from nested message loops. We must dispatch this
+  // task non-nested to avoid re-entrancy issues.
+  GetCleanupTaskRunner()->PostNonNestableTask(
+      FROM_HERE,
+      base::BindOnce(&RenderWidget::Close, close_weak_ptr_factory_.GetWeakPtr(),
+                     base::WrapUnique(this)));
 }
 
 void RenderWidget::PrepareForClose() {
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index cd57753..b05042c 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -472,9 +472,8 @@
   void Shutdown(std::unique_ptr<RenderWidget> widget) {
     shutdown_ = true;
 
-    // OnClose takes ownership and destroys the widget.
-    widget->OnClose();
-    widget.release();
+    widget->PrepareForClose();
+    widget->Close(std::move(widget));
   }
 
  protected:
diff --git a/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt b/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt
new file mode 100644
index 0000000..bdc6a4a
--- /dev/null
+++ b/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt
@@ -0,0 +1,6 @@
+rootWebArea
+++genericContainer
+++++link
+++++++genericContainer invisible
+++++staticText name='done'
+++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/html/area-serialization-crash.html b/content/test/data/accessibility/html/area-serialization-crash.html
new file mode 100644
index 0000000..2598e6e
--- /dev/null
+++ b/content/test/data/accessibility/html/area-serialization-crash.html
@@ -0,0 +1,23 @@
+<!--
+@WAIT-FOR:done
+
+This is a regression test for a bug that crashes during blink serialization
+when determining if an area element is a descendant of an anchor.
+-->
+<!DOCTYPE html>
+<html>
+<script>
+  window.onload = () => {
+    var canvas = document.createElement('canvas');
+    canvas.id = 'canvas';
+    canvas.hidden = true;
+
+    var area = document.createElement('area');
+    area.appendChild(canvas);
+    document.body.appendChild(area);
+    document.body.appendChild(document.createTextNode('done'));
+  };
+</script>
+<body>
+</body>
+</html>
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index fa168f73..447ab10e 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -50,8 +50,8 @@
 # ========================
 
 crbug.com/953120 conformance/programs/program-handling.html [ Failure ]
-# TODO(kbr): restore suppression for Android / Qualcomm below after this is fixed.
-crbug.com/949249 conformance2/extensions/ovr_multiview2.html [ Failure ]
+
+crbug.com/949249 [ passthrough ] conformance2/extensions/ovr_multiview2.html [ Failure ]
 
 # Marking a test as failing on all platforms.
 crbug.com/985032 conformance2/glsl3/sampler-array-indexing.html [ Failure ]
@@ -160,6 +160,7 @@
 crbug.com/951628 [ win no-passthrough ] conformance/rendering/blending.html [ Failure ]
 
 # Win / D3D11 backend
+# This test seems to flakily pass sometimes (at least on AMD and Intel).
 crbug.com/angleproject/3388 [ win d3d11 ] conformance2/uniforms/large-uniform-buffers.html [ Failure ]
 
 # Win / NVidia
@@ -236,6 +237,7 @@
 crbug.com/992457 [ win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html [ RetryOnFailure ]
 
 # Recent AMD drivers seem to have a regression with 3D textures.
+# (Some of these tests seem to occasionally pass unexpectedly.)
 crbug.com/angleproject/2424 [ d3d11 win amd ] conformance2/textures/canvas_sub_rectangle/tex-3d-* [ Failure ]
 crbug.com/angleproject/2424 [ d3d11 win amd ] conformance2/textures/image/tex-3d-* [ Failure ]
 crbug.com/angleproject/2424 [ d3d11 win amd ] conformance2/textures/image_data/tex-3d-* [ Failure ]
@@ -674,16 +676,13 @@
 
 # Qualcomm (Pixel 2) failures
 crbug.com/906737 [ android qualcomm ] conformance/extensions/webgl-compressed-texture-astc.html [ Failure ]
-# TODO(kbr): uncomment after http://crbug.com/949249 fixed
-# crbug.com/906739 [ android qualcomm ] conformance2/extensions/ovr_multiview2.html [ Failure ]
-crbug.com/906742 [ android qualcomm ] conformance2/glsl3/compare-structs-containing-arrays.html [ Failure ]
+crbug.com/906742 [ android qualcomm no-passthrough ] conformance2/glsl3/compare-structs-containing-arrays.html [ Failure ]
 crbug.com/906735 [ android qualcomm ] conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ]
 crbug.com/981216 [ android qualcomm-adreno-(tm)-540 ] deqp/functional/gles3/fbocolorbuffer/tex2d_01.html [ RetryOnFailure ]
 crbug.com/949321 [ android qualcomm ] deqp/functional/gles3/framebufferblit/default_framebuffer_02.html [ RetryOnFailure ]
 
 # This test is failing on Android Pixel 2 and 3 (Qualcomm)
 # Seems to be an OpenGL ES bug.
-crbug.com/945903 [ android qualcomm ] conformance2/rendering/vertex-id.html [ Failure ]
 crbug.com/695742 [ android qualcomm no-angle ] deqp/functional/gles3/multisample.html [ RetryOnFailure ]
 
 # This test is flaky but can fail three times in a row so it must be
@@ -704,7 +703,6 @@
 crbug.com/906724 [ android opengles ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
 
 crbug.com/angleproject/3684 [ android opengles ] conformance2/renderbuffers/multisample-with-full-sample-counts.html [ Failure ]
-crbug.com/983142 [ android opengles ] conformance2/textures/misc/tex-storage-compressed-formats.html [ Failure ]
 crbug.com/967410 [ android opengles ] conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html [ Failure ]
 crbug.com/967410 [ android opengles ] conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html [ Failure ]
 crbug.com/967410 [ android opengles ] conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 330cfab..2b6f156 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -43,7 +43,6 @@
 crbug.com/849576 [ no-passthrough ] WebglExtension_KHR_parallel_shader_compile [ Skip ]
 
 # Extensions not available under D3D9
-[ win d3d9 ] WebglExtension_EXT_float_blend [ Failure ]
 [ win d3d9 ] WebglExtension_EXT_sRGB [ Failure ]
 crbug.com/867718 [ win d3d9 ] WebglExtension_EXT_disjoint_timer_query [ Failure ]
 [ win amd d3d9 ] WebglExtension_WEBGL_depth_texture [ Failure ]
@@ -51,13 +50,18 @@
 
 # Android general
 [ android ] WebglExtension_EXT_frag_depth [ Failure ]
-[ android ] WebglExtension_EXT_float_blend [ Failure ]
-[ android ] WebglExtension_EXT_shader_texture_lod [ Failure ]
-[ android ] WebglExtension_WEBGL_compressed_texture_astc [ Failure ]
 [ android ] WebglExtension_WEBGL_compressed_texture_pvrtc [ Failure ]
 [ android ] WebglExtension_WEBGL_compressed_texture_s3tc [ Failure ]
-[ android ] WebglExtension_WEBGL_depth_texture [ Failure ]
-[ android ] WebglExtension_WEBGL_draw_buffers [ Failure ]
+
+# Android hardware-specific
+[ android qualcomm ] WebglExtension_EXT_float_blend [ Failure ]
+[ android qualcomm ] WebglExtension_EXT_shader_texture_lod [ Failure ]
+[ android qualcomm ] WebglExtension_WEBGL_draw_buffers [ Failure ]
+[ android qualcomm-adreno-(tm)-330 no-passthrough ] WebglExtension_OES_texture_float_linear [ Failure ]
+[ android qualcomm-adreno-(tm)-418 ] WebglExtension_WEBGL_depth_texture [ Failure ]
+[ android qualcomm-adreno-(tm)-418 ] WebglExtension_EXT_sRGB [ Failure ]
+[ android qualcomm-adreno-(tm)-420 ] WebglExtension_EXT_sRGB [ Failure ]
+[ android qualcomm-adreno-(tm)-430 ] WebglExtension_EXT_sRGB [ Failure ]
 
 # ========================
 # Conformance expectations
@@ -70,13 +74,7 @@
 
 # Nvidia bugs fixed in latest driver
 # TODO(http://crbug.com/887241): Upgrade the drivers on the bots.
-crbug.com/772651 [ linux nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html [ Failure ]
 crbug.com/905370 [ android nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html [ Failure ]
-crbug.com/772651 [ nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html [ Failure ]
-crbug.com/798117 [ win nvidia vulkan ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ]
-crbug.com/798117 [ linux nvidia ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ]
-crbug.com/798117 [ android nvidia ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ]
-crbug.com/792210 [ nvidia ] conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html [ Failure ]
 
 # This test needs to be rewritten to measure its expected
 # performance; it's currently too flaky even on release bots.
@@ -97,7 +95,7 @@
 crbug.com/979444 [ linux ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ]
 crbug.com/979444 [ mac no-passthrough ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ]
 crbug.com/979444 [ win ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ]
-crbug.com/979444 [ android no-angle ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ]
+crbug.com/979444 [ android ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ]
 
 # Win / AMD / Passthrough command decoder / D3D11
 crbug.com/685232 [ win amd d3d11 passthrough ] conformance/textures/misc/copytexsubimage2d-subrects.html [ RetryOnFailure ]
@@ -179,7 +177,6 @@
 
 # Win / AMD D3D9 failures
 crbug.com/475095 [ win amd d3d9 ] conformance/extensions/angle-instanced-arrays.html [ Failure ]
-crbug.com/475095 [ win amd d3d9 ] conformance/rendering/more-than-65536-indices.html [ Failure ]
 
 # Win / D3D9 failures
 # Skipping these two tests because they're causing assertion failures.
@@ -207,14 +204,12 @@
 # Win / OpenGL / AMD failures
 crbug.com/649824 [ win amd opengl ] conformance/attribs/gl-bindAttribLocation-aliasing.html [ Skip ]
 crbug.com/angleproject/1007 [ win amd opengl ] conformance/glsl/misc/shader-struct-scope.html [ Skip ]
-crbug.com/angleproject/1007 [ win amd opengl ] conformance/glsl/misc/struct-nesting-of-variable-names.html [ Failure ]
 crbug.com/angleproject/1506 [ win amd opengl ] conformance/rendering/clipping-wide-points.html [ Failure ]
 
 # AMD RX 550 Failures
 crbug.com/950123 [ win amd-0x699f opengl ] conformance/glsl/bugs/gl-fragcoord-multisampling-bug.html [ Skip ]
 crbug.com/950123 [ win amd-0x699f opengl ] conformance/glsl/misc/fragcolor-fragdata-invariant.html [ Skip ]
 crbug.com/950123 [ win amd-0x699f opengl ] conformance/glsl/samplers/glsl-function-texture2dprojlod.html [ Skip ]
-crbug.com/951771 [ win amd-0x699f opengl ] conformance/reading/read-pixels-test.html [ Failure ]
 crbug.com/950123 [ win amd-0x699f opengl ] conformance/rendering/line-rendering-quality.html [ Skip ]
 crbug.com/952887 [ win amd-0x699f opengl passthrough ] conformance/rendering/multisample-corruption.html [ Skip ]
 
@@ -232,32 +227,12 @@
 crbug.com/angleproject/2192 [ win d3d9 passthrough ] conformance/textures/webgl_canvas/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
 
 # Vulkan / Win / Passthrough command decoder
-crbug.com/angleproject/2708 [ win vulkan passthrough ] conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html [ Failure ]
-crbug.com/angleproject/2929 [ win vulkan passthrough ] conformance/canvas/canvas-test.html [ Failure ]
-crbug.com/angleproject/2918 [ win vulkan passthrough ] conformance/canvas/draw-static-webgl-to-multiple-canvas-test.html [ Failure ]
-crbug.com/angleproject/2918 [ win vulkan passthrough ] conformance/canvas/draw-webgl-to-canvas-test.html [ Failure ]
-crbug.com/angleproject/2913 [ win vulkan passthrough ] conformance/context/context-attribute-preserve-drawing-buffer.html [ Failure ]
 crbug.com/angleproject/3469 [ win vulkan passthrough ] conformance/extensions/webgl-draw-buffers.html [ Failure ]
-crbug.com/angleproject/2987 [ win vulkan passthrough ] conformance/misc/uninitialized-test.html [ Failure ]
-crbug.com/angleproject/2911 [ win vulkan passthrough ] conformance/more/functions/copyTexSubImage2D.html [ Failure ]
 crbug.com/angleproject/2916 [ win vulkan passthrough ] conformance/offscreencanvas/context-lost-restored-worker.html [ Failure ]
 crbug.com/angleproject/2916 [ win vulkan passthrough ] conformance/offscreencanvas/context-lost-restored.html [ Failure ]
-crbug.com/angleproject/2909 [ win vulkan passthrough ] conformance/ogles/GL/faceforward/faceforward_001_to_006.html [ Failure ]
 crbug.com/angleproject/3788 [ win vulkan passthrough ] conformance/reading/read-pixels-test.html [ RetryOnFailure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/renderbuffers/depth-renderbuffer-initialization.html [ Failure ]
-crbug.com/angleproject/2910 [ win vulkan passthrough ] conformance/renderbuffers/framebuffer-object-attachment.html [ Failure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ]
-crbug.com/angleproject/0 [ win vulkan passthrough ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ]
-crbug.com/angleproject/2919 [ win vulkan passthrough ] conformance/rendering/preservedrawingbuffer-leak.html [ Failure ]
 crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/copy-tex-image-and-sub-image-2d.html [ Failure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html [ Failure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/copytexsubimage2d-subrects.html [ Failure ]
-crbug.com/angleproject/2920 [ win vulkan passthrough ] conformance/textures/misc/gl-pixelstorei.html [ Failure ]
-crbug.com/angleproject/2912 [ win vulkan passthrough ] conformance/textures/misc/tex-image-and-sub-image-2d-with-array-buffer-view.html [ Failure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/tex-image-webgl.html [ Failure ]
-crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/texture-attachment-formats.html [ Failure ]
 crbug.com/angleproject/2914 [ win vulkan passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ]
-crbug.com/angleproject/2913 [ win vulkan passthrough ] conformance/textures/misc/texture-hd-dpi.html [ Failure ]
 crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/texture-mips.html [ Failure ]
 
 # Note: the following test crashes so it's skipped.  http://anglebug.com/3352
@@ -282,8 +257,6 @@
 crbug.com/angleproject/3741 [ win vulkan passthrough ] conformance/textures/misc/mipmap-fbo.html [ RetryOnFailure ]
 
 # Vulkan / Win / NVIDIA / Passthrough command decoder
-crbug.com/angleproject/2918 [ win nvidia vulkan passthrough ] conformance/canvas/to-data-url-test.html [ Failure ]
-crbug.com/angleproject/2922 [ win nvidia vulkan passthrough ] conformance/context/premultiplyalpha-test.html [ Failure ]
 crbug.com/963205 [ win nvidia vulkan passthrough ] conformance/extensions/webgl-compressed-texture-s3tc-srgb.html [ Failure ]
 crbug.com/964321 [ win nvidia vulkan passthrough ] conformance/extensions/webgl-compressed-texture-s3tc.html [ RetryOnFailure ]
 crbug.com/963217 [ win nvidia vulkan passthrough ] conformance/glsl/samplers/glsl-function-texture2dprojlod.html [ Failure ]
@@ -296,28 +269,22 @@
 crbug.com/angleproject/2930 [ win nvidia vulkan passthrough ] conformance/textures/misc/texture-size-cube-maps.html [ Failure ]
 crbug.com/angleproject/3481 [ win nvidia vulkan passthrough ] conformance/textures/misc/texture-sub-image-cube-maps.html [ Failure ]
 crbug.com/angleproject/2926 [ win nvidia vulkan passthrough ] deqp/data/gles2/shaders/conversions.html [ Failure ]
-crbug.com/979641 [ win nvidia vulkan passthrough ] conformance/canvas/viewport-unchanged-upon-resize.html [ Failure ]
+crbug.com/angleproject/2909 [ win nvidia vulkan passthrough ] conformance/ogles/GL/faceforward/faceforward_001_to_006.html [ Failure ]
+crbug.com/angleproject/2722 [ win nvidia vulkan passthrough ] conformance/textures/misc/texture-attachment-formats.html [ Failure ]
+crbug.com/angleproject/2722 [ win nvidia vulkan passthrough ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ]
+crbug.com/angleproject/2987 [ win7 nvidia vulkan passthrough ] conformance/misc/uninitialized-test.html [ Failure ]
 
 # Vulkan / Win / AMD / Passthrough command decoder
-crbug.com/angleproject/2931 [ win amd vulkan passthrough ] conformance/buffers/buffer-data-dynamic-delay.html [ Failure ]
-crbug.com/angleproject/2918 [ win amd vulkan passthrough ] conformance/canvas/to-data-url-test.html [ Failure ]
-crbug.com/angleproject/2922 [ win amd vulkan passthrough ] conformance/context/premultiplyalpha-test.html [ Failure ]
 crbug.com/angleproject/2722 [ win amd vulkan passthrough ] conformance/rendering/clipping-wide-points.html [ Failure ]
 crbug.com/angleproject/2926 [ win amd vulkan passthrough ] deqp/data/gles2/shaders/conversions.html [ Failure ]
 crbug.com/angleproject/2926 [ win amd vulkan passthrough ] deqp/data/gles2/shaders/linkage.html [ Failure ]
 crbug.com/931016 [ win amd vulkan passthrough ] conformance/textures/image_bitmap_from_canvas/tex-2d-luminance* [ Failure ]
 crbug.com/931016 [ win amd vulkan passthrough ] conformance/textures/image_bitmap_from_canvas/tex-2d-rgb* [ Failure ]
-crbug.com/angleproject/3343 [ win amd vulkan passthrough ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ]
-crbug.com/857644 [ win passthrough amd vulkan ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ]
-crbug.com/957644 [ win passthrough amd vulkan ] conformance/glsl/samplers/glsl-function-texture2dprojlod.html [ Failure ]
 crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
 crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
-crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ]
-crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ]
-crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ]
-crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ]
-crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ]
 
+# Vulkan / Win / Intel / Passthrough command decoder
+crbug.com/angleproject/2909 [ win intel vulkan passthrough ] conformance/ogles/GL/faceforward/faceforward_001_to_006.html [ Failure ]
 
 ####################
 # Mac failures     #
@@ -415,13 +382,9 @@
 crbug.com/918995 [ linux debug nvidia-0x1cb3 ] conformance/rendering/polygon-offset.html [ RetryOnFailure ]
 
 # AMD
-crbug.com/844311 [ linux amd ] conformance/glsl/misc/fragcolor-fragdata-invariant.html [ Failure ]
 crbug.com/550989 [ linux amd ] conformance/more/functions/uniformi.html [ RetryOnFailure ]
 crbug.com/642822 [ linux amd ] conformance/rendering/clipping-wide-points.html [ Failure ]
 
-# AMD Radeon 6450 and/or R7 240
-crbug.com/479260 [ linux amd no-angle ] conformance/extensions/angle-instanced-arrays.html [ Failure ]
-
 # Linux passthrough AMD
 crbug.com/960808 [ linux amd passthrough ] conformance/glsl/misc/shader-with-non-reserved-words.html [ Failure ]
 crbug.com/998498 [ linux amd passthrough ] conformance/textures/misc/tex-input-validation.html [ Failure ]
@@ -435,13 +398,12 @@
 # Android failures #
 ####################
 
-crbug.com/903903 [ android ] conformance/glsl/bugs/sampler-array-struct-function-arg.html [ Failure ]
+crbug.com/903903 [ android qualcomm ] conformance/glsl/bugs/sampler-array-struct-function-arg.html [ Failure ]
 crbug.com/478572 [ android qualcomm ] conformance/glsl/bugs/sequence-operator-evaluation-order.html [ Failure ]
 
 # The following test is very slow and therefore times out on Android bot.
 [ android ] conformance/rendering/multisample-corruption.html [ Skip ]
 crbug.com/679697 [ android qualcomm no-passthrough ] conformance/textures/misc/copytexsubimage2d-large-partial-copy-corruption.html [ Failure ]
-crbug.com/951628 [ android no-passthrough ] conformance/rendering/blending.html [ Failure ]
 
 # The following WebView crashes are causing problems with further
 # tests in the suite, so skip them for now.
@@ -484,7 +446,6 @@
 crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/misc/shader-with-vec4-vec3-vec4-conditional.html [ Failure ]
 crbug.com/611943 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/misc/struct-equals.html [ Failure ]
 crbug.com/478572 [ android qualcomm-adreno-(tm)-330 ] deqp/data/gles2/shaders/linkage.html [ Failure ]
-[ android qualcomm-adreno-(tm)-330 no-passthrough ] WebglExtension_OES_texture_float_linear [ Failure ]
 crbug.com/678850 [ android qualcomm-adreno-(tm)-330 ] conformance/more/functions/vertexAttribPointerBadArgs.html [ Failure ]
 crbug.com/678850 [ android qualcomm-adreno-(tm)-330 ] conformance/attribs/gl-vertexattribpointer.html [ Failure ]
 crbug.com/709704 [ android qualcomm-adreno-(tm)-330 ] conformance/glsl/bugs/varying-arrays-should-not-be-reversed.html [ Failure ]
@@ -523,8 +484,8 @@
 crbug.com/891456 [ android qualcomm-adreno-(tm)-418 ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html [ RetryOnFailure ]
 crbug.com/934545 [ android android-chromium qualcomm-adreno-(tm)-418 ] conformance/textures/misc/texture-npot-video.html [ RetryOnFailure ]
 crbug.com/610951 [ android qualcomm-adreno-(tm)-418 ] conformance/uniforms/uniform-samplers-test.html [ Skip ]
-crbug.com/610951 [ android qualcomm-adreno-(tm)-418 ] WebglExtension_EXT_sRGB [ Failure ]
 crbug.com/914631 [ android qualcomm-adreno-(tm)-418 passthrough ] conformance/limits/gl-max-texture-dimensions.html [ RetryOnFailure ]
+crbug.com/951628 [ android qualcomm-adreno-(tm)-418 no-passthrough ] conformance/rendering/blending.html [ Failure ]
 
 # Nexus 6 (Adreno 420) and 6P (Adreno 430)
 crbug.com/499555 [ android qualcomm-adreno-(tm)-420 ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ]
@@ -555,13 +516,9 @@
 crbug.com/499555 [ android qualcomm-adreno-(tm)-420 no-passthrough ] conformance/textures/misc/copy-tex-image-and-sub-image-2d.html [ Failure ]
 crbug.com/663071 [ android qualcomm-adreno-(tm)-430 ] conformance/uniforms/uniform-samplers-test.html [ Skip ]
 crbug.com/693135 [ android qualcomm-adreno-(tm)-420 ] conformance/offscreencanvas/context-attribute-preserve-drawing-buffer.html [ Failure ]
-[ qualcomm-adreno-(tm)-420 android ] WebglExtension_EXT_sRGB [ Failure ]
-[ qualcomm-adreno-(tm)-430 android ] WebglExtension_EXT_sRGB [ Failure ]
 crbug.com/angleproject/2046 [ android qualcomm-adreno-(tm)-420 ] conformance/glsl/misc/uninitialized-local-global-variables.html [ Failure ]
 
 # Android NVIDIA: Nexus 9 and/or Shield TV
-crbug.com/478572 [ android nvidia ] deqp/data/gles2/shaders/functions.html [ Failure ]
-crbug.com/606096 [ android nvidia ] conformance/glsl/bugs/multiplication-assignment.html [ Failure ]
 crbug.com/912161 [ android nvidia ] conformance/glsl/constructors/glsl-construct-ivec4.html [ RetryOnFailure ]
 crbug.com/912161 [ android nvidia ] conformance/glsl/constructors/glsl-construct-mat2.html [ RetryOnFailure ]
 crbug.com/891456 [ android nvidia ] conformance/extensions/oes-texture-float-with-video.html [ RetryOnFailure ]
@@ -580,13 +537,11 @@
 
 # Android ANGLE GLES
 crbug.com/981579 [ android opengles ] conformance/textures/misc/tex-video-using-tex-unit-non-zero.html [ RetryOnFailure ]
-crbug.com/981579 [ android android-chromium opengles ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ]
 crbug.com/906724 [ android opengles ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
 crbug.com/906724 [ android opengles ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
 # TODO(crbug.com/979444, crbug.com/986808): once this is passing on
 # the passthrough command decoder, simplify the RetryOnFailure
 # expectation at the top of this file to just not declare any OS.
-crbug.com/986808 [ android opengles ] conformance/textures/misc/texture-corner-case-videos.html [ Failure ]
 
 # Misc failures
 crbug.com/angleproject/2988 [ android opengles ] conformance/context/context-size-change.html [ Failure ]
diff --git a/device/fido/hid/fido_hid_device.cc b/device/fido/hid/fido_hid_device.cc
index 6f01df9..a90c2a7 100644
--- a/device/fido/hid/fido_hid_device.cc
+++ b/device/fido/hid/fido_hid_device.cc
@@ -361,6 +361,14 @@
     return;
   }
 
+  if (!message->MessageComplete()) {
+    // Continue reading additional packets.
+    connection_->Read(base::BindOnce(&FidoHidDevice::OnReadContinuation,
+                                     weak_factory_.GetWeakPtr(),
+                                     std::move(*message)));
+    return;
+  }
+
   // Received a message from a different channel, so try again.
   if (channel_id_ != message->channel_id()) {
     ReadMessage();
@@ -387,14 +395,6 @@
       NOTREACHED();
   }
 
-  if (!message->MessageComplete()) {
-    // Continue reading additional packets.
-    connection_->Read(base::BindOnce(&FidoHidDevice::OnReadContinuation,
-                                     weak_factory_.GetWeakPtr(),
-                                     std::move(*message)));
-    return;
-  }
-
   MessageReceived(std::move(*message));
 }
 
@@ -413,7 +413,11 @@
   }
   DCHECK(buf);
 
-  message.AddContinuationPacket(*buf);
+  if (!message.AddContinuationPacket(*buf)) {
+    Transition(State::kDeviceError);
+    return;
+  }
+
   if (!message.MessageComplete()) {
     connection_->Read(base::BindOnce(&FidoHidDevice::OnReadContinuation,
                                      weak_factory_.GetWeakPtr(),
@@ -421,6 +425,12 @@
     return;
   }
 
+  // Received a message from a different channel, so try again.
+  if (channel_id_ != message.channel_id()) {
+    ReadMessage();
+    return;
+  }
+
   MessageReceived(std::move(message));
 }
 
diff --git a/device/fido/hid/fido_hid_device_unittest.cc b/device/fido/hid/fido_hid_device_unittest.cc
index 49fb61a..b659797 100644
--- a/device/fido/hid/fido_hid_device_unittest.cc
+++ b/device/fido/hid/fido_hid_device_unittest.cc
@@ -387,6 +387,130 @@
   EXPECT_THAT(*value, testing::ElementsAreArray(kU2fMockResponseData));
 }
 
+// InvertChannelID inverts all the bits in the given channel ID. This is used to
+// create a channel ID that will not be equal to the expected channel ID.
+std::array<uint8_t, 4> InvertChannelID(
+    const std::array<uint8_t, 4> channel_id) {
+  std::array<uint8_t, 4> ret;
+  memcpy(ret.data(), channel_id.data(), ret.size());
+  for (size_t i = 0; i < ret.size(); i++) {
+    ret[i] ^= 0xff;
+  }
+  return ret;
+}
+
+TEST_F(FidoHidDeviceTest, TestMessageOnOtherChannel) {
+  // Test that a HID message with a different channel ID is ignored.
+  ::testing::Sequence sequence;
+  auto mock_connection = CreateHidConnectionWithHidInitExpectations(
+      kChannelId, fake_hid_manager_.get(), sequence);
+
+  // HID_CBOR request to authenticator.
+  mock_connection->ExpectHidWriteWithCommand(FidoHidDeviceCommand::kMsg);
+
+  EXPECT_CALL(*mock_connection, ReadPtr(_))
+      .InSequence(sequence)
+      // Message on wrong channel.
+      .WillOnce(Invoke([&](device::mojom::HidConnection::ReadCallback* cb) {
+        std::move(*cb).Run(
+            true, 0,
+            CreateMockResponseWithChannelId(
+                InvertChannelID(mock_connection->connection_channel_id()),
+                kHidUnknownCommandError));
+      }))
+      // Expected message on the correct channel.
+      .WillOnce(Invoke([&](device::mojom::HidConnection::ReadCallback* cb) {
+        std::move(*cb).Run(true, 0,
+                           CreateMockResponseWithChannelId(
+                               mock_connection->connection_channel_id(),
+                               kU2fMockResponseMessage));
+      }));
+
+  FidoDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
+
+  std::vector<std::unique_ptr<FidoHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
+  ASSERT_EQ(1u, u2f_devices.size());
+  auto& device = u2f_devices.front();
+
+  TestDeviceCallbackReceiver cb;
+  device->DeviceTransact(GetMockDeviceRequest(), cb.callback());
+  cb.WaitForCallback();
+  const auto& value = cb.value();
+  ASSERT_TRUE(value);
+  EXPECT_THAT(*value, testing::ElementsAreArray(kU2fMockResponseData));
+}
+
+TEST_F(FidoHidDeviceTest, TestContinuedMessageOnOtherChannel) {
+  // Test that a multi-frame HID message with a different channel ID is
+  // ignored.
+  ::testing::Sequence sequence;
+  auto mock_connection = CreateHidConnectionWithHidInitExpectations(
+      kChannelId, fake_hid_manager_.get(), sequence);
+
+  // HID_CBOR request to authenticator.
+  mock_connection->ExpectHidWriteWithCommand(FidoHidDeviceCommand::kMsg);
+
+  constexpr uint8_t kOtherChannelMsgPrefix[64] = {
+      0x83,
+      0x00,
+      // Mark reply as being 64 bytes long, which is more than a single USB
+      // frame can contain.
+      0x40,
+      0,
+  };
+
+  constexpr uint8_t kOtherChannelMsgSuffix[64] = {
+      // Continuation packet zero.
+      0x00,
+      // Contents can be anything.
+  };
+
+  EXPECT_CALL(*mock_connection, ReadPtr(_))
+      .InSequence(sequence)
+      // Beginning of a message on the wrong channel.
+      .WillOnce(Invoke([&](device::mojom::HidConnection::ReadCallback* cb) {
+        std::move(*cb).Run(
+            true, 0,
+            CreateMockResponseWithChannelId(
+                InvertChannelID(mock_connection->connection_channel_id()),
+                kOtherChannelMsgPrefix));
+      }))
+      // Continuation of the message on the wrong channel.
+      .WillOnce(Invoke([&](device::mojom::HidConnection::ReadCallback* cb) {
+        std::move(*cb).Run(
+            true, 0,
+            CreateMockResponseWithChannelId(
+                InvertChannelID(mock_connection->connection_channel_id()),
+                kOtherChannelMsgSuffix));
+      }))
+      // Expected message on the correct channel.
+      .WillOnce(Invoke([&](device::mojom::HidConnection::ReadCallback* cb) {
+        std::move(*cb).Run(true, 0,
+                           CreateMockResponseWithChannelId(
+                               mock_connection->connection_channel_id(),
+                               kU2fMockResponseMessage));
+      }));
+
+  FidoDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
+
+  std::vector<std::unique_ptr<FidoHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
+  ASSERT_EQ(1u, u2f_devices.size());
+  auto& device = u2f_devices.front();
+
+  TestDeviceCallbackReceiver cb;
+  device->DeviceTransact(GetMockDeviceRequest(), cb.callback());
+  cb.WaitForCallback();
+  const auto& value = cb.value();
+  ASSERT_TRUE(value);
+  EXPECT_THAT(*value, testing::ElementsAreArray(kU2fMockResponseData));
+}
+
 TEST_F(FidoHidDeviceTest, TestDeviceTimeoutAfterKeepAliveMessage) {
   ::testing::Sequence sequence;
   auto mock_connection = CreateHidConnectionWithHidInitExpectations(
diff --git a/device/gamepad/game_controller_data_fetcher_mac.mm b/device/gamepad/game_controller_data_fetcher_mac.mm
index e6440ec1..c1dc3db 100644
--- a/device/gamepad/game_controller_data_fetcher_mac.mm
+++ b/device/gamepad/game_controller_data_fetcher_mac.mm
@@ -6,6 +6,7 @@
 
 #include <string.h>
 
+#include "base/mac/mac_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -19,6 +20,46 @@
 
 const int kGCControllerPlayerIndexCount = 4;
 
+// Returns true if |controller| should be enumerated by this data fetcher.
+bool IsSupported(GCController* controller) {
+  // We only support the extendedGamepad profile, the basic gamepad profile
+  // appears to only be for iOS devices.
+  if (![controller extendedGamepad])
+    return false;
+
+  // In OS X 10.15, Game Controller API added support for Xbox Wireless
+  // Controller and Dualshock 4. A productCategory property was added to
+  // GCController to allow applications to detect these new categories of
+  // devices.
+  //
+  // In Chrome for Mac, Xbox Wireless Controller and Dualshock 4 are
+  // enumerated by XboxDataFetcher and GamepadPlatformDataFetcherMac,
+  // respectively. If GameControllerDataFetcherMac also enumerates these
+  // devices, it will add duplicate gamepads to the gamepad list.
+  //
+  // On macOS 10.15 or later, use the productCategory property to distinguish
+  // Xbox One and Dualshock 4 and block them from being enumerated by this
+  // data fetcher. On 10.14 or earlier, compare the |vendor_name| against
+  // known values for these devices. Once Chrome no longer supports 10.14, the
+  // |vendor_name| path may be removed.
+  if (base::mac::IsAtLeastOS10_15()) {
+    NSString* product_category =
+        [controller performSelector:@selector(productCategory)];
+    if ([product_category isEqualToString:@"Xbox One"])
+      return false;
+    if ([product_category isEqualToString:@"DualShock 4"])
+      return false;
+  } else {
+    NSString* vendor_name = [controller vendorName];
+    if ([vendor_name isEqualToString:@"Xbox Wireless Controller"])
+      return false;
+    if ([vendor_name isEqualToString:@"Wireless Controller"])
+      return false;
+  }
+
+  return true;
+}
+
 }  // namespace
 
 GameControllerDataFetcherMac::GameControllerDataFetcherMac() {}
@@ -37,9 +78,7 @@
   bool player_indices[Gamepads::kItemsLengthCap];
   std::fill(player_indices, player_indices + Gamepads::kItemsLengthCap, false);
   for (GCController* controller in controllers) {
-    // We only support the extendedGamepad profile, the basic gamepad profile
-    // appears to only be for iOS devices.
-    if (![controller extendedGamepad])
+    if (!IsSupported(controller))
       continue;
 
     int player_index = [controller playerIndex];
@@ -55,9 +94,7 @@
   // In the second pass, assign indices to newly connected gamepads and fetch
   // the gamepad state.
   for (GCController* controller in controllers) {
-    auto extended_gamepad = [controller extendedGamepad];
-
-    if (!extended_gamepad)
+    if (!IsSupported(controller))
       continue;
 
     int player_index = [controller playerIndex];
@@ -104,6 +141,7 @@
 
     pad.timestamp = CurrentTimeInMicroseconds();
 
+    auto extended_gamepad = [controller extendedGamepad];
     pad.axes[AXIS_INDEX_LEFT_STICK_X] =
         [[[extended_gamepad leftThumbstick] xAxis] value];
     pad.axes[AXIS_INDEX_LEFT_STICK_Y] =
diff --git a/device/gamepad/nintendo_controller.cc b/device/gamepad/nintendo_controller.cc
index 110e9b0..d47cd32a 100644
--- a/device/gamepad/nintendo_controller.cc
+++ b/device/gamepad/nintendo_controller.cc
@@ -886,6 +886,9 @@
 
 std::vector<std::unique_ptr<NintendoController>>
 NintendoController::Decompose() {
+  // Stop any ongoing vibration effects before decomposing the device.
+  SetZeroVibration();
+
   std::vector<std::unique_ptr<NintendoController>> decomposed_devices;
   if (composite_left_)
     decomposed_devices.push_back(std::move(composite_left_));
@@ -951,7 +954,7 @@
   if (state_ != kInitialized)
     return false;
   if (is_composite_)
-    return true;
+    return composite_left_ && composite_right_;
   switch (gamepad_id_) {
     case GamepadId::kNintendoProduct2009:
     case GamepadId::kNintendoProduct2006:
@@ -968,10 +971,12 @@
 }
 
 bool NintendoController::HasGuid(const std::string& guid) const {
-  if (is_composite_)
+  if (is_composite_) {
+    DCHECK(composite_left_);
+    DCHECK(composite_right_);
     return composite_left_->HasGuid(guid) || composite_right_->HasGuid(guid);
-  else
-    return device_info_->guid == guid;
+  }
+  return device_info_->guid == guid;
 }
 
 GamepadStandardMappingFunction NintendoController::GetMappingFunction() const {
@@ -1027,6 +1032,8 @@
 
 void NintendoController::UpdateGamepadState(Gamepad& pad) const {
   if (is_composite_) {
+    DCHECK(composite_left_);
+    DCHECK(composite_right_);
     // If this is a composite device, update the gamepad state using the state
     // of the subcomponents.
     pad.connected = true;
@@ -1709,8 +1716,10 @@
                                       double weak_magnitude) {
   if (is_composite_) {
     // Split the vibration effect between the left and right subdevices.
-    composite_left_->SetVibration(strong_magnitude, 0);
-    composite_right_->SetVibration(0, weak_magnitude);
+    if (composite_left_ && composite_right_) {
+      composite_left_->SetVibration(strong_magnitude, 0);
+      composite_right_->SetVibration(0, weak_magnitude);
+    }
   } else {
     RequestVibration(kVibrationFrequencyStrongRumble,
                      kVibrationAmplitudeStrongRumbleMax * strong_magnitude,
diff --git a/docs/lldbinit.md b/docs/lldbinit.md
new file mode 100644
index 0000000..7dc4e7e
--- /dev/null
+++ b/docs/lldbinit.md
@@ -0,0 +1,13 @@
+# Usage of tools/lldb/lldbinit.py
+
+Usage of Chromium's [lldbinit.py](../tools/lldb/lldbinit.py) is recommended when
+debugging with lldb. This is necessary for source-level debugging when
+`strip_absolute_paths_from_debug_symbols` is enabled [this is the default].
+
+To use, add the following to your `~/.lldbinit`
+
+```
+# So that lldbinit.py takes precedence.
+script sys.path[:0] = ['<.../path/to/chromium/src/tools/lldb>']
+script import lldbinit
+```
diff --git a/extensions/browser/api/api_resource_manager.h b/extensions/browser/api/api_resource_manager.h
index 9c0bd27..3141f848 100644
--- a/extensions/browser/api/api_resource_manager.h
+++ b/extensions/browser/api/api_resource_manager.h
@@ -105,7 +105,7 @@
                            public ProcessManagerObserver {
  public:
   explicit ApiResourceManager(content::BrowserContext* context)
-      : data_(new ApiResourceData()),
+      : data_(base::MakeRefCounted<ApiResourceData>()),
         extension_registry_observer_(this),
         process_manager_observer_(this) {
     extension_registry_observer_.Add(ExtensionRegistry::Get(context));
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_action.cc b/extensions/browser/api/declarative_webrequest/webrequest_action.cc
index 14db9db..adb529d8 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_action.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_action.cc
@@ -116,7 +116,7 @@
     const base::Value* value,
     std::string* error,
     bool* bad_message) {
-  return scoped_refptr<const WebRequestAction>(new T);
+  return base::MakeRefCounted<T>();
 }
 
 scoped_refptr<const WebRequestAction> CreateRedirectRequestAction(
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc
index 086987d..1df437f 100644
--- a/extensions/browser/api/device_permissions_manager.cc
+++ b/extensions/browser/api/device_permissions_manager.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/singleton.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -225,11 +226,11 @@
   }
 
   if (type == kDeviceTypeUsb) {
-    return new DevicePermissionEntry(
+    return base::MakeRefCounted<DevicePermissionEntry>(
         DevicePermissionEntry::Type::USB, vendor_id, product_id, serial_number,
         manufacturer_string, product_string, last_used);
   } else if (type == kDeviceTypeHid) {
-    return new DevicePermissionEntry(
+    return base::MakeRefCounted<DevicePermissionEntry>(
         DevicePermissionEntry::Type::HID, vendor_id, product_id, serial_number,
         base::string16(), product_string, last_used);
   }
@@ -562,8 +563,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DevicePermissions* device_permissions = GetForExtension(extension_id);
 
-  scoped_refptr<DevicePermissionEntry> device_entry(
-      new DevicePermissionEntry(device));
+  auto device_entry = base::MakeRefCounted<DevicePermissionEntry>(device);
 
   if (device_entry->IsPersistent()) {
     for (const auto& entry : device_permissions->entries()) {
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc
index f28fa32..83cd02e 100644
--- a/extensions/browser/api/device_permissions_prompt.cc
+++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/i18n/message_formatter.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/scoped_observer.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -367,8 +368,8 @@
     bool multiple,
     std::vector<UsbDeviceFilterPtr> filters,
     const UsbDevicesCallback& callback) {
-  prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple,
-                                           std::move(filters), callback);
+  prompt_ = base::MakeRefCounted<UsbDevicePermissionsPrompt>(
+      extension, context, multiple, std::move(filters), callback);
   ShowDialog();
 }
 
@@ -378,8 +379,8 @@
     bool multiple,
     const std::vector<HidDeviceFilter>& filters,
     const HidDevicesCallback& callback) {
-  prompt_ = new HidDevicePermissionsPrompt(extension, context, multiple,
-                                           filters, callback);
+  prompt_ = base::MakeRefCounted<HidDevicePermissionsPrompt>(
+      extension, context, multiple, filters, callback);
   ShowDialog();
 }
 
diff --git a/extensions/browser/api/file_handlers/app_file_handler_util.cc b/extensions/browser/api/file_handlers/app_file_handler_util.cc
index 75126f5..5e1e198f 100644
--- a/extensions/browser/api/file_handlers/app_file_handler_util.cc
+++ b/extensions/browser/api/file_handlers/app_file_handler_util.cc
@@ -10,6 +10,7 @@
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "build/build_config.h"
@@ -325,8 +326,8 @@
     const std::set<base::FilePath>& directory_paths,
     const base::Closure& on_success,
     const base::Callback<void(const base::FilePath&)>& on_failure) {
-  scoped_refptr<WritableFileChecker> checker(new WritableFileChecker(
-      paths, context, directory_paths, on_success, on_failure));
+  auto checker = base::MakeRefCounted<WritableFileChecker>(
+      paths, context, directory_paths, on_success, on_failure);
   checker->Check();
 }
 
diff --git a/extensions/browser/api/networking_private/networking_private_linux.cc b/extensions/browser/api/networking_private/networking_private_linux.cc
index 4d3f105..37ca2849b 100644
--- a/extensions/browser/api/networking_private/networking_private_linux.cc
+++ b/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
-#include "base/message_loop/message_pump_type.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
@@ -169,7 +169,7 @@
   dbus_options.connection_type = dbus::Bus::PRIVATE;
   dbus_options.dbus_task_runner = dbus_task_runner_;
 
-  dbus_ = new dbus::Bus(dbus_options);
+  dbus_ = base::MakeRefCounted<dbus::Bus>(dbus_options);
   network_manager_proxy_ = dbus_->GetObjectProxy(
       networking_private::kNetworkManagerNamespace,
       dbus::ObjectPath(networking_private::kNetworkManagerPath));
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc
index b1cc646d..701a4dc 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -16,6 +16,7 @@
 #include "base/containers/adapters.h"
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
@@ -1227,7 +1228,7 @@
 
   // Only create a copy if we really want to modify the response headers.
   if (override_response_headers->get() == NULL) {
-    *override_response_headers = new net::HttpResponseHeaders(
+    *override_response_headers = base::MakeRefCounted<net::HttpResponseHeaders>(
         original_response_headers->raw_headers());
   }
 
@@ -1353,8 +1354,9 @@
   if (new_url.is_valid()) {
     // Only create a copy if we really want to modify the response headers.
     if (override_response_headers->get() == NULL) {
-      *override_response_headers = new net::HttpResponseHeaders(
-          original_response_headers->raw_headers());
+      *override_response_headers =
+          base::MakeRefCounted<net::HttpResponseHeaders>(
+              original_response_headers->raw_headers());
     }
     (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found");
     (*override_response_headers)->RemoveHeader("location");
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc
index dfd927a..a8c35d1 100644
--- a/extensions/browser/content_verifier.cc
+++ b/extensions/browser/content_verifier.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
@@ -513,7 +514,8 @@
   if (shutdown_on_ui_)
     return;
 
-  if (delegate_->ShouldBeVerified(*extension)) {
+  if (delegate_->GetVerifierSourceType(*extension) ==
+      ContentVerifierDelegate::VerifierSourceType::SIGNED_HASHES) {
     base::PostTask(
         FROM_HERE, {content::BrowserThread::IO},
         base::BindOnce(&ContentVerifier::OnExtensionLoadedOnIO, this,
diff --git a/extensions/browser/content_verifier.h b/extensions/browser/content_verifier.h
index 39c6bff..1c275b47 100644
--- a/extensions/browser/content_verifier.h
+++ b/extensions/browser/content_verifier.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/scoped_observer.h"
 #include "base/version.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc
index 3830b2e1..6194b19 100644
--- a/extensions/browser/content_verifier/test_utils.cc
+++ b/extensions/browser/content_verifier/test_utils.cc
@@ -132,12 +132,9 @@
 MockContentVerifierDelegate::MockContentVerifierDelegate() = default;
 MockContentVerifierDelegate::~MockContentVerifierDelegate() = default;
 
-bool MockContentVerifierDelegate::ShouldBeChecked(const Extension& extension) {
-  return true;
-}
-
-bool MockContentVerifierDelegate::ShouldBeVerified(const Extension& extension) {
-  return true;
+ContentVerifierDelegate::VerifierSourceType
+MockContentVerifierDelegate::GetVerifierSourceType(const Extension& extension) {
+  return VerifierSourceType::SIGNED_HASHES;
 }
 
 ContentVerifierKey MockContentVerifierDelegate::GetPublicKey() {
diff --git a/extensions/browser/content_verifier/test_utils.h b/extensions/browser/content_verifier/test_utils.h
index 9b72376..c2bdf0e5 100644
--- a/extensions/browser/content_verifier/test_utils.h
+++ b/extensions/browser/content_verifier/test_utils.h
@@ -111,8 +111,7 @@
   ~MockContentVerifierDelegate() override;
 
   // ContentVerifierDelegate:
-  bool ShouldBeChecked(const Extension& extension) override;
-  bool ShouldBeVerified(const Extension& extension) override;
+  VerifierSourceType GetVerifierSourceType(const Extension& extension) override;
   ContentVerifierKey GetPublicKey() override;
   GURL GetSignatureFetchUrl(const ExtensionId& extension_id,
                             const base::Version& version) override;
diff --git a/extensions/browser/content_verifier_delegate.h b/extensions/browser/content_verifier_delegate.h
index 6888fd1..f8939923 100644
--- a/extensions/browser/content_verifier_delegate.h
+++ b/extensions/browser/content_verifier_delegate.h
@@ -23,18 +23,27 @@
 // This is an interface for clients that want to use a ContentVerifier.
 class ContentVerifierDelegate {
  public:
+  // Types of hash sources used for content verification of an extension.
+  enum class VerifierSourceType {
+    // Use no hashes for verification, this effectively means the extension
+    // won't be verified.
+    NONE,
+
+    // Use unsigned local hashes (computed_hashes.json) only and not
+    // verified_contents.json.
+    UNSIGNED_HASHES,
+
+    // Use signed hashes (verified_contents.json).
+    // Note that GetPublicKey and GetSignatureFetchUrl would be required for
+    // this.
+    SIGNED_HASHES,
+  };
+
   virtual ~ContentVerifierDelegate() {}
 
-  // Returns true if resources from |extension| should be checked for some
-  // content mismatch at all. Note that differs from ShouldBeVerified, and does
-  // not consider whether |extension| has signed hashes (verified_contents.json)
-  // or not.
-  virtual bool ShouldBeChecked(const Extension& extension) = 0;
-
-  // Returns whether or not resources from |extension| should be verified using
-  // signed hashes data (verified_contents.json). If yes, methods GetPublicKey
-  // and GetSignatureFetchUrl might be used.
-  virtual bool ShouldBeVerified(const Extension& extension) = 0;
+  // Returns verification source type for |extension|.
+  virtual VerifierSourceType GetVerifierSourceType(
+      const Extension& extension) = 0;
 
   // Returns the public key to use for validating signatures.
   virtual ContentVerifierKey GetPublicKey() = 0;
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index 15b13c88..96509e3 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/process/process.h"
@@ -335,9 +336,9 @@
   if (render_frame_host)
     DCHECK_EQ(render_process_id, render_frame_host->GetProcess()->GetID());
 
-  scoped_refptr<ExtensionFunction> function(CreateExtensionFunction(
+  scoped_refptr<ExtensionFunction> function = CreateExtensionFunction(
       params, extension, render_process_id, *process_map,
-      ExtensionAPI::GetSharedInstance(), browser_context_, callback));
+      ExtensionAPI::GetSharedInstance(), browser_context_, callback);
   if (!function.get())
     return;
 
@@ -482,7 +483,8 @@
 }
 
 // static
-ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
+scoped_refptr<ExtensionFunction>
+ExtensionFunctionDispatcher::CreateExtensionFunction(
     const ExtensionHostMsg_Request_Params& params,
     const Extension* extension,
     int requesting_process_id,
@@ -490,7 +492,7 @@
     ExtensionAPI* api,
     void* profile_id,
     const ExtensionFunction::ResponseCallback& callback) {
-  ExtensionFunction* function =
+  scoped_refptr<ExtensionFunction> function =
       ExtensionFunctionRegistry::GetInstance().NewFunction(params.name);
   if (!function) {
     LOG(ERROR) << "Unknown Extension API - " << params.name;
diff --git a/extensions/browser/extension_function_dispatcher.h b/extensions/browser/extension_function_dispatcher.h
index 92d3529..6721cee 100644
--- a/extensions/browser/extension_function_dispatcher.h
+++ b/extensions/browser/extension_function_dispatcher.h
@@ -28,9 +28,6 @@
 class ProcessMap;
 class WindowController;
 
-// A factory function for creating new ExtensionFunction instances.
-typedef ExtensionFunction* (*ExtensionFunctionFactory)();
-
 // ExtensionFunctionDispatcher receives requests to execute functions from
 // Chrome extensions running in a RenderFrameHost and dispatches them to the
 // appropriate handler. It lives entirely on the UI thread.
@@ -128,7 +125,7 @@
   // Helper to create an ExtensionFunction to handle the function given by
   // |params|. Can be called on any thread.
   // Does not set subclass properties, or include_incognito.
-  static ExtensionFunction* CreateExtensionFunction(
+  static scoped_refptr<ExtensionFunction> CreateExtensionFunction(
       const ExtensionHostMsg_Request_Params& params,
       const Extension* extension,
       int requesting_process_id,
diff --git a/extensions/browser/extension_function_registry.cc b/extensions/browser/extension_function_registry.cc
index f9a8d72..6b8fb3e4 100644
--- a/extensions/browser/extension_function_registry.cc
+++ b/extensions/browser/extension_function_registry.cc
@@ -34,13 +34,13 @@
   return true;
 }
 
-ExtensionFunction* ExtensionFunctionRegistry::NewFunction(
+scoped_refptr<ExtensionFunction> ExtensionFunctionRegistry::NewFunction(
     const std::string& name) {
   auto iter = factories_.find(name);
   if (iter == factories_.end()) {
     return NULL;
   }
-  ExtensionFunction* function = iter->second.factory_();
+  scoped_refptr<ExtensionFunction> function = iter->second.factory_();
   function->set_name(iter->second.function_name_);
   function->set_histogram_value(iter->second.histogram_value_);
   return function;
diff --git a/extensions/browser/extension_function_registry.h b/extensions/browser/extension_function_registry.h
index 93b5411..0e26517 100644
--- a/extensions/browser/extension_function_registry.h
+++ b/extensions/browser/extension_function_registry.h
@@ -9,17 +9,18 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "extensions/browser/extension_function_histogram_value.h"
 
 class ExtensionFunction;
 
 // A factory function for creating new ExtensionFunction instances.
-using ExtensionFunctionFactory = ExtensionFunction* (*)();
+using ExtensionFunctionFactory = scoped_refptr<ExtensionFunction> (*)();
 
 // Template for defining ExtensionFunctionFactory.
 template <class T>
-ExtensionFunction* NewExtensionFunction() {
-  return new T();
+scoped_refptr<ExtensionFunction> NewExtensionFunction() {
+  return base::MakeRefCounted<T>();
 }
 
 // Contains a list of all known extension functions and allows clients to
@@ -54,7 +55,7 @@
                                   ExtensionFunctionFactory factory);
 
   // Factory method for the ExtensionFunction registered as 'name'.
-  ExtensionFunction* NewFunction(const std::string& name);
+  scoped_refptr<ExtensionFunction> NewFunction(const std::string& name);
 
   // Registers a new extension function. This will override any existing entry.
   void Register(const FactoryEntry& entry);
diff --git a/extensions/browser/guest_view/web_view/web_view_find_helper.cc b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
index 5c74ebe8..defb854 100644
--- a/extensions/browser/guest_view/web_view/web_view_find_helper.cc
+++ b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/memory/scoped_refptr.h"
 #include "components/guest_view/browser/guest_view_event.h"
 #include "extensions/browser/api/guest_view/web_view/web_view_internal_api.h"
 #include "extensions/browser/guest_view/web_view/web_view_constants.h"
@@ -96,9 +97,9 @@
   // function can be called when the find results are available.
   std::pair<FindInfoMap::iterator, bool> insert_result =
       find_info_map_.insert(std::make_pair(
-          current_find_request_id_, base::WrapRefCounted(new FindInfo(
-                                        current_find_request_id_, search_text,
-                                        options.Clone(), find_function))));
+          current_find_request_id_,
+          base::MakeRefCounted<FindInfo>(current_find_request_id_, search_text,
+                                         options.Clone(), find_function)));
   // No duplicate insertions.
   DCHECK(insert_result.second);
 
diff --git a/extensions/browser/value_store/value_store_factory_impl.cc b/extensions/browser/value_store/value_store_factory_impl.cc
index 3689421..09f3a94 100644
--- a/extensions/browser/value_store/value_store_factory_impl.cc
+++ b/extensions/browser/value_store/value_store_factory_impl.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/browser/value_store/value_store_factory_impl.h"
 
+#include "base/memory/scoped_refptr.h"
 #include "extensions/browser/value_store/legacy_value_store_factory.h"
 
 namespace extensions {
@@ -11,7 +12,8 @@
 using SettingsNamespace = settings_namespace::Namespace;
 
 ValueStoreFactoryImpl::ValueStoreFactoryImpl(const base::FilePath& profile_path)
-    : legacy_factory_(new LegacyValueStoreFactory(profile_path)) {}
+    : legacy_factory_(
+          base::MakeRefCounted<LegacyValueStoreFactory>(profile_path)) {}
 
 ValueStoreFactoryImpl::~ValueStoreFactoryImpl() = default;
 
diff --git a/extensions/browser/value_store/value_store_frontend.cc b/extensions/browser/value_store/value_store_frontend.cc
index 6e7348c..931c1f8 100644
--- a/extensions/browser/value_store/value_store_frontend.cc
+++ b/extensions/browser/value_store/value_store_frontend.cc
@@ -10,6 +10,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/task/post_task.h"
 #include "base/trace_event/trace_event.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -113,7 +114,7 @@
 ValueStoreFrontend::ValueStoreFrontend(
     const scoped_refptr<ValueStoreFactory>& store_factory,
     BackendType backend_type)
-    : backend_(new Backend(store_factory, backend_type)) {
+    : backend_(base::MakeRefCounted<Backend>(store_factory, backend_type)) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index 03ec5be..52a07ef 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -232,6 +232,7 @@
         "chrome://add-supervision/*",
         "chrome://assistant-optin/*",
         "chrome://cast/*",
+        "chrome://cellular-setup/*",
         "chrome://discards/*",
         "chrome://extensions-frame/*",  // TODO(dbeam): still needed?
         "chrome://extensions/*",
@@ -652,6 +653,7 @@
     "matches": [
       "chrome://add-supervision/*",
       "chrome://assistant-optin/*",
+      "chrome://cellular-setup/*",
       "chrome://chrome-signin/*",
       "chrome://discards/*",
       "chrome://hats/*",
@@ -672,6 +674,7 @@
     "matches": [
       "chrome://add-supervision/*",
       "chrome://assistant-optin/*",
+      "chrome://cellular-setup/*",
       "chrome://chrome-signin/*",
       "chrome://discards/*",
       "chrome://hats/*",
@@ -690,6 +693,7 @@
     "matches": [
       "chrome://add-supervision/*",
       "chrome://assistant-optin/*",
+      "chrome://cellular-setup/*",
       "chrome://chrome-signin/*",
       "chrome://discards/*",
       "chrome://hats/*",
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
index 91d70df..404c61a 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -1445,7 +1445,8 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner =
         context()->web_frame()->GetTaskRunner(
             blink::TaskType::kInternalDefault);
-    message_filter_ = new AutomationMessageFilter(this, std::move(task_runner));
+    message_filter_ = base::MakeRefCounted<AutomationMessageFilter>(
+        this, std::move(task_runner));
   }
 }
 
@@ -1845,15 +1846,15 @@
 void AutomationInternalCustomBindings::RouteNodeIDFunction(
     const std::string& name,
     NodeIDFunction callback) {
-  scoped_refptr<NodeIDWrapper> wrapper = new NodeIDWrapper(this, callback);
+  auto wrapper = base::MakeRefCounted<NodeIDWrapper>(this, callback);
   RouteHandlerFunction(name, base::BindRepeating(&NodeIDWrapper::Run, wrapper));
 }
 
 void AutomationInternalCustomBindings::RouteNodeIDPlusAttributeFunction(
     const std::string& name,
     NodeIDPlusAttributeFunction callback) {
-  scoped_refptr<NodeIDPlusAttributeWrapper> wrapper =
-      new NodeIDPlusAttributeWrapper(this, callback);
+  auto wrapper =
+      base::MakeRefCounted<NodeIDPlusAttributeWrapper>(this, callback);
   RouteHandlerFunction(
       name, base::BindRepeating(&NodeIDPlusAttributeWrapper::Run, wrapper));
 }
@@ -1861,8 +1862,7 @@
 void AutomationInternalCustomBindings::RouteNodeIDPlusRangeFunction(
     const std::string& name,
     NodeIDPlusRangeFunction callback) {
-  scoped_refptr<NodeIDPlusRangeWrapper> wrapper =
-      new NodeIDPlusRangeWrapper(this, callback);
+  auto wrapper = base::MakeRefCounted<NodeIDPlusRangeWrapper>(this, callback);
   RouteHandlerFunction(
       name, base::BindRepeating(&NodeIDPlusRangeWrapper::Run, wrapper));
 }
@@ -1870,8 +1870,8 @@
 void AutomationInternalCustomBindings::RouteNodeIDPlusStringBoolFunction(
     const std::string& name,
     NodeIDPlusStringBoolFunction callback) {
-  scoped_refptr<NodeIDPlusStringBoolWrapper> wrapper =
-      new NodeIDPlusStringBoolWrapper(this, callback);
+  auto wrapper =
+      base::MakeRefCounted<NodeIDPlusStringBoolWrapper>(this, callback);
   RouteHandlerFunction(
       name, base::BindRepeating(&NodeIDPlusStringBoolWrapper::Run, wrapper));
 }
@@ -1879,8 +1879,8 @@
 void AutomationInternalCustomBindings::RouteNodeIDPlusDimensionsFunction(
     const std::string& name,
     NodeIDPlusDimensionsFunction callback) {
-  scoped_refptr<NodeIDPlusDimensionsWrapper> wrapper =
-      new NodeIDPlusDimensionsWrapper(this, callback);
+  auto wrapper =
+      base::MakeRefCounted<NodeIDPlusDimensionsWrapper>(this, callback);
   RouteHandlerFunction(
       name, base::BindRepeating(&NodeIDPlusDimensionsWrapper::Run, wrapper));
 }
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index e41d7b7..cbf0f72 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -10,12 +10,6 @@
 import("//testing/test.gni")
 import("//tools/grit/repack.gni")
 
-declare_args() {
-  # Enables Vulkan in WebEngine (has effect only for context instances that have
-  # Vulkan loader service in the service directory).
-  web_engine_enable_vulkan = false
-}
-
 config("web_engine_implementation") {
   defines = [ "WEB_ENGINE_IMPLEMENTATION" ]
 }
@@ -54,6 +48,7 @@
     "//content/app/resources",
     "//content/app/strings",
     "//content/browser/tracing:resources",
+    "//gpu/command_buffer/service",
     "//mojo/public/js:resources",
     "//net:net_resources",
     "//third_party/blink/public:resources",
@@ -80,6 +75,7 @@
     "//fuchsia/base",
     "//fuchsia/base:message_port",
     "//fuchsia/base:modular",
+    "//gpu/command_buffer/service",
     "//media/fuchsia/cdm/service",
     "//media/fuchsia/mojom",
     "//mojo/public/cpp/bindings",
@@ -163,9 +159,6 @@
     ":*",
     "//fuchsia/runners:cast_runner_browsertests__exec",
   ]
-  if (web_engine_enable_vulkan) {
-    defines = [ "WEB_ENGINE_ENABLE_VULKAN" ]
-  }
 }
 
 executable("web_engine_exe") {
diff --git a/fuchsia/engine/DEPS b/fuchsia/engine/DEPS
index a86f48c..eb2adde57 100644
--- a/fuchsia/engine/DEPS
+++ b/fuchsia/engine/DEPS
@@ -1,5 +1,8 @@
 include_rules = [
+  "+components/viz/common",
   "+content/public/app",
+  "+gpu/command_buffer/service",
   "+services/service_manager",
   "+ui/base",
+  "+ui/gl/gl_switches.h",
 ]
diff --git a/fuchsia/engine/browser/cookie_manager_impl_unittest.cc b/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
index 753202a..1794c0f3 100644
--- a/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
+++ b/fuchsia/engine/browser/cookie_manager_impl_unittest.cc
@@ -75,8 +75,7 @@
     mojo_cookie_manager_->SetCanonicalCookie(
         *CreateCookie(name, value), "https", options,
         base::Bind([](net::CanonicalCookie::CookieInclusionStatus status) {
-          EXPECT_EQ(status,
-                    net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+          EXPECT_TRUE(status.IsInclude());
         }));
   }
 
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.cc b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
index ae98822..ff48f43 100644
--- a/fuchsia/engine/browser/web_engine_browser_main_parts.cc
+++ b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
@@ -10,12 +10,14 @@
 #include "base/command_line.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/logging.h"
+#include "content/public/browser/gpu_data_manager.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/main_function_params.h"
 #include "fuchsia/engine/browser/context_impl.h"
 #include "fuchsia/engine/browser/web_engine_browser_context.h"
 #include "fuchsia/engine/browser/web_engine_screen.h"
 #include "fuchsia/engine/common.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
 #include "ui/aura/screen_ozone.h"
 #include "ui/ozone/public/ozone_platform.h"
 
@@ -42,6 +44,17 @@
 
   display::Screen::SetScreenInstance(screen_.get());
 
+  // If Vulkan is not enabled then disable hardware acceleration. Otherwise gpu
+  // process will be restarted several times trying to initialize GL before
+  // falling back to software compositing.
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseVulkan)) {
+    content::GpuDataManager* gpu_data_manager =
+        content::GpuDataManager::GetInstance();
+    DCHECK(gpu_data_manager);
+    gpu_data_manager->DisableHardwareAcceleration();
+  }
+
   DCHECK(!browser_context_);
   browser_context_ = std::make_unique<WebEngineBrowserContext>(
       base::CommandLine::ForCurrentProcess()->HasSwitch(kIncognitoSwitch));
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index 19f3e2cb..5d8d9b2 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "base/base_paths_fuchsia.h"
+#include "base/base_switches.h"
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/scoped_file.h"
@@ -32,10 +33,13 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "components/viz/common/features.h"
 #include "content/public/common/content_switches.h"
 #include "fuchsia/engine/common.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
 #include "net/http/http_util.h"
 #include "services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h"
+#include "ui/gl/gl_switches.h"
 
 namespace {
 
@@ -192,14 +196,21 @@
                                       base::JoinString(handles_ids, ","));
   }
 
-#if defined(WEB_ENGINE_ENABLE_VULKAN)
-  // TODO(fbx/35009): Add a flag in CreateContextParams to enable/disable Vulkan
-  // and use it here.
-  launch_command.AppendSwitchASCII(
-      "--enable-features", "DefaultEnableOopRasterization,UseSkiaRenderer");
-  launch_command.AppendSwitch("--use-vulkan");
-  launch_command.AppendSwitchASCII("--use-gl", "stub");
-#endif  // WEB_ENGINE_ENABLE_VULKAN
+  fuchsia::web::ContextFeatureFlags features = {};
+  if (params.has_features())
+    features = params.features();
+
+  bool enable_vulkan = (features & fuchsia::web::ContextFeatureFlags::VULKAN) ==
+                       fuchsia::web::ContextFeatureFlags::VULKAN;
+
+  if (enable_vulkan) {
+    launch_command.AppendSwitch(switches::kUseVulkan);
+    launch_command.AppendSwitchASCII(switches::kEnableFeatures,
+                                     features::kUseSkiaRenderer.name);
+    launch_command.AppendSwitch(switches::kEnableOopRasterization);
+    launch_command.AppendSwitchASCII(switches::kUseGL,
+                                     gl::kGLImplementationStubName);
+  }
 
   // Validate embedder-supplied product, and optional version, and pass it to
   // the Context to include in the UserAgent.
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc
index a9fee8f..88a63ea 100644
--- a/fuchsia/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -156,10 +156,11 @@
       : run_timeout_(
             TestTimeouts::action_timeout(),
             base::MakeExpectedNotRunClosure(FROM_HERE, "Run() timed out.")) {
-
     // Create the CastRunner, published into |test_services_|.
+    constexpr fuchsia::web::ContextFeatureFlags kFeatures = {};
     cast_runner_ = std::make_unique<CastRunner>(
-        &outgoing_directory_, WebContentRunner::CreateIncognitoWebContext());
+        &outgoing_directory_,
+        WebContentRunner::CreateIncognitoWebContext(kFeatures));
 
     // Connect to the CastRunner's fuchsia.sys.Runner interface.
     fidl::InterfaceHandle<fuchsia::io::Directory> directory;
diff --git a/fuchsia/runners/cast/main.cc b/fuchsia/runners/cast/main.cc
index bf2dff86..ecafa69 100644
--- a/fuchsia/runners/cast/main.cc
+++ b/fuchsia/runners/cast/main.cc
@@ -14,9 +14,13 @@
   base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
   base::RunLoop run_loop;
 
+  constexpr fuchsia::web::ContextFeatureFlags kCastRunnerFeatures =
+      fuchsia::web::ContextFeatureFlags::NETWORK |
+      fuchsia::web::ContextFeatureFlags::AUDIO;
+
   CastRunner runner(
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
-      WebContentRunner::CreateIncognitoWebContext());
+      WebContentRunner::CreateIncognitoWebContext(kCastRunnerFeatures));
 
   base::fuchsia::ComponentContextForCurrentProcess()
       ->outgoing()
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc
index e402290..2469821 100644
--- a/fuchsia/runners/common/web_content_runner.cc
+++ b/fuchsia/runners/common/web_content_runner.cc
@@ -32,7 +32,8 @@
 }
 
 fuchsia::web::ContextPtr CreateWebContextWithDataDirectory(
-    fidl::InterfaceHandle<fuchsia::io::Directory> data_directory) {
+    fidl::InterfaceHandle<fuchsia::io::Directory> data_directory,
+    fuchsia::web::ContextFeatureFlags features) {
   auto web_context_provider = base::fuchsia::ComponentContextForCurrentProcess()
                                   ->svc()
                                   ->Connect<fuchsia::web::ContextProvider>();
@@ -45,6 +46,8 @@
   if (data_directory)
     create_params.set_data_directory(std::move(data_directory));
 
+  create_params.set_features(features);
+
   // Set |remote_debugging_port| on the context, if set.
   if (BUILDFLAG(ENABLE_REMOTE_DEBUGGING_ON_PORT) != 0) {
     create_params.set_remote_debugging_port(
@@ -66,15 +69,19 @@
 }  // namespace
 
 // static
-fuchsia::web::ContextPtr WebContentRunner::CreateDefaultWebContext() {
-  return CreateWebContextWithDataDirectory(OpenDirectoryOrFail(
-      base::FilePath(base::fuchsia::kPersistedDataDirectoryPath)));
+fuchsia::web::ContextPtr WebContentRunner::CreateDefaultWebContext(
+    fuchsia::web::ContextFeatureFlags features) {
+  return CreateWebContextWithDataDirectory(
+      OpenDirectoryOrFail(
+          base::FilePath(base::fuchsia::kPersistedDataDirectoryPath)),
+      features);
 }
 
 // static
-fuchsia::web::ContextPtr WebContentRunner::CreateIncognitoWebContext() {
+fuchsia::web::ContextPtr WebContentRunner::CreateIncognitoWebContext(
+    fuchsia::web::ContextFeatureFlags features) {
   return CreateWebContextWithDataDirectory(
-      fidl::InterfaceHandle<fuchsia::io::Directory>());
+      fidl::InterfaceHandle<fuchsia::io::Directory>(), features);
 }
 
 WebContentRunner::WebContentRunner(sys::OutgoingDirectory* outgoing_directory,
diff --git a/fuchsia/runners/common/web_content_runner.h b/fuchsia/runners/common/web_content_runner.h
index d584e83..b1c6323 100644
--- a/fuchsia/runners/common/web_content_runner.h
+++ b/fuchsia/runners/common/web_content_runner.h
@@ -23,12 +23,14 @@
   // Creates and returns a web.Context with a default path and parameters,
   // and with access to the same services as this Runner. The returned binding
   // is configured to exit this process on error.
-  static fuchsia::web::ContextPtr CreateDefaultWebContext();
+  static fuchsia::web::ContextPtr CreateDefaultWebContext(
+      fuchsia::web::ContextFeatureFlags features);
 
   // Creates and returns an incognito web.Context  with access to the same
   // services as this Runner. The returned binding is configured to exit this
   // process on error.
-  static fuchsia::web::ContextPtr CreateIncognitoWebContext();
+  static fuchsia::web::ContextPtr CreateIncognitoWebContext(
+      fuchsia::web::ContextFeatureFlags features);
 
   // |outgoing_directory|: OutgoingDirectory into which this Runner will be
   //   published. |on_idle_closure| will be invoked when the final client of the
diff --git a/fuchsia/runners/web/main.cc b/fuchsia/runners/web/main.cc
index 7780fef..ed0d1f7 100644
--- a/fuchsia/runners/web/main.cc
+++ b/fuchsia/runners/web/main.cc
@@ -14,9 +14,15 @@
   base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
   base::RunLoop run_loop;
 
+  constexpr fuchsia::web::ContextFeatureFlags kWebRunnerFeatures =
+      fuchsia::web::ContextFeatureFlags::NETWORK |
+      fuchsia::web::ContextFeatureFlags::AUDIO |
+      fuchsia::web::ContextFeatureFlags::VULKAN |
+      fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER;
+
   WebContentRunner runner(
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get(),
-      WebContentRunner::CreateDefaultWebContext());
+      WebContentRunner::CreateDefaultWebContext(kWebRunnerFeatures));
 
   base::fuchsia::ComponentContextForCurrentProcess()
       ->outgoing()
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
index eaedb24..32c2114 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
@@ -303,8 +303,9 @@
   shared_image.reset();
 }
 
+// TODO(crbug/994720): Failing on Android builders.
 // Test to check that only one context can write at a time
-TEST_F(SharedImageBackingFactoryAHBTest, OnlyOneWriter) {
+TEST_F(SharedImageBackingFactoryAHBTest, DISABLED_OnlyOneWriter) {
   if (!base::AndroidHardwareBufferCompat::IsSupportAvailable())
     return;
 
diff --git a/gpu/command_buffer/service/shared_image_video.cc b/gpu/command_buffer/service/shared_image_video.cc
index d98d8a9..7ef707a 100644
--- a/gpu/command_buffer/service/shared_image_video.cc
+++ b/gpu/command_buffer/service/shared_image_video.cc
@@ -113,6 +113,7 @@
 
 SharedImageVideo::SharedImageVideo(
     const Mailbox& mailbox,
+    const gfx::Size& size,
     const gfx::ColorSpace color_space,
     scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
     std::unique_ptr<gles2::AbstractTexture> abstract_texture,
@@ -121,12 +122,11 @@
     : SharedImageBacking(
           mailbox,
           viz::RGBA_8888,
-          stream_texture_sii->GetSize(),
+          size,
           color_space,
           (SHARED_IMAGE_USAGE_DISPLAY | SHARED_IMAGE_USAGE_GLES2),
-          viz::ResourceSizes::UncheckedSizeInBytes<size_t>(
-              stream_texture_sii->GetSize(),
-              viz::RGBA_8888),
+          viz::ResourceSizes::UncheckedSizeInBytes<size_t>(size,
+                                                           viz::RGBA_8888),
           is_thread_safe),
       stream_texture_sii_(std::move(stream_texture_sii)),
       abstract_texture_(std::move(abstract_texture)),
diff --git a/gpu/command_buffer/service/shared_image_video.h b/gpu/command_buffer/service/shared_image_video.h
index 798d51f..bc4d108 100644
--- a/gpu/command_buffer/service/shared_image_video.h
+++ b/gpu/command_buffer/service/shared_image_video.h
@@ -32,6 +32,7 @@
  public:
   SharedImageVideo(
       const Mailbox& mailbox,
+      const gfx::Size& size,
       const gfx::ColorSpace color_space,
       scoped_refptr<StreamTextureSharedImageInterface> stream_texture_sii,
       std::unique_ptr<gles2::AbstractTexture> abstract_texture,
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc
index 71daeaa..434983a6 100644
--- a/gpu/ipc/service/stream_texture_android.cc
+++ b/gpu/ipc/service/stream_texture_android.cc
@@ -298,7 +298,7 @@
   // TODO(vikassoni): Hardcoding colorspace to SRGB. Figure how if we have a
   // colorspace and wire it here.
   auto shared_image = std::make_unique<SharedImageVideo>(
-      mailbox, gfx::ColorSpace::CreateSRGB(), this,
+      mailbox, size_, gfx::ColorSpace::CreateSRGB(), this,
       std::move(legacy_mailbox_texture), context_state_, false);
   channel_->shared_image_stub()->factory()->RegisterBacking(
       std::move(shared_image), true /* allow_legacy_mailbox */);
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index 46ac171..97dd12d1 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -248,8 +248,8 @@
 
   if (cookie->IsSecure() && !secure_source) {
     if (!callback.is_null())
-      std::move(callback).Run(
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
+      std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus(
+          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
     return;
   }
 
@@ -258,14 +258,14 @@
   if (ns_cookie != nil) {
     system_store_->SetCookieAsync(
         ns_cookie, &cookie->CreationDate(),
-        BindSetCookiesCallback(
-            &callback, net::CanonicalCookie::CookieInclusionStatus::INCLUDE));
+        BindSetCookiesCallback(&callback,
+                               net::CanonicalCookie::CookieInclusionStatus()));
     return;
   }
 
   if (!callback.is_null())
-    std::move(callback).Run(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+    std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus(
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE));
 }
 
 void CookieStoreIOS::GetCookieListWithOptionsAsync(
@@ -643,7 +643,7 @@
     SetCookiesCallback callback,
     net::CanonicalCookie::CookieInclusionStatus status) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE)
+  if (status.IsInclude())
     UpdateCachesFromCookieMonster();
   if (!callback.is_null())
     std::move(callback).Run(status);
@@ -682,9 +682,8 @@
   cookie_list.reserve([cookies count]);
   for (NSHTTPCookie* cookie in cookies) {
     base::Time created = system_store_->GetCookieCreationTime(cookie);
-    cookie_list.push_back(
-        {CanonicalCookieFromSystemCookie(cookie, created),
-         net::CanonicalCookie::CookieInclusionStatus::INCLUDE});
+    cookie_list.push_back({CanonicalCookieFromSystemCookie(cookie, created),
+                           net::CanonicalCookie::CookieInclusionStatus()});
   }
   return cookie_list;
 }
diff --git a/ios/web/download/download_session_cookie_storage.mm b/ios/web/download/download_session_cookie_storage.mm
index de71338..9138bea 100644
--- a/ios/web/download/download_session_cookie_storage.mm
+++ b/ios/web/download/download_session_cookie_storage.mm
@@ -44,10 +44,8 @@
   for (NSHTTPCookie* cookie in self.cookies) {
     net::CanonicalCookie canonical_cookie =
         net::CanonicalCookieFromSystemCookie(cookie, base::Time());
-    if (canonical_cookie.IncludeForRequestURL(gURL, options) ==
-        net::CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+    if (canonical_cookie.IncludeForRequestURL(gURL, options).IsInclude())
       [result addObject:cookie];
-    }
   }
   return [result copy];
 }
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.mm b/ios/web/net/cookies/wk_http_system_cookie_store.mm
index 20400842..f5c0c12 100644
--- a/ios/web/net/cookies/wk_http_system_cookie_store.mm
+++ b/ios/web/net/cookies/wk_http_system_cookie_store.mm
@@ -45,8 +45,7 @@
       net::CanonicalCookieFromSystemCookie(cookie, base::Time());
   net::CookieOptions options;
   options.set_include_httponly();
-  return canonical_cookie.IncludeForRequestURL(url, options) ==
-         net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  return canonical_cookie.IncludeForRequestURL(url, options).IsInclude();
 }
 
 }  // namespace
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 749e124e..08c606b 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -260,6 +260,10 @@
 const base::Feature kD3D11VideoDecoderIgnoreWorkarounds{
     "D3D11VideoDecoderIgnoreWorkarounds", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Don't allow use of 11.1 devices, even if supported. They might be more crashy
+const base::Feature kD3D11LimitTo11_0{"D3D11VideoDecoderLimitTo11_0",
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Falls back to other decoders after audio/video decode error happens. The
 // implementation may choose different strategies on when to fallback. See
 // DecoderStream for details. When disabled, playback will fail immediately
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 2ce263a..9728fc17 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -101,6 +101,7 @@
 MEDIA_EXPORT extern const base::Feature kBackgroundVideoPauseOptimization;
 MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoder;
 MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderIgnoreWorkarounds;
+MEDIA_EXPORT extern const base::Feature kD3D11LimitTo11_0;
 MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting;
 MEDIA_EXPORT extern const base::Feature kFFmpegDecodeOpaqueVP8;
 MEDIA_EXPORT extern const base::Feature kFailUrlProvisionFetcherForTesting;
diff --git a/media/gpu/android/direct_shared_image_video_provider.cc b/media/gpu/android/direct_shared_image_video_provider.cc
index 739b4ce1..5620d53 100644
--- a/media/gpu/android/direct_shared_image_video_provider.cc
+++ b/media/gpu/android/direct_shared_image_video_provider.cc
@@ -239,7 +239,7 @@
   // TODO(vikassoni): This shared image need to be thread safe eventually for
   // webview to work with shared images.
   auto shared_image = std::make_unique<gpu::SharedImageVideo>(
-      mailbox, gfx::ColorSpace::CreateSRGB(), std::move(image),
+      mailbox, size, gfx::ColorSpace::CreateSRGB(), std::move(image),
       std::move(texture), std::move(shared_context),
       false /* is_thread_safe */);
 
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index ab888eed..a9d873f 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -230,15 +230,11 @@
     return;
   }
 
-  usable_feature_level_ = device_->GetFeatureLevel();
-
-  // If we're ignoring workarounds, also limit to 11.0.  This is to see if 11.0
-  // is more stable than 11.1, even though it doesn't really have much to do
-  // with the IgnoreWorkarounds experiment.
-  if (usable_feature_level_ > D3D_FEATURE_LEVEL_11_0 &&
-      base::FeatureList::IsEnabled(kD3D11VideoDecoderIgnoreWorkarounds)) {
-    usable_feature_level_ = D3D_FEATURE_LEVEL_11_0;
+  if (!GetD3D11FeatureLevel(device_, &usable_feature_level_)) {
+    NotifyError("D3D11 feature level not supported");
+    return;
   }
+
   device_->GetImmediateContext(device_context_.ReleaseAndGetAddressOf());
 
   HRESULT hr;
@@ -714,6 +710,22 @@
 }
 
 // static
+bool D3D11VideoDecoder::GetD3D11FeatureLevel(ComD3D11Device dev,
+                                             D3D_FEATURE_LEVEL* feature_level) {
+  if (!dev || !feature_level)
+    return false;
+
+  *feature_level = dev->GetFeatureLevel();
+  if (*feature_level < D3D_FEATURE_LEVEL_11_0)
+    return false;
+
+  // TODO(tmathmeyer) should we log this to UMA?
+  if (base::FeatureList::IsEnabled(kD3D11LimitTo11_0))
+    *feature_level = D3D_FEATURE_LEVEL_11_0;
+  return true;
+}
+
+// static
 std::vector<SupportedVideoDecoderConfig>
 D3D11VideoDecoder::GetSupportedVideoDecoderConfigs(
     const gpu::GpuPreferences& gpu_preferences,
@@ -753,7 +765,12 @@
     return {};
   }
 
-  D3D_FEATURE_LEVEL usable_feature_level = d3d11_device->GetFeatureLevel();
+  D3D_FEATURE_LEVEL usable_feature_level;
+  if (!GetD3D11FeatureLevel(d3d11_device, &usable_feature_level)) {
+    UMA_HISTOGRAM_ENUMERATION(
+        uma_name, NotSupportedReason::kInsufficientD3D11FeatureLevel);
+    return {};
+  }
 
   const bool allow_encrypted =
       (usable_feature_level > D3D_FEATURE_LEVEL_11_0) &&
diff --git a/media/gpu/windows/d3d11_video_decoder.h b/media/gpu/windows/d3d11_video_decoder.h
index 8bb999e..270acb7 100644
--- a/media/gpu/windows/d3d11_video_decoder.h
+++ b/media/gpu/windows/d3d11_video_decoder.h
@@ -83,6 +83,9 @@
   void OutputResult(const CodecPicture* picture,
                     D3D11PictureBuffer* picture_buffer) override;
 
+  static bool GetD3D11FeatureLevel(ComD3D11Device dev,
+                                   D3D_FEATURE_LEVEL* feature_level);
+
   // Return the set of video decoder configs that we support.
   static std::vector<SupportedVideoDecoderConfig>
   GetSupportedVideoDecoderConfigs(
diff --git a/media/mojo/services/mojo_cdm_service.cc b/media/mojo/services/mojo_cdm_service.cc
index 3334ac0..a49ac81 100644
--- a/media/mojo/services/mojo_cdm_service.cc
+++ b/media/mojo/services/mojo_cdm_service.cc
@@ -60,7 +60,9 @@
                                 const CdmConfig& cdm_config,
                                 InitializeCallback callback) {
   DVLOG(1) << __func__ << ": " << key_system;
-  DCHECK(!cdm_);
+
+  CHECK(!has_initialize_been_called_) << "Initialize should only happen once";
+  has_initialize_been_called_ = true;
 
   auto weak_this = weak_factory_.GetWeakPtr();
   cdm_factory_->Create(
@@ -154,6 +156,7 @@
     return;
   }
 
+  CHECK(!cdm_) << "CDM should only be created once.";
   cdm_ = cdm;
 
   if (context_) {
diff --git a/media/mojo/services/mojo_cdm_service.h b/media/mojo/services/mojo_cdm_service.h
index c8de553..bfe7baf 100644
--- a/media/mojo/services/mojo_cdm_service.h
+++ b/media/mojo/services/mojo_cdm_service.h
@@ -101,6 +101,8 @@
   // Callback for when |decryptor_| loses connectivity.
   void OnDecryptorConnectionError();
 
+  bool has_initialize_been_called_ = false;
+
   CdmFactory* cdm_factory_;
   MojoCdmServiceContext* const context_ = nullptr;
   scoped_refptr<::media::ContentDecryptionModule> cdm_;
diff --git a/mojo/public/cpp/base/big_buffer.cc b/mojo/public/cpp/base/big_buffer.cc
index 72da4c8c..85ba9c96 100644
--- a/mojo/public/cpp/base/big_buffer.cc
+++ b/mojo/public/cpp/base/big_buffer.cc
@@ -79,7 +79,7 @@
 // static
 constexpr size_t BigBuffer::kMaxInlineBytes;
 
-BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes) {}
+BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes), bytes_size_(0) {}
 
 BigBuffer::BigBuffer(BigBuffer&& other) = default;
 
@@ -99,7 +99,8 @@
   if (storage_type_ == BigBuffer::StorageType::kBytes) {
     // Either |size| is small enough or shared memory allocation failed, and
     // fallback to inline allocation is feasible.
-    bytes_ = std::vector<uint8_t>(size);
+    bytes_ = std::make_unique<uint8_t[]>(size);
+    bytes_size_ = size;
   }
 }
 
@@ -114,7 +115,7 @@
 const uint8_t* BigBuffer::data() const {
   switch (storage_type_) {
     case StorageType::kBytes:
-      return bytes_.data();
+      return bytes_.get();
     case StorageType::kSharedMemory:
       DCHECK(shared_memory_->buffer_mapping_);
       return static_cast<const uint8_t*>(
@@ -132,7 +133,7 @@
 size_t BigBuffer::size() const {
   switch (storage_type_) {
     case StorageType::kBytes:
-      return bytes_.size();
+      return bytes_size_;
     case StorageType::kSharedMemory:
       return shared_memory_->size();
     case StorageType::kInvalidBuffer:
@@ -199,8 +200,9 @@
   BigBuffer buffer;
   buffer.storage_type_ = view.storage_type_;
   if (view.storage_type_ == BigBuffer::StorageType::kBytes) {
-    std::copy(view.bytes_.begin(), view.bytes_.end(),
-              std::back_inserter(buffer.bytes_));
+    buffer.bytes_ = std::make_unique<uint8_t[]>(view.bytes_.size());
+    buffer.bytes_size_ = view.bytes_.size();
+    std::copy(view.bytes_.begin(), view.bytes_.end(), buffer.bytes_.get());
   } else if (view.storage_type_ == BigBuffer::StorageType::kSharedMemory) {
     buffer.shared_memory_ = std::move(*view.shared_memory_);
   }
diff --git a/mojo/public/cpp/base/big_buffer.h b/mojo/public/cpp/base/big_buffer.h
index 579cf358..ef13e1e3 100644
--- a/mojo/public/cpp/base/big_buffer.h
+++ b/mojo/public/cpp/base/big_buffer.h
@@ -72,7 +72,7 @@
     kInvalidBuffer,
   };
 
-  // Defaults to empty vector storage.
+  // Defaults to empty kBytes storage.
   BigBuffer();
   BigBuffer(BigBuffer&& other);
 
@@ -108,9 +108,9 @@
 
   StorageType storage_type() const { return storage_type_; }
 
-  const std::vector<uint8_t>& bytes() const {
+  base::span<const uint8_t> byte_span() const {
     DCHECK_EQ(storage_type_, StorageType::kBytes);
-    return bytes_;
+    return base::make_span(bytes_.get(), bytes_size_);
   }
 
   internal::BigBufferSharedMemoryRegion& shared_memory() {
@@ -122,7 +122,8 @@
   friend class BigBufferView;
 
   StorageType storage_type_;
-  std::vector<uint8_t> bytes_;
+  std::unique_ptr<uint8_t[]> bytes_;
+  size_t bytes_size_;
   base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
 
   DISALLOW_COPY_AND_ASSIGN(BigBuffer);
diff --git a/mojo/public/cpp/base/big_buffer_mojom_traits.cc b/mojo/public/cpp/base/big_buffer_mojom_traits.cc
index 9d506dff..db1be4da 100644
--- a/mojo/public/cpp/base/big_buffer_mojom_traits.cc
+++ b/mojo/public/cpp/base/big_buffer_mojom_traits.cc
@@ -4,8 +4,6 @@
 
 #include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
 
-#include <vector>
-
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "mojo/public/cpp/bindings/array_data_view.h"
@@ -55,10 +53,10 @@
 }
 
 // static
-const std::vector<uint8_t>&
+base::span<const uint8_t>
 UnionTraits<mojo_base::mojom::BigBufferDataView, mojo_base::BigBuffer>::bytes(
     const mojo_base::BigBuffer& buffer) {
-  return buffer.bytes();
+  return buffer.byte_span();
 }
 
 // static
diff --git a/mojo/public/cpp/base/big_buffer_mojom_traits.h b/mojo/public/cpp/base/big_buffer_mojom_traits.h
index 0322cdb6..8cad0d4 100644
--- a/mojo/public/cpp/base/big_buffer_mojom_traits.h
+++ b/mojo/public/cpp/base/big_buffer_mojom_traits.h
@@ -6,7 +6,6 @@
 #define MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_MOJOM_TRAITS_H_
 
 #include <cstdint>
-#include <vector>
 
 #include "base/component_export.h"
 #include "base/containers/span.h"
@@ -37,7 +36,7 @@
   static mojo_base::mojom::BigBufferDataView::Tag GetTag(
       const mojo_base::BigBuffer& buffer);
 
-  static const std::vector<uint8_t>& bytes(const mojo_base::BigBuffer& buffer);
+  static base::span<const uint8_t> bytes(const mojo_base::BigBuffer& buffer);
   static mojo_base::internal::BigBufferSharedMemoryRegion& shared_memory(
       mojo_base::BigBuffer& buffer);
   static bool invalid_buffer(mojo_base::BigBuffer& buffer);
diff --git a/net/base/network_change_notifier_posix.cc b/net/base/network_change_notifier_posix.cc
index c5aa68d..cbfb6f9a 100644
--- a/net/base/network_change_notifier_posix.cc
+++ b/net/base/network_change_notifier_posix.cc
@@ -22,7 +22,16 @@
 NetworkChangeNotifierPosix::NetworkChangeNotifierPosix(
     NetworkChangeNotifier::ConnectionType initial_connection_type,
     NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype)
-    : NetworkChangeNotifier(NetworkChangeCalculatorParamsPosix()),
+    : NetworkChangeNotifierPosix(initial_connection_type,
+                                 initial_connection_subtype,
+                                 /*system_dns_config_notifier=*/nullptr) {}
+
+NetworkChangeNotifierPosix::NetworkChangeNotifierPosix(
+    NetworkChangeNotifier::ConnectionType initial_connection_type,
+    NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype,
+    SystemDnsConfigChangeNotifier* system_dns_config_notifier)
+    : NetworkChangeNotifier(NetworkChangeCalculatorParamsPosix(),
+                            system_dns_config_notifier),
       connection_type_(initial_connection_type),
       max_bandwidth_mbps_(
           NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
diff --git a/net/base/network_change_notifier_posix.h b/net/base/network_change_notifier_posix.h
index 7617124..939338c 100644
--- a/net/base/network_change_notifier_posix.h
+++ b/net/base/network_change_notifier_posix.h
@@ -52,6 +52,14 @@
  private:
   friend class NetworkChangeNotifierPosixTest;
 
+  // For testing purposes, allows specifying a SystemDnsConfigChangeNotifier.
+  // If |system_dns_config_notifier| is nullptr, NetworkChangeNotifier create a
+  // global one.
+  NetworkChangeNotifierPosix(
+      NetworkChangeNotifier::ConnectionType initial_connection_type,
+      NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype,
+      SystemDnsConfigChangeNotifier* system_dns_config_notifier);
+
   // Calculates parameters used for network change notifier online/offline
   // signals.
   static NetworkChangeNotifier::NetworkChangeCalculatorParams
diff --git a/net/base/network_change_notifier_posix_unittest.cc b/net/base/network_change_notifier_posix_unittest.cc
index 2fe938f..8306ba5 100644
--- a/net/base/network_change_notifier_posix_unittest.cc
+++ b/net/base/network_change_notifier_posix_unittest.cc
@@ -17,13 +17,18 @@
 class NetworkChangeNotifierPosixTest : public testing::Test {
  public:
   NetworkChangeNotifierPosixTest()
-      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
-        notifier_(new NetworkChangeNotifierPosix(
-            NetworkChangeNotifier::CONNECTION_UNKNOWN,
-            NetworkChangeNotifier::SUBTYPE_UNKNOWN)) {
+      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
+    // Create a SystemDnsConfigChangeNotifier instead of letting
+    // NetworkChangeNotifier create a global one, otherwise the global one will
+    // hold a TaskRunner handle to |task_environment_| and crash if any
+    // subsequent tests use it.
+    dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>();
+    notifier_.reset(new NetworkChangeNotifierPosix(
+        NetworkChangeNotifier::CONNECTION_UNKNOWN,
+        NetworkChangeNotifier::SUBTYPE_UNKNOWN, dns_config_notifier_.get()));
     auto dns_config_service = std::make_unique<TestDnsConfigService>();
     dns_config_service_ = dns_config_service.get();
-    notifier_->system_dns_config_notifier()->SetDnsConfigServiceForTesting(
+    dns_config_notifier_->SetDnsConfigServiceForTesting(
         std::move(dns_config_service));
   }
 
@@ -37,6 +42,7 @@
  private:
   base::test::TaskEnvironment task_environment_;
   net::NetworkChangeNotifier::DisableForTest mock_notifier_disabler_;
+  std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
   std::unique_ptr<NetworkChangeNotifierPosix> notifier_;
   TestDnsConfigService* dns_config_service_;
 };
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index 1b5b386..584caa6 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -44,11 +44,13 @@
 
 #include "net/cookies/canonical_cookie.h"
 
+#include <sstream>
 #include <utility>
 
 #include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "net/base/url_util.h"
@@ -101,6 +103,36 @@
   *cookie_line += cookie.Value();
 }
 
+uint32_t GetBitmask(
+    CanonicalCookie::CookieInclusionStatus::ExclusionReason reason) {
+  return 1u << static_cast<uint32_t>(reason);
+}
+
+void ApplySameSiteCookieWarningToStatus(
+    CookieSameSite samesite,
+    CookieSameSite effective_samesite,
+    bool is_secure,
+    CookieOptions::SameSiteCookieContext context,
+    CanonicalCookie::CookieInclusionStatus* status) {
+  if (samesite == CookieSameSite::UNSPECIFIED &&
+      context < CookieOptions::SameSiteCookieContext::SAME_SITE_LAX) {
+    status->set_warning(CanonicalCookie::CookieInclusionStatus::
+                            WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
+  }
+  // This will overwrite the previous warning but it is more specific so that
+  // is ok.
+  if (effective_samesite == CookieSameSite::LAX_MODE_ALLOW_UNSAFE &&
+      context ==
+          CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE) {
+    status->set_warning(CanonicalCookie::CookieInclusionStatus::
+                            WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
+  }
+  if (samesite == CookieSameSite::NO_RESTRICTION && !is_secure) {
+    status->set_warning(
+        CanonicalCookie::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
+  }
+}
+
 }  // namespace
 
 // Keep defaults here in sync with content/public/common/cookie_manager.mojom.
@@ -211,23 +243,25 @@
   if (status == nullptr) {
     status = &blank_status;
   }
-  *status = CookieInclusionStatus::INCLUDE;
+  *status = CookieInclusionStatus();
 
   ParsedCookie parsed_cookie(cookie_line);
 
   if (!parsed_cookie.IsValid()) {
     DVLOG(net::cookie_util::kVlogSetCookies)
         << "WARNING: Couldn't parse cookie";
-    *status = CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
+    status->AddExclusionReason(CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+    // Don't continue, because an invalid ParsedCookie doesn't have any
+    // attributes.
+    // TODO(chlily): Log metrics.
     return nullptr;
   }
 
   std::string cookie_domain;
   if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) {
     DVLOG(net::cookie_util::kVlogSetCookies)
-        << "Create() failed to get a cookie domain";
-    *status = CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
-    return nullptr;
+        << "Create() failed to get a valid cookie domain";
+    status->AddExclusionReason(CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
   }
 
   std::string cookie_path = CanonPathWithString(
@@ -242,15 +276,18 @@
       parsed_cookie, creation_time, cookie_server_time);
 
   CookiePrefix prefix = GetCookiePrefix(parsed_cookie.Name());
-  bool is_cookie_valid = IsCookiePrefixValid(prefix, url, parsed_cookie);
-  RecordCookiePrefixMetrics(prefix, is_cookie_valid);
-  if (!is_cookie_valid) {
+  bool is_cookie_prefix_valid = IsCookiePrefixValid(prefix, url, parsed_cookie);
+  RecordCookiePrefixMetrics(prefix, is_cookie_prefix_valid);
+  if (!is_cookie_prefix_valid) {
     DVLOG(net::cookie_util::kVlogSetCookies)
         << "Create() failed because the cookie violated prefix rules.";
-    *status = CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
-    return nullptr;
+    status->AddExclusionReason(CookieInclusionStatus::EXCLUDE_INVALID_PREFIX);
   }
 
+  // TODO(chlily): Log metrics.
+  if (!status->IsInclude())
+    return nullptr;
+
   std::unique_ptr<CanonicalCookie> cc(std::make_unique<CanonicalCookie>(
       parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path,
       creation_time, cookie_expires, creation_time, parsed_cookie.IsSecure(),
@@ -258,7 +295,8 @@
       parsed_cookie.Priority()));
 
   DCHECK(cc->IsCanonical());
-  DCHECK(*status == CookieInclusionStatus::INCLUDE);
+
+  // TODO(chlily): Log metrics.
   return cc;
 }
 
@@ -376,26 +414,29 @@
     const GURL& url,
     const CookieOptions& options) const {
   base::TimeDelta cookie_age = base::Time::Now() - CreationDate();
+  CookieInclusionStatus status;
   // Filter out HttpOnly cookies, per options.
   if (options.exclude_httponly() && IsHttpOnly())
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
+    status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
   // Secure cookies should not be included in requests for URLs with an
   // insecure scheme.
   if (IsSecure() && !url.SchemeIsCryptographic())
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
+    status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
   // Don't include cookies for requests that don't apply to the cookie domain.
   if (!IsDomainMatch(url.host()))
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH;
+    status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
   // Don't include cookies for requests with a url path that does not path
   // match the cookie-path.
   if (!IsOnPath(url.path()))
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH;
+    status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_NOT_ON_PATH);
   // Don't include same-site cookies for cross-site requests.
-  switch (GetEffectiveSameSite()) {
+  CookieSameSite effective_same_site = GetEffectiveSameSite();
+  switch (effective_same_site) {
     case CookieSameSite::STRICT_MODE:
       if (options.same_site_cookie_context() <
           CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT) {
-        return CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
+        status.AddExclusionReason(
+            CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT);
       }
       break;
     case CookieSameSite::LAX_MODE:
@@ -412,11 +453,11 @@
               base::TimeDelta::FromMinutes(1), base::TimeDelta::FromDays(5),
               100);
         }
-        return (SameSite() == CookieSameSite::UNSPECIFIED)
-                   ? CanonicalCookie::CookieInclusionStatus::
-                         EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX
-                   : CanonicalCookie::CookieInclusionStatus::
-                         EXCLUDE_SAMESITE_LAX;
+        status.AddExclusionReason(
+            (SameSite() == CookieSameSite::UNSPECIFIED)
+                ? CookieInclusionStatus::
+                      EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX
+                : CookieInclusionStatus::EXCLUDE_SAMESITE_LAX);
       }
       break;
     // TODO(crbug.com/990439): Add a browsertest for this behavior.
@@ -425,8 +466,8 @@
       if (options.same_site_cookie_context() <
           CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE) {
         // TODO(chlily): Do we need a separate CookieInclusionStatus for this?
-        return CanonicalCookie::CookieInclusionStatus::
-            EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX;
+        status.AddExclusionReason(
+            CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
       } else if (options.same_site_cookie_context() ==
                  CookieOptions::SameSiteCookieContext::
                      SAME_SITE_LAX_METHOD_UNSAFE) {
@@ -448,22 +489,29 @@
   // be set while the options are on).
   if (cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled() &&
       IsEffectivelySameSiteNone() && !IsSecure()) {
-    return CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE;
+    status.AddExclusionReason(
+        CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
   }
 
-  return CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  ApplySameSiteCookieWarningToStatus(
+      SameSite(), effective_same_site, IsSecure(),
+      options.same_site_cookie_context(), &status);
+
+  // TODO(chlily): Log metrics.
+  return status;
 }
 
 CanonicalCookie::CookieInclusionStatus CanonicalCookie::IsSetPermittedInContext(
     const CookieOptions& options) const {
+  CookieInclusionStatus status;
   if (options.exclude_httponly() && IsHttpOnly()) {
     DVLOG(net::cookie_util::kVlogSetCookies)
         << "HttpOnly cookie not permitted in script context.";
-    return CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
+    status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
   }
 
-  switch (GetEffectiveSameSite()) {
+  CookieSameSite effective_same_site = GetEffectiveSameSite();
+  switch (effective_same_site) {
     case CookieSameSite::STRICT_MODE:
       // This intentionally checks for `< SAME_SITE_LAX`, as we allow
       // `SameSite=Strict` cookies to be set for top-level navigations that
@@ -473,7 +521,8 @@
         DVLOG(net::cookie_util::kVlogSetCookies)
             << "Trying to set a `SameSite=Strict` cookie from a "
                "cross-site URL.";
-        return CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
+        status.AddExclusionReason(
+            CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT);
       }
       break;
     case CookieSameSite::LAX_MODE:
@@ -484,12 +533,14 @@
           DVLOG(net::cookie_util::kVlogSetCookies)
               << "Cookies with no known SameSite attribute being treated as "
                  "lax; attempt to set from a cross-site URL denied.";
-          return CanonicalCookie::CookieInclusionStatus::
-              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX;
+          status.AddExclusionReason(
+              CookieInclusionStatus::
+                  EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
         } else {
           DVLOG(net::cookie_util::kVlogSetCookies)
               << "Trying to set a `SameSite=Lax` cookie from a cross-site URL.";
-          return CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX;
+          status.AddExclusionReason(
+              CookieInclusionStatus::EXCLUDE_SAMESITE_LAX);
         }
       }
       break;
@@ -497,7 +548,12 @@
       break;
   }
 
-  return CookieInclusionStatus::INCLUDE;
+  ApplySameSiteCookieWarningToStatus(
+      SameSite(), effective_same_site, IsSecure(),
+      options.same_site_cookie_context(), &status);
+
+  // TODO(chlily): Log metrics.
+  return status;
 }
 
 std::string CanonicalCookie::DebugString() const {
@@ -672,6 +728,142 @@
   return domain_.substr(1);
 }
 
+CanonicalCookie::CookieInclusionStatus::CookieInclusionStatus()
+    : exclusion_reasons_(0u), warning_(DO_NOT_WARN) {}
+
+CanonicalCookie::CookieInclusionStatus::CookieInclusionStatus(
+    ExclusionReason reason,
+    WarningReason warning)
+    : exclusion_reasons_(GetBitmask(reason)), warning_(warning) {}
+
+bool CanonicalCookie::CookieInclusionStatus::operator==(
+    const CookieInclusionStatus& other) const {
+  return exclusion_reasons_ == other.exclusion_reasons_ &&
+         warning_ == other.warning_;
+}
+
+bool CanonicalCookie::CookieInclusionStatus::operator!=(
+    const CookieInclusionStatus& other) const {
+  return !operator==(other);
+}
+
+bool CanonicalCookie::CookieInclusionStatus::IsInclude() const {
+  return exclusion_reasons_ == 0u;
+}
+
+bool CanonicalCookie::CookieInclusionStatus::HasExclusionReason(
+    ExclusionReason reason) const {
+  return exclusion_reasons_ & GetBitmask(reason);
+}
+
+void CanonicalCookie::CookieInclusionStatus::AddExclusionReason(
+    ExclusionReason reason) {
+  exclusion_reasons_ |= GetBitmask(reason);
+}
+
+void CanonicalCookie::CookieInclusionStatus::AddExclusionReasonsAndWarningIfAny(
+    const CookieInclusionStatus& other) {
+  exclusion_reasons_ |= other.exclusion_reasons_;
+  if (other.warning_ != DO_NOT_WARN)
+    warning_ = other.warning_;
+}
+
+void CanonicalCookie::CookieInclusionStatus::RemoveExclusionReason(
+    ExclusionReason reason) {
+  exclusion_reasons_ &= ~(GetBitmask(reason));
+}
+
+bool CanonicalCookie::CookieInclusionStatus::ShouldWarn() const {
+  return warning_ != DO_NOT_WARN;
+}
+
+std::string CanonicalCookie::CookieInclusionStatus::GetDebugString() const {
+  std::string out;
+
+  // Inclusion/exclusion
+  if (IsInclude())
+    base::StrAppend(&out, {"INCLUDE, "});
+  if (HasExclusionReason(EXCLUDE_UNKNOWN_ERROR))
+    base::StrAppend(&out, {"EXCLUDE_UNKNOWN_ERROR, "});
+  if (HasExclusionReason(EXCLUDE_HTTP_ONLY))
+    base::StrAppend(&out, {"EXCLUDE_HTTP_ONLY, "});
+  if (HasExclusionReason(EXCLUDE_SECURE_ONLY))
+    base::StrAppend(&out, {"EXCLUDE_SECURE_ONLY, "});
+  if (HasExclusionReason(EXCLUDE_DOMAIN_MISMATCH))
+    base::StrAppend(&out, {"EXCLUDE_DOMAIN_MISMATCH, "});
+  if (HasExclusionReason(EXCLUDE_NOT_ON_PATH))
+    base::StrAppend(&out, {"EXCLUDE_NOT_ON_PATH, "});
+  if (HasExclusionReason(EXCLUDE_SAMESITE_STRICT))
+    base::StrAppend(&out, {"EXCLUDE_SAMESITE_STRICT, "});
+  if (HasExclusionReason(EXCLUDE_SAMESITE_LAX))
+    base::StrAppend(&out, {"EXCLUDE_SAMESITE_LAX, "});
+  if (HasExclusionReason(EXCLUDE_SAMESITE_EXTENDED))
+    base::StrAppend(&out, {"EXCLUDE_SAMESITE_EXTENDED, "});
+  if (HasExclusionReason(EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX))
+    base::StrAppend(&out, {"EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, "});
+  if (HasExclusionReason(EXCLUDE_SAMESITE_NONE_INSECURE))
+    base::StrAppend(&out, {"EXCLUDE_SAMESITE_NONE_INSECURE, "});
+  if (HasExclusionReason(EXCLUDE_USER_PREFERENCES))
+    base::StrAppend(&out, {"EXCLUDE_USER_PREFERENCES, "});
+  if (HasExclusionReason(EXCLUDE_FAILURE_TO_STORE))
+    base::StrAppend(&out, {"EXCLUDE_FAILURE_TO_STORE, "});
+  if (HasExclusionReason(EXCLUDE_NONCOOKIEABLE_SCHEME))
+    base::StrAppend(&out, {"EXCLUDE_NONCOOKIEABLE_SCHEME, "});
+  if (HasExclusionReason(EXCLUDE_OVERWRITE_SECURE))
+    base::StrAppend(&out, {"EXCLUDE_OVERWRITE_SECURE, "});
+  if (HasExclusionReason(EXCLUDE_OVERWRITE_HTTP_ONLY))
+    base::StrAppend(&out, {"EXCLUDE_OVERWRITE_HTTP_ONLY, "});
+  if (HasExclusionReason(EXCLUDE_INVALID_DOMAIN))
+    base::StrAppend(&out, {"EXCLUDE_INVALID_DOMAIN, "});
+  if (HasExclusionReason(EXCLUDE_INVALID_PREFIX))
+    base::StrAppend(&out, {"EXCLUDE_INVALID_PREFIX, "});
+
+  // Add warning
+  switch (warning_) {
+    case DO_NOT_WARN:
+      base::StrAppend(&out, {"DO_NOT_WARN"});
+      break;
+    case WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT:
+      base::StrAppend(&out, {"WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT"});
+      break;
+    case WARN_SAMESITE_NONE_INSECURE:
+      base::StrAppend(&out, {"WARN_SAMESITE_NONE_INSECURE"});
+      break;
+    case WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE:
+      base::StrAppend(&out, {"WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE"});
+      break;
+  }
+
+  return out;
+}
+
+bool CanonicalCookie::CookieInclusionStatus::IsValid() const {
+  // Bit positions where there should not be any true bits.
+  uint32_t mask = ~0u << static_cast<int>(NUM_EXCLUSION_REASONS);
+  return (mask & exclusion_reasons_) == 0u;
+}
+
+bool CanonicalCookie::CookieInclusionStatus::
+    HasExactlyExclusionReasonsForTesting(
+        std::vector<CanonicalCookie::CookieInclusionStatus::ExclusionReason>
+            reasons) const {
+  CookieInclusionStatus expected = MakeFromReasonsForTesting(reasons);
+  return expected.exclusion_reasons_ == exclusion_reasons_;
+}
+
+// static
+CanonicalCookie::CookieInclusionStatus
+CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+    std::vector<ExclusionReason> reasons,
+    WarningReason warning) {
+  CookieInclusionStatus status;
+  for (ExclusionReason reason : reasons) {
+    status.AddExclusionReason(reason);
+  }
+  status.set_warning(warning);
+  return status;
+}
+
 CookieAndLineWithStatus::CookieAndLineWithStatus() = default;
 
 CookieAndLineWithStatus::CookieAndLineWithStatus(
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index 061d6b7..e91331d 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -33,6 +33,8 @@
 
 class NET_EXPORT CanonicalCookie {
  public:
+  class CookieInclusionStatus;
+
   CanonicalCookie();
   CanonicalCookie(const CanonicalCookie& other);
 
@@ -58,39 +60,6 @@
 
   // Supports the default copy constructor.
 
-  // This enum represents if a cookie was included or excluded, and if excluded
-  // why.
-  enum class CookieInclusionStatus {
-    INCLUDE = 0,
-    EXCLUDE_HTTP_ONLY,
-    EXCLUDE_SECURE_ONLY,
-    EXCLUDE_DOMAIN_MISMATCH,
-    EXCLUDE_NOT_ON_PATH,
-    EXCLUDE_SAMESITE_STRICT,
-    EXCLUDE_SAMESITE_LAX,
-    // TODO(crbug.com/989171): Replace this with FirstPartyLax and
-    // FirstPartyStrict.
-    EXCLUDE_SAMESITE_EXTENDED,
-    // The following two are used for the SameSiteByDefaultCookies experiment,
-    // where if the SameSite attribute is not specified, it will be treated as
-    // SameSite=Lax by default.
-    EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
-    // This is used if SameSite=None is specified, but the cookie is not Secure.
-    EXCLUDE_SAMESITE_NONE_INSECURE,
-    EXCLUDE_USER_PREFERENCES,
-
-    // Statuses specific to setting cookies
-    EXCLUDE_FAILURE_TO_STORE,
-    EXCLUDE_NONCOOKIEABLE_SCHEME,
-    EXCLUDE_OVERWRITE_SECURE,
-    EXCLUDE_OVERWRITE_HTTP_ONLY,
-    EXCLUDE_INVALID_DOMAIN,
-    EXCLUDE_INVALID_PREFIX,
-
-    // Please keep last
-    EXCLUDE_UNKNOWN_ERROR
-  };
-
   // Creates a new |CanonicalCookie| from the |cookie_line| and the
   // |creation_time|.  Canonicalizes inputs.  May return nullptr if
   // an attribute value is invalid.  |url| must be valid.  |creation_time| may
@@ -321,6 +290,138 @@
   CookiePriority priority_;
 };
 
+// This class represents if a cookie was included or excluded in a cookie get or
+// set operation, and if excluded why. It holds a vector of reasons for
+// exclusion, where cookie inclusion is represented by the absence of any
+// exclusion reasons. Also marks whether a cookie should be warned about, e.g.
+// for deprecation or intervention reasons.
+// TODO(chlily): Rename/move this to just net::CookieInclusionStatus.
+class NET_EXPORT CanonicalCookie::CookieInclusionStatus {
+ public:
+  // Types of reasons why a cookie might be excluded.
+  // If adding a ExclusionReason, please also update the GetDebugString()
+  // method.
+  enum ExclusionReason {
+    EXCLUDE_UNKNOWN_ERROR = 0,
+
+    EXCLUDE_HTTP_ONLY = 1,
+    EXCLUDE_SECURE_ONLY = 2,
+    EXCLUDE_DOMAIN_MISMATCH = 3,
+    EXCLUDE_NOT_ON_PATH = 4,
+    EXCLUDE_SAMESITE_STRICT = 5,
+    EXCLUDE_SAMESITE_LAX = 6,
+    // TODO(crbug.com/989171): Replace this with FirstPartyLax and
+    // FirstPartyStrict.
+    EXCLUDE_SAMESITE_EXTENDED = 7,
+    // The following two are used for the SameSiteByDefaultCookies experiment,
+    // where if the SameSite attribute is not specified, it will be treated as
+    // SameSite=Lax by default.
+    EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX = 8,
+    // This is used if SameSite=None is specified, but the cookie is not
+    // Secure.
+    EXCLUDE_SAMESITE_NONE_INSECURE = 9,
+    EXCLUDE_USER_PREFERENCES = 10,
+
+    // Statuses specific to setting cookies
+    EXCLUDE_FAILURE_TO_STORE = 11,
+    EXCLUDE_NONCOOKIEABLE_SCHEME = 12,
+    EXCLUDE_OVERWRITE_SECURE = 13,
+    EXCLUDE_OVERWRITE_HTTP_ONLY = 14,
+    EXCLUDE_INVALID_DOMAIN = 15,
+    EXCLUDE_INVALID_PREFIX = 16,
+
+    // This should be kept last.
+    NUM_EXCLUSION_REASONS
+  };
+
+  // Reason to warn about a cookie. If you add one, please update
+  // GetDebugString().
+  // TODO(chlily): Do we need to support multiple warning statuses?
+  enum WarningReason {
+    DO_NOT_WARN = 0,
+    // Warn if a cookie with unspecified SameSite attribute is used in a
+    // cross-site context.
+    WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+    // Warn if a cookie with SameSite=None is not Secure.
+    WARN_SAMESITE_NONE_INSECURE,
+    // Warn if a cookie with unspecified SameSite attribute is defaulted into
+    // Lax and is sent on a request with unsafe method, only because it is new
+    // enough to activate the Lax-allow-unsafe intervention.
+    WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE,
+  };
+
+  // Makes a status that says include.
+  CookieInclusionStatus();
+
+  // Makes a status that contains the given exclusion reason and warning.
+  explicit CookieInclusionStatus(ExclusionReason reason,
+                                 WarningReason warning = DO_NOT_WARN);
+
+  bool operator==(const CookieInclusionStatus& other) const;
+  bool operator!=(const CookieInclusionStatus& other) const;
+
+  // Whether the status is to include the cookie, and has no other reasons for
+  // exclusion.
+  bool IsInclude() const;
+
+  // Whether the given reason for exclusion is present.
+  bool HasExclusionReason(ExclusionReason status_type) const;
+
+  // Add an exclusion reason.
+  void AddExclusionReason(ExclusionReason status_type);
+
+  // Add all the exclusion reasons given in |other|. If there is a warning in
+  // |other| (other than DO_NOT_WARN), also apply that. This could overwrite the
+  // existing warning, so set the most important warnings last.
+  void AddExclusionReasonsAndWarningIfAny(const CookieInclusionStatus& other);
+
+  // Remove an exclusion reason.
+  void RemoveExclusionReason(ExclusionReason reason);
+
+  // Whether the cookie should be warned about.
+  bool ShouldWarn() const;
+
+  WarningReason warning() const { return warning_; }
+  void set_warning(WarningReason warning) { warning_ = warning; }
+
+  // Used for serialization/deserialization.
+  uint32_t exclusion_reasons() const { return exclusion_reasons_; }
+  void set_exclusion_reasons(uint32_t exclusion_reasons) {
+    exclusion_reasons_ = exclusion_reasons;
+  }
+
+  // Get exclusion reason(s) and warning in string format.
+  std::string GetDebugString() const;
+
+  // Checks that the underlying bit vector representation doesn't contain any
+  // extraneous bits that are not mapped to any enum values. Does not check
+  // for reasons which semantically cannot coexist.
+  bool IsValid() const;
+
+  // Checks whether the exclusion reasons are exactly the set of exclusion
+  // reasons in the vector. (Ignores warnings.)
+  bool HasExactlyExclusionReasonsForTesting(
+      std::vector<ExclusionReason> reasons) const;
+
+  // Makes a status that contains the given exclusion reasons and warning.
+  static CookieInclusionStatus MakeFromReasonsForTesting(
+      std::vector<ExclusionReason> reasons,
+      WarningReason warning = DO_NOT_WARN);
+
+ private:
+  // A bit vector of the applicable exclusion reasons.
+  uint32_t exclusion_reasons_ = 0u;
+
+  // Applicable warning reason.
+  WarningReason warning_ = DO_NOT_WARN;
+};
+
+NET_EXPORT inline std::ostream& operator<<(
+    std::ostream& os,
+    const CanonicalCookie::CookieInclusionStatus status) {
+  return os << status.GetDebugString();
+}
+
 // These enable us to pass along a list of excluded cookie with the reason they
 // were excluded
 struct CookieWithStatus {
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 2d2018e0..04afd97 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -201,7 +201,7 @@
   std::unique_ptr<CanonicalCookie> cookie =
       CanonicalCookie::Create(url, "A=2; HttpOnly", now, server_time, &status);
   EXPECT_TRUE(cookie->IsHttpOnly());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+  EXPECT_TRUE(status.IsInclude());
 }
 
 TEST(CanonicalCookieTest, CreateWithInvalidDomain) {
@@ -213,8 +213,8 @@
   std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
       url, "A=2; Domain=wrongdomain.com", now, server_time, &status);
   EXPECT_EQ(nullptr, cookie.get());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
 }
 
 TEST(CanonicalCookieTest, EmptyExpiry) {
@@ -630,40 +630,50 @@
 
   std::unique_ptr<CanonicalCookie> cookie(
       CanonicalCookie::Create(url, "A=2", creation_time, server_time));
-  EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
-  EXPECT_EQ(cookie->IncludeForRequestURL(GURL("http://www.example.com/foo/bar"),
-                                         options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
-  EXPECT_EQ(cookie->IncludeForRequestURL(
-                GURL("https://www.example.com/foo/bar"), options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
-  EXPECT_EQ(
-      cookie->IncludeForRequestURL(GURL("https://sub.example.com"), options),
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
-  EXPECT_EQ(cookie->IncludeForRequestURL(GURL("https://sub.www.example.com"),
-                                         options),
-            CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
+  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).IsInclude());
+  EXPECT_TRUE(cookie
+                  ->IncludeForRequestURL(GURL("http://www.example.com/foo/bar"),
+                                         options)
+                  .IsInclude());
+  EXPECT_TRUE(cookie
+                  ->IncludeForRequestURL(
+                      GURL("https://www.example.com/foo/bar"), options)
+                  .IsInclude());
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(GURL("https://sub.example.com"), options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_DOMAIN_MISMATCH}));
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(GURL("https://sub.www.example.com"), options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_DOMAIN_MISMATCH}));
 
   // Test that cookie with a cookie path that does not match the url path are
   // not included.
   cookie = CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
                                    server_time);
-  EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
-            CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH);
-  EXPECT_EQ(cookie->IncludeForRequestURL(
-                GURL("http://www.example.com/foo/bar/index.html"), options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(url, options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
+  EXPECT_TRUE(
+      cookie
+          ->IncludeForRequestURL(
+              GURL("http://www.example.com/foo/bar/index.html"), options)
+          .IsInclude());
 
   // Test that a secure cookie is not included for a non secure URL.
   GURL secure_url("https://www.example.com");
   cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
                                    server_time);
   EXPECT_TRUE(cookie->IsSecure());
-  EXPECT_EQ(cookie->IncludeForRequestURL(secure_url, options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
-  EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
-            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
+  EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options).IsInclude());
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(url, options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   // Test that http only cookies are only included if the include httponly flag
   // is set on the cookie options.
@@ -671,11 +681,12 @@
   cookie =
       CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
   EXPECT_TRUE(cookie->IsHttpOnly());
-  EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
-            CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).IsInclude());
   options.set_exclude_httponly();
-  EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
-            CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(url, options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 }
 
 TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
@@ -696,167 +707,191 @@
       {"A=2; SameSite=Strict", false, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", false, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", false, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", false, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // Lax cookies:
       {"A=2; SameSite=Lax", false, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
       {"A=2; SameSite=Lax", false, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
       {"A=2; SameSite=Lax", false, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=Lax", false, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // None cookies:
       {"A=2; SameSite=None; Secure", false, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
-      {"A=2; SameSite=None; Secure", false, CookieSameSite::NO_RESTRICTION,
-       CookieSameSite::NO_RESTRICTION,
-       CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", false, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", false, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", false, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // Unspecified cookies (without SameSite-by-default):
       {"A=2", false, CookieSameSite::UNSPECIFIED,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
-      {"A=2", false, CookieSameSite::UNSPECIFIED,
-       CookieSameSite::NO_RESTRICTION,
-       CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<
+               CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)},
       {"A=2", false, CookieSameSite::UNSPECIFIED,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<
+               CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)},
       {"A=2", false, CookieSameSite::UNSPECIFIED,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2", false, CookieSameSite::UNSPECIFIED,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
 
       // SameSite-by-default is enabled:
       // Strict cookies:
       {"A=2; SameSite=Strict", true, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", true, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", true, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
       {"A=2; SameSite=Strict", true, CookieSameSite::STRICT_MODE,
        CookieSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // Lax cookies:
       {"A=2; SameSite=Lax", true, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
       {"A=2; SameSite=Lax", true, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
       {"A=2; SameSite=Lax", true, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=Lax", true, CookieSameSite::LAX_MODE,
        CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // None cookies:
       {"A=2; SameSite=None; Secure", true, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", true, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", true, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       {"A=2; SameSite=None; Secure", true, CookieSameSite::NO_RESTRICTION,
        CookieSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE},
+       CanonicalCookie::CookieInclusionStatus()},
       // Unspecified recently-created cookies (with SameSite-by-default):
       {"A=2", true, CookieSameSite::UNSPECIFIED,
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::
-           EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kShortAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED,
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE, kShortAge},
+       CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<
+               CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE),
+       kShortAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED,
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE, kShortAge},
+       CanonicalCookie::CookieInclusionStatus(), kShortAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED,
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE, kShortAge},
+       CanonicalCookie::CookieInclusionStatus(), kShortAge},
       // Unspecified not-recently-created cookies (with SameSite-by-default):
       {"A=2", true, CookieSameSite::UNSPECIFIED, CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
-       CanonicalCookie::CookieInclusionStatus::
-           EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kLongAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED, CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
-       CanonicalCookie::CookieInclusionStatus::
-           EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kLongAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED, CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), kLongAge},
       {"A=2", true, CookieSameSite::UNSPECIFIED, CookieSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
-       CanonicalCookie::CookieInclusionStatus::INCLUDE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), kLongAge},
   };
 
   GURL url("https://example.test");
@@ -914,12 +949,60 @@
          features::kCookiesWithoutSameSiteMustBeSecure} /* enabled_features */,
         {} /* disabled_features */);
 
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE,
-        cookie->IncludeForRequestURL(url, options));
+    EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)
+                    .HasExactlyExclusionReasonsForTesting(
+                        {CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_SAMESITE_NONE_INSECURE}));
   }
 }
 
+TEST(CanonicalCookieTest, MultipleExclusionReasons) {
+  GURL url("http://www.not-secure.com/foo");
+  base::Time creation_time = base::Time::Now();
+  base::Optional<base::Time> server_time = base::nullopt;
+  CookieOptions options;
+  options.set_exclude_httponly();
+  options.set_same_site_cookie_context(
+      CookieOptions::SameSiteCookieContext::CROSS_SITE);
+
+  // Test IncludeForRequestURL()
+  // Note: This is a cookie that should never exist normally, because Create()
+  // would weed it out.
+  CanonicalCookie cookie1 = CanonicalCookie(
+      "name", "value", "other-domain.com", "/bar", creation_time, base::Time(),
+      base::Time(), true /* secure */, true /* httponly */,
+      CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT);
+  EXPECT_TRUE(
+      cookie1.IncludeForRequestURL(url, options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+               CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
+               CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
+               CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
+               CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_SAMESITE_STRICT}));
+
+  // Test Create()
+  CanonicalCookie::CookieInclusionStatus create_status;
+  auto cookie2 = CanonicalCookie::Create(
+      url, "__Secure-notactuallysecure=value;Domain=some-other-domain.com",
+      creation_time, server_time, &create_status);
+  ASSERT_FALSE(cookie2);
+  EXPECT_TRUE(create_status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+       CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
+
+  // Test IsSetPermittedInContext()
+  auto cookie3 = CanonicalCookie::Create(
+      url, "name=value;HttpOnly;SameSite=Lax", creation_time, server_time);
+  ASSERT_TRUE(cookie3);
+  EXPECT_TRUE(
+      cookie3->IsSetPermittedInContext(options)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+               CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX}));
+}
+
 TEST(CanonicalCookieTest, PartialCompare) {
   GURL url("http://www.example.com");
   base::Time creation_time = base::Time::Now();
@@ -958,13 +1041,13 @@
   // A __Secure- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
                                        server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
                                        creation_time, server_time, &status));
   // (EXCLUDE_HTTP_ONLY would be fine, too)
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
 
   // A typoed prefix does not have to be Secure.
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
@@ -979,8 +1062,8 @@
   // A __Secure- cookie can't be set on a non-secure origin.
   EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
                                        creation_time, server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
 }
 
 TEST(CanonicalCookieTest, HostCookiePrefix) {
@@ -994,13 +1077,13 @@
   // A __Host- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
                                        server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
       server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
                                       creation_time, server_time));
 
@@ -1008,8 +1091,8 @@
   EXPECT_FALSE(CanonicalCookie::Create(
       http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
       creation_time, server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
                                       creation_time, server_time));
 
@@ -1017,13 +1100,13 @@
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
       creation_time, server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
       server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
 
   // A __Host- cookie may have a domain if it's an IP address that matches the
   // URL.
@@ -1041,12 +1124,12 @@
   EXPECT_FALSE(CanonicalCookie::Create(https_url,
                                        "__Host-A=B; Path=/foo; Secure;",
                                        creation_time, server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
                                        creation_time, server_time, &status));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-            status);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
                                       creation_time, server_time));
 
@@ -1806,15 +1889,17 @@
   CookieOptions context_network;
   context_network.set_include_httponly();
 
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            cookie_scriptable.IsSetPermittedInContext(context_network));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            cookie_scriptable.IsSetPermittedInContext(context_script));
+  EXPECT_TRUE(
+      cookie_scriptable.IsSetPermittedInContext(context_network).IsInclude());
+  EXPECT_TRUE(
+      cookie_scriptable.IsSetPermittedInContext(context_script).IsInclude());
 
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            cookie_httponly.IsSetPermittedInContext(context_network));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-            cookie_httponly.IsSetPermittedInContext(context_script));
+  EXPECT_TRUE(
+      cookie_httponly.IsSetPermittedInContext(context_network).IsInclude());
+  EXPECT_TRUE(
+      cookie_httponly.IsSetPermittedInContext(context_script)
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 
   CookieOptions context_cross_site;
   CookieOptions context_same_site_lax;
@@ -1830,15 +1915,15 @@
         base::Time(), true /*secure*/, false /*httponly*/,
         CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
 
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unrestricted.IsSetPermittedInContext(
-                  context_cross_site));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unrestricted.IsSetPermittedInContext(
-                  context_same_site_lax));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unrestricted.IsSetPermittedInContext(
-                  context_same_site_strict));
+    EXPECT_TRUE(cookie_same_site_unrestricted
+                    .IsSetPermittedInContext(context_cross_site)
+                    .IsInclude());
+    EXPECT_TRUE(cookie_same_site_unrestricted
+                    .IsSetPermittedInContext(context_same_site_lax)
+                    .IsInclude());
+    EXPECT_TRUE(cookie_same_site_unrestricted
+                    .IsSetPermittedInContext(context_same_site_strict)
+                    .IsInclude());
   }
 
   {
@@ -1847,14 +1932,16 @@
         base::Time(), true /*secure*/, false /*httponly*/,
         CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT);
 
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
-              cookie_same_site_lax.IsSetPermittedInContext(context_cross_site));
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::INCLUDE,
-        cookie_same_site_lax.IsSetPermittedInContext(context_same_site_lax));
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::INCLUDE,
-        cookie_same_site_lax.IsSetPermittedInContext(context_same_site_strict));
+    EXPECT_TRUE(cookie_same_site_lax.IsSetPermittedInContext(context_cross_site)
+                    .HasExactlyExclusionReasonsForTesting(
+                        {CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_SAMESITE_LAX}));
+    EXPECT_TRUE(
+        cookie_same_site_lax.IsSetPermittedInContext(context_same_site_lax)
+            .IsInclude());
+    EXPECT_TRUE(
+        cookie_same_site_lax.IsSetPermittedInContext(context_same_site_strict)
+            .IsInclude());
   }
 
   {
@@ -1865,15 +1952,17 @@
 
     // TODO(morlovich): Do compatibility testing on whether set of strict in lax
     // context really should be accepted.
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
-        cookie_same_site_strict.IsSetPermittedInContext(context_cross_site));
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::INCLUDE,
-        cookie_same_site_strict.IsSetPermittedInContext(context_same_site_lax));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_strict.IsSetPermittedInContext(
-                  context_same_site_strict));
+    EXPECT_TRUE(
+        cookie_same_site_strict.IsSetPermittedInContext(context_cross_site)
+            .HasExactlyExclusionReasonsForTesting(
+                {CanonicalCookie::CookieInclusionStatus::
+                     EXCLUDE_SAMESITE_STRICT}));
+    EXPECT_TRUE(
+        cookie_same_site_strict.IsSetPermittedInContext(context_same_site_lax)
+            .IsInclude());
+    EXPECT_TRUE(cookie_same_site_strict
+                    .IsSetPermittedInContext(context_same_site_strict)
+                    .IsInclude());
   }
 
   // Behavior of UNSPECIFIED depends on an experiment.
@@ -1886,32 +1975,130 @@
     base::test::ScopedFeatureList feature_list;
     feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
 
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_cross_site));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_same_site_lax));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_same_site_strict));
+    EXPECT_TRUE(
+        cookie_same_site_unspecified.IsSetPermittedInContext(context_cross_site)
+            .IsInclude());
+    EXPECT_TRUE(cookie_same_site_unspecified
+                    .IsSetPermittedInContext(context_same_site_lax)
+                    .IsInclude());
+    EXPECT_TRUE(cookie_same_site_unspecified
+                    .IsSetPermittedInContext(context_same_site_strict)
+                    .IsInclude());
   }
 
   {
     base::test::ScopedFeatureList feature_list;
     feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
 
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::
-                  EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_cross_site));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_same_site_lax));
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              cookie_same_site_unspecified.IsSetPermittedInContext(
-                  context_same_site_strict));
+    EXPECT_TRUE(
+        cookie_same_site_unspecified.IsSetPermittedInContext(context_cross_site)
+            .HasExactlyExclusionReasonsForTesting(
+                {CanonicalCookie::CookieInclusionStatus::
+                     EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
+    EXPECT_TRUE(cookie_same_site_unspecified
+                    .IsSetPermittedInContext(context_same_site_lax)
+                    .IsInclude());
+    EXPECT_TRUE(cookie_same_site_unspecified
+                    .IsSetPermittedInContext(context_same_site_strict)
+                    .IsInclude());
   }
 }
 
+TEST(CookieInclusionStatusTest, IncludeStatus) {
+  int num_exclusion_reasons = static_cast<int>(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS);
+  // Zero-argument constructor
+  CanonicalCookie::CookieInclusionStatus status;
+  EXPECT_TRUE(status.IsValid());
+  EXPECT_TRUE(status.IsInclude());
+  for (int i = 0; i < num_exclusion_reasons; ++i) {
+    EXPECT_FALSE(status.HasExclusionReason(
+        static_cast<CanonicalCookie::CookieInclusionStatus::ExclusionReason>(
+            i)));
+  }
+  EXPECT_FALSE(status.HasExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
+}
+
+TEST(CookieInclusionStatusTest, ExcludeStatus) {
+  int num_exclusion_reasons = static_cast<int>(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS);
+  for (int i = 0; i < num_exclusion_reasons; ++i) {
+    auto reason =
+        static_cast<CanonicalCookie::CookieInclusionStatus::ExclusionReason>(i);
+    CanonicalCookie::CookieInclusionStatus status(reason);
+    EXPECT_TRUE(status.IsValid());
+    EXPECT_FALSE(status.IsInclude());
+    EXPECT_TRUE(status.HasExclusionReason(reason));
+    for (int j = 0; j < num_exclusion_reasons; ++j) {
+      if (i == j)
+        continue;
+      EXPECT_FALSE(status.HasExclusionReason(
+          static_cast<CanonicalCookie::CookieInclusionStatus::ExclusionReason>(
+              j)));
+    }
+  }
+}
+
+TEST(CookieInclusionStatusTest, NotValid) {
+  CanonicalCookie::CookieInclusionStatus status;
+  int num_exclusion_reasons = static_cast<int>(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS);
+  status.set_exclusion_reasons(1 << num_exclusion_reasons);
+  EXPECT_FALSE(status.IsInclude());
+  EXPECT_FALSE(status.IsValid());
+
+  status.set_exclusion_reasons(~0u);
+  EXPECT_FALSE(status.IsInclude());
+  EXPECT_FALSE(status.IsValid());
+}
+
+TEST(CookieInclusionStatusTest, AddExclusionReason) {
+  CanonicalCookie::CookieInclusionStatus status;
+  status.AddExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+  EXPECT_TRUE(status.IsValid());
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR}));
+}
+
+TEST(CookieInclusionStatusTest, RemoveExclusionReason) {
+  CanonicalCookie::CookieInclusionStatus status(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+  EXPECT_TRUE(status.IsValid());
+  ASSERT_TRUE(status.HasExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
+
+  status.RemoveExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+  EXPECT_TRUE(status.IsValid());
+  EXPECT_FALSE(status.HasExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
+
+  // Removing a nonexistent exclusion reason doesn't do anything.
+  ASSERT_FALSE(status.HasExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS));
+  status.RemoveExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS);
+  EXPECT_TRUE(status.IsValid());
+  EXPECT_FALSE(status.HasExclusionReason(
+      CanonicalCookie::CookieInclusionStatus::NUM_EXCLUSION_REASONS));
+}
+
+TEST(CookieInclusionStatusTest, AddExclusionReasonsAndWarningIfAny) {
+  CanonicalCookie::CookieInclusionStatus status1;
+  CanonicalCookie::CookieInclusionStatus status2;
+
+  status1.set_exclusion_reasons(0b00011111u);
+  status2.set_exclusion_reasons(0b11111000u);
+  status2.set_warning(
+      CanonicalCookie::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
+
+  status1.AddExclusionReasonsAndWarningIfAny(status2);
+
+  EXPECT_EQ(0b11111111u, status1.exclusion_reasons());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE,
+            status1.warning());
+}
+
 }  // namespace net
diff --git a/net/cookies/cookie_deletion_info.cc b/net/cookies/cookie_deletion_info.cc
index 3dd42902..c791ba5c 100644
--- a/net/cookies/cookie_deletion_info.cc
+++ b/net/cookies/cookie_deletion_info.cc
@@ -121,8 +121,7 @@
   }
 
   if (url.has_value() &&
-      cookie.IncludeForRequestURL(url.value(), cookie_options) !=
-          CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+      !cookie.IncludeForRequestURL(url.value(), cookie_options).IsInclude()) {
     return false;
   }
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index c742cfc..d522c4d 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -975,7 +975,7 @@
     CanonicalCookie::CookieInclusionStatus status =
         (*it)->IncludeForRequestURL(url, options);
 
-    if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+    if (!status.IsInclude()) {
       if (options.return_excluded_cookies())
         excluded_cookies->push_back({**it, status});
       continue;
@@ -988,13 +988,14 @@
   }
 }
 
-CanonicalCookie::CookieInclusionStatus CookieMonster::DeleteAnyEquivalentCookie(
+void CookieMonster::MaybeDeleteEquivalentCookieAndUpdateStatus(
     const std::string& key,
     const CanonicalCookie& ecc,
     bool source_secure,
     bool skip_httponly,
     bool already_expired,
-    base::Time* creation_date_to_inherit) {
+    base::Time* creation_date_to_inherit,
+    CanonicalCookie::CookieInclusionStatus* status) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   bool found_equivalent_cookie = false;
@@ -1037,6 +1038,9 @@
         if (!skip_httponly || !cc->IsHttpOnly()) {
           histogram_cookie_delete_equivalent_->Add(
               COOKIE_DELETE_EQUIVALENT_WOULD_HAVE_DELETED);
+        } else {
+          // Would also have skipped for being httponly, so make a note of that.
+          skipped_httponly = true;
         }
       }
     } else if (ecc.IsEquivalent(*cc)) {
@@ -1065,10 +1069,11 @@
   if (cookie_it_to_possibly_delete != cookies_.end()) {
     CanonicalCookie* cc_to_possibly_delete =
         cookie_it_to_possibly_delete->second.get();
-    // If a secure cookie was encountered (and left alone), don't actually
+    // 1) If a secure cookie was encountered (and left alone), don't actually
     // modify any of the pre-existing cookies. Only delete if no secure cookies
-    // were skipped.
-    if (!skipped_secure_cookie) {
+    // were skipped. 2) Only delete if the status of the current cookie-addition
+    // is "include", so that we don't throw out a valid cookie for a bad cookie.
+    if (!skipped_secure_cookie && status->IsInclude()) {
       histogram_cookie_delete_equivalent_->Add(COOKIE_DELETE_EQUIVALENT_FOUND);
       if (cc_to_possibly_delete->Value() == ecc.Value()) {
         *creation_date_to_inherit = cc_to_possibly_delete->CreationDate();
@@ -1078,7 +1083,7 @@
       InternalDeleteCookie(cookie_it_to_possibly_delete, true,
                            already_expired ? DELETE_COOKIE_EXPIRED_OVERWRITE
                                            : DELETE_COOKIE_OVERWRITE);
-    } else {
+    } else if (skipped_secure_cookie) {
       // If any secure cookie was skipped, preserve the pre-existing cookie.
       DCHECK(cc_skipped_secure);
       net_log_.AddEvent(
@@ -1090,13 +1095,15 @@
     }
   }
 
-  if (skipped_httponly)
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY;
+  if (skipped_httponly) {
+    status->AddExclusionReason(
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY);
+  }
 
-  if (skipped_secure_cookie)
-    return CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
-
-  return CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  if (skipped_secure_cookie) {
+    status->AddExclusionReason(
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE);
+  }
 }
 
 CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
@@ -1135,42 +1142,33 @@
                                        SetCookiesCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  CanonicalCookie::CookieInclusionStatus status;
+
   std::string scheme_lower = base::ToLowerASCII(source_scheme);
   bool secure_source = GURL::SchemeIsCryptographic(scheme_lower);
   if ((cc->IsSecure() && !secure_source)) {
-    MaybeRunCookieCallback(
-        std::move(callback),
+    status.AddExclusionReason(
         CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
-    return;
   }
 
-  CanonicalCookie::CookieInclusionStatus status =
-      cc->IsSetPermittedInContext(options);
-  if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-    // IsSetPermittedInContext already logs if it rejects a cookie, so
-    // CookieMonster doesn't need to.
-    MaybeRunCookieCallback(std::move(callback), status);
-    return;
-  }
+  status.AddExclusionReasonsAndWarningIfAny(
+      cc->IsSetPermittedInContext(options));
 
   if (!IsCookieableScheme(scheme_lower)) {
-    MaybeRunCookieCallback(
-        std::move(callback),
+    status.AddExclusionReason(
         CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME);
-    return;
   }
 
   // If both SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure
   // are enabled, non-SameSite cookies without the Secure attribute will be
-  // rejected.
+  // rejected. A warning for this would have been added by
+  // IsSetPermittedInContext().
   if (cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled() &&
       cc->IsEffectivelySameSiteNone() && !cc->IsSecure()) {
     DVLOG(net::cookie_util::kVlogSetCookies)
         << "SetCookie() rejecting insecure cookie with SameSite=None.";
-    status =
-        CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE;
-    MaybeRunCookieCallback(std::move(callback), status);
-    return;
+    status.AddExclusionReason(
+        CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
   }
 
   const std::string key(GetKey(cc->Domain()));
@@ -1184,67 +1182,67 @@
 
   base::Time creation_date_to_inherit;
 
-  status = DeleteAnyEquivalentCookie(
+  MaybeDeleteEquivalentCookieAndUpdateStatus(
       key, *cc, secure_source, options.exclude_httponly(), already_expired,
-      &creation_date_to_inherit);
+      &creation_date_to_inherit, &status);
 
-  if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-    std::string error;
-    error =
-        "SetCookie() not clobbering httponly cookie or secure cookie for "
-        "insecure scheme";
-
-    DVLOG(net::cookie_util::kVlogSetCookies) << error;
-    MaybeRunCookieCallback(std::move(callback), status);
-    return;
-  }
-
-  DVLOG(net::cookie_util::kVlogSetCookies)
-      << "SetCookie() key: " << key << " cc: " << cc->DebugString();
-
-  // Realize that we might be setting an expired cookie, and the only point
-  // was to delete the cookie which we've already done.
-  if (!already_expired) {
-    // See InitializeHistograms() for details.
-    if (cc->IsPersistent()) {
-      histogram_expiration_duration_minutes_->Add(
-          (cc->ExpiryDate() - creation_date).InMinutes());
-    }
-
-    // Histogram the type of scheme used on URLs that set cookies. This
-    // intentionally includes cookies that are set or overwritten by
-    // http:// URLs, but not cookies that are cleared by http:// URLs, to
-    // understand if the former behavior can be deprecated for Secure
-    // cookies.
-    CookieSource cookie_source_sample =
-        (secure_source
-             ? (cc->IsSecure()
-                    ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
-                    : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME)
-             : (cc->IsSecure()
-                    ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
-                    : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME));
-    histogram_cookie_source_scheme_->Add(cookie_source_sample);
-
-    if (!creation_date_to_inherit.is_null()) {
-      cc->SetCreationDate(creation_date_to_inherit);
-    }
-
-    InternalInsertCookie(key, std::move(cc), true);
-  } else {
+  if (status.HasExclusionReason(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE) ||
+      status.HasExclusionReason(CanonicalCookie::CookieInclusionStatus::
+                                    EXCLUDE_OVERWRITE_HTTP_ONLY)) {
     DVLOG(net::cookie_util::kVlogSetCookies)
-        << "SetCookie() not storing already expired cookie.";
+        << "SetCookie() not clobbering httponly cookie or secure cookie for "
+           "insecure scheme";
   }
 
-  // We assume that hopefully setting a cookie will be less common than
-  // querying a cookie.  Since setting a cookie can put us over our limits,
-  // make sure that we garbage collect...  We can also make the assumption that
-  // if a cookie was set, in the common case it will be used soon after,
-  // and we will purge the expired cookies in GetCookies().
-  GarbageCollect(creation_date, key);
+  if (status.IsInclude()) {
+    DVLOG(net::cookie_util::kVlogSetCookies)
+        << "SetCookie() key: " << key << " cc: " << cc->DebugString();
 
-  MaybeRunCookieCallback(std::move(callback),
-                         CanonicalCookie::CookieInclusionStatus::INCLUDE);
+    // Realize that we might be setting an expired cookie, and the only point
+    // was to delete the cookie which we've already done.
+    if (!already_expired) {
+      // See InitializeHistograms() for details.
+      if (cc->IsPersistent()) {
+        histogram_expiration_duration_minutes_->Add(
+            (cc->ExpiryDate() - creation_date).InMinutes());
+      }
+
+      // Histogram the type of scheme used on URLs that set cookies. This
+      // intentionally includes cookies that are set or overwritten by
+      // http:// URLs, but not cookies that are cleared by http:// URLs, to
+      // understand if the former behavior can be deprecated for Secure
+      // cookies.
+      CookieSource cookie_source_sample =
+          (secure_source
+               ? (cc->IsSecure()
+                      ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME
+                      : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME)
+               : (cc->IsSecure()
+                      ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
+                      : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME));
+      histogram_cookie_source_scheme_->Add(cookie_source_sample);
+
+      if (!creation_date_to_inherit.is_null()) {
+        cc->SetCreationDate(creation_date_to_inherit);
+      }
+
+      InternalInsertCookie(key, std::move(cc), true);
+    } else {
+      DVLOG(net::cookie_util::kVlogSetCookies)
+          << "SetCookie() not storing already expired cookie.";
+    }
+
+    // We assume that hopefully setting a cookie will be less common than
+    // querying a cookie.  Since setting a cookie can put us over our limits,
+    // make sure that we garbage collect...  We can also make the assumption
+    // that if a cookie was set, in the common case it will be used soon after,
+    // and we will purge the expired cookies in GetCookies().
+    GarbageCollect(creation_date, key);
+  }
+
+  // TODO(chlily): Log metrics.
+  MaybeRunCookieCallback(std::move(callback), status);
 }
 
 void CookieMonster::SetAllCookies(CookieList list,
@@ -1278,7 +1276,7 @@
   // https://codereview.chromium.org/2882063002/#msg64), which would
   // solve the return value problem.
   MaybeRunCookieCallback(std::move(callback),
-                         CanonicalCookie::CookieInclusionStatus::INCLUDE);
+                         CanonicalCookie::CookieInclusionStatus());
 }
 
 void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 24fdb41..a0bd017 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -440,14 +440,19 @@
   // If a cookie is deleted, and its value matches |ecc|'s value, then
   // |creation_date_to_inherit| will be set to that cookie's creation date.
   //
+  // The cookie will not be deleted if |*status| is not "include" when calling
+  // the function. The function will update |*status| with exclusion reasons if
+  // a secure cookie was skipped or an httponly cookie was skipped.
+  //
   // NOTE: There should never be more than a single matching equivalent cookie.
-  CanonicalCookie::CookieInclusionStatus DeleteAnyEquivalentCookie(
+  void MaybeDeleteEquivalentCookieAndUpdateStatus(
       const std::string& key,
       const CanonicalCookie& ecc,
       bool source_secure,
       bool skip_httponly,
       bool already_expired,
-      base::Time* creation_date_to_inherit);
+      base::Time* creation_date_to_inherit,
+      CanonicalCookie::CookieInclusionStatus* status);
 
   // Inserts |cc| into cookies_. Returns an iterator that points to the inserted
   // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid.
diff --git a/net/cookies/cookie_monster_change_dispatcher.cc b/net/cookies/cookie_monster_change_dispatcher.cc
index 7d09ea4..36f432f 100644
--- a/net/cookies/cookie_monster_change_dispatcher.cc
+++ b/net/cookies/cookie_monster_change_dispatcher.cc
@@ -60,9 +60,10 @@
     net::CookieChangeCause change_cause) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  if (!url_.is_empty() && cookie.IncludeForRequestURL(url_, options_) !=
-                              CanonicalCookie::CookieInclusionStatus::INCLUDE)
+  if (!url_.is_empty() &&
+      !cookie.IncludeForRequestURL(url_, options_).IsInclude()) {
     return;
+  }
 
   // TODO(mmenke, pwnall): Run callbacks synchronously?
   task_runner_->PostTask(
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index 463b9ccd..2829477 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -74,7 +74,7 @@
 
  private:
   void Run(CanonicalCookie::CookieInclusionStatus status) {
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+    EXPECT_TRUE(status.IsInclude());
     CookieTestCallback::Run();
   }
   CookieOptions options_;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 3a101a1..c3fe16e 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -141,7 +141,7 @@
     ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cm->SetAllCookiesAsync(list, callback.MakeCallback());
     callback.WaitUntilDone();
-    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   bool SetCookieWithCreationTime(CookieMonster* cm,
@@ -156,7 +156,7 @@
                                 base::nullopt /* server_time */),
         url.scheme(), CookieOptions(), callback.MakeCallback());
     callback.WaitUntilDone();
-    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   uint32_t DeleteAllCreatedInTimeRange(CookieMonster* cm,
@@ -963,7 +963,7 @@
 
   ExecuteLoads(CookieStoreCommand::LOAD_COOKIES_FOR_KEY);
   call1.WaitUntilDone();
-  EXPECT_EQ(call1.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(call1.result().IsInclude());
   EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ADD; ", TakeCommandSummary());
 
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call2;
@@ -972,7 +972,7 @@
                               base::nullopt /* server_time */),
       http_www_foo_.url().scheme(), CookieOptions(), call2.MakeCallback());
   ASSERT_TRUE(call2.was_run());
-  EXPECT_EQ(call2.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(call2.result().IsInclude());
   EXPECT_EQ("ADD; ", TakeCommandSummary());
 }
 
@@ -997,14 +997,14 @@
 
   ExecuteLoads(CookieStoreCommand::LOAD);
   call1.WaitUntilDone();
-  EXPECT_EQ(call1.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(call1.result().IsInclude());
   EXPECT_EQ("LOAD; ADD; ADD; ", TakeCommandSummary());
 
   // 2nd set doesn't need to read from store. It erases the old cookies, though.
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call2;
   cookie_monster_->SetAllCookiesAsync(list, call2.MakeCallback());
   ASSERT_TRUE(call2.was_run());
-  EXPECT_EQ(call2.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(call2.result().IsInclude());
   EXPECT_EQ("REMOVE; REMOVE; ADD; ADD; ", TakeCommandSummary());
 }
 
@@ -1241,8 +1241,7 @@
   EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ADD; ", TakeCommandSummary());
   EXPECT_TRUE(get_cookie_list_callback_was_run);
   ASSERT_TRUE(set_cookies_callback.was_run());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookies_callback.result());
+  EXPECT_TRUE(set_cookies_callback.result().IsInclude());
 
   ASSERT_TRUE(get_cookie_list_callback_deferred.was_run());
   EXPECT_THAT(get_cookie_list_callback_deferred.cookies(),
@@ -1455,40 +1454,45 @@
 
   base::Time now = base::Time::Now();
   base::Optional<base::Time> server_time = base::nullopt;
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "x=1"));
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::INCLUDE,
-      SetCanonicalCookieReturnStatus(
-          cm.get(), CanonicalCookie::Create(http_url, "y=1", now, server_time),
-          "http", false /*modify_httponly*/));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "x=1").IsInclude());
+  EXPECT_TRUE(SetCanonicalCookieReturnStatus(
+                  cm.get(),
+                  CanonicalCookie::Create(http_url, "y=1", now, server_time),
+                  "http", false /*modify_httponly*/)
+                  .IsInclude());
 
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
-      CreateAndSetCookieReturnStatus(cm.get(), foo_url, "x=1"));
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
-      SetCanonicalCookieReturnStatus(
-          cm.get(), CanonicalCookie::Create(foo_url, "y=1", now, server_time),
-          "foo", false /*modify_httponly*/));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), foo_url, "x=1")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_NONCOOKIEABLE_SCHEME}));
+  EXPECT_TRUE(SetCanonicalCookieReturnStatus(
+                  cm.get(),
+                  CanonicalCookie::Create(foo_url, "y=1", now, server_time),
+                  "foo", false /*modify_httponly*/)
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_NONCOOKIEABLE_SCHEME}));
 
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm_foo.get(), foo_url, "x=1"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            SetCanonicalCookieReturnStatus(
-                cm_foo.get(),
-                CanonicalCookie::Create(foo_url, "y=1", now, server_time),
-                "foo", false /*modify_httponly*/));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm_foo.get(), foo_url, "x=1").IsInclude());
+  EXPECT_TRUE(SetCanonicalCookieReturnStatus(
+                  cm_foo.get(),
+                  CanonicalCookie::Create(foo_url, "y=1", now, server_time),
+                  "foo", false /*modify_httponly*/)
+                  .IsInclude());
 
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
-      CreateAndSetCookieReturnStatus(cm_foo.get(), http_url, "x=1"));
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
-      SetCanonicalCookieReturnStatus(
-          cm_foo.get(),
-          CanonicalCookie::Create(http_url, "y=1", now, server_time), "http",
-          false /*modify_httponly*/));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm_foo.get(), http_url, "x=1")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_NONCOOKIEABLE_SCHEME}));
+  EXPECT_TRUE(SetCanonicalCookieReturnStatus(
+                  cm_foo.get(),
+                  CanonicalCookie::Create(http_url, "y=1", now, server_time),
+                  "http", false /*modify_httponly*/)
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_NONCOOKIEABLE_SCHEME}));
 }
 
 TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
@@ -1600,8 +1604,8 @@
   ASSERT_TRUE(iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.Format(".%D"), iter->cookie.Domain());
   EXPECT_EQ("E", iter->cookie.Name());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            iter->status);
+  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   ASSERT_TRUE(++iter == excluded_cookies.end());
 
@@ -1617,14 +1621,14 @@
   ASSERT_TRUE(iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.host(), iter->cookie.Domain());
   EXPECT_EQ("A", iter->cookie.Name());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-            iter->status);
+  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 
   ASSERT_TRUE(++iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.Format(".%D"), iter->cookie.Domain());
   EXPECT_EQ("E", iter->cookie.Name());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            iter->status);
+  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   ASSERT_TRUE(++iter == excluded_cookies.end());
 
@@ -1691,8 +1695,8 @@
   ASSERT_TRUE(it != excluded_cookies.end());
   EXPECT_EQ("C", it->cookie.Name());
   EXPECT_EQ("/bar", it->cookie.Path());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-            it->status);
+  EXPECT_TRUE(it->status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
 
   ASSERT_TRUE(++it == excluded_cookies.end());
 
@@ -1702,8 +1706,8 @@
   ASSERT_TRUE(it != excluded_cookies.end());
   EXPECT_EQ("A", it->cookie.Name());
   EXPECT_EQ("/foo", it->cookie.Path());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-            it->status);
+  EXPECT_TRUE(it->status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
 
   ASSERT_TRUE(++it == excluded_cookies.end());
 }
@@ -2219,8 +2223,7 @@
   // The tasks should run in order, and the get should see the cookies.
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookie_callback.result());
+  EXPECT_TRUE(set_cookie_callback.result().IsInclude());
 
   get_cookies_callback1.WaitUntilDone();
   EXPECT_EQ(1u, get_cookies_callback1.cookies().size());
@@ -2307,8 +2310,7 @@
   EXPECT_EQ(0u, get_cookies_callback1.cookies().size());
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookie_callback.result());
+  EXPECT_TRUE(set_cookie_callback.result().IsInclude());
 
   get_cookies_callback2.WaitUntilDone();
   EXPECT_EQ(1u, get_cookies_callback2.cookies().size());
@@ -2362,8 +2364,7 @@
   EXPECT_EQ(0u, get_cookies_callback1.cookies().size());
 
   set_cookie_callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookie_callback.result());
+  EXPECT_TRUE(set_cookie_callback.result().IsInclude());
 
   // A subsequent get cookies call should see the new cookie.
   GetAllCookiesCallback get_cookies_callback2;
@@ -2834,6 +2835,60 @@
       CookieMonster::COOKIE_DELETE_EQUIVALENT_FOUND_WITH_SAME_VALUE, 1);
 }
 
+// Test skipping a cookie in DeleteAnyEquivalentCookie for multiple reasons
+// (Secure and HttpOnly).
+TEST_F(CookieMonsterTest, SkipDontOverwriteForMultipleReasons) {
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_));
+
+  // Set a secure, httponly cookie from a secure origin
+  auto preexisting_cookie = CanonicalCookie::Create(
+      https_www_foo_.url(), "A=B;Secure;HttpOnly", base::Time::Now(),
+      base::nullopt /* server_time */);
+  CanonicalCookie::CookieInclusionStatus status =
+      SetCanonicalCookieReturnStatus(cm.get(), std::move(preexisting_cookie),
+                                     "https", true /* can_modify_httponly */);
+  ASSERT_TRUE(status.IsInclude());
+
+  // Attempt to set a new cookie with the same name that is not Secure or
+  // Httponly from an insecure scheme.
+  auto cookie =
+      CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
+                              base::nullopt /* server_time */);
+  status = SetCanonicalCookieReturnStatus(cm.get(), std::move(cookie), "http",
+                                          false /* can_modify_httponly */);
+  EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
+       CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY}));
+}
+
+// Test that when we check for equivalent cookies, we don't remove any if the
+// cookie should not be set.
+TEST_F(CookieMonsterTest, DontDeleteEquivalentCookieIfSetIsRejected) {
+  scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+  std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_));
+
+  auto preexisting_cookie = CanonicalCookie::Create(
+      http_www_foo_.url(), "cookie=foo", base::Time::Now(),
+      base::nullopt /* server_time */);
+  CanonicalCookie::CookieInclusionStatus status =
+      SetCanonicalCookieReturnStatus(cm.get(), std::move(preexisting_cookie),
+                                     "https", false /* can_modify_httponly */);
+  ASSERT_TRUE(status.IsInclude());
+
+  auto bad_cookie = CanonicalCookie::Create(
+      http_www_foo_.url(), "cookie=bar;secure", base::Time::Now(),
+      base::nullopt /* server_time */);
+  CanonicalCookie::CookieInclusionStatus status2 =
+      SetCanonicalCookieReturnStatus(cm.get(), std::move(bad_cookie), "http",
+                                     false /* can_modify_httponly */);
+  EXPECT_TRUE(status2.HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
+
+  // Check that the original cookie is still there.
+  EXPECT_EQ("cookie=foo", GetCookies(cm.get(), https_www_foo_.url()));
+}
+
 TEST_F(CookieMonsterTest, SetSecureCookies) {
   std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_));
   GURL http_url("http://www.foo.com");
@@ -2844,32 +2899,36 @@
 
   // A non-secure cookie can be created from either a URL with a secure or
   // insecure scheme.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C;"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B;"));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C;").IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B;").IsInclude());
 
   // A secure cookie cannot be created from a URL with an insecure scheme.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=B; Secure"));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=B; Secure")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   // A secure cookie can be created from a URL with a secure scheme.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and a
   // secure cookie with the same name already exists, do not update the cookie.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C;"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C;")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
 
   // If a non-secure cookie is created from a URL with an secure scheme, and a
   // secure cookie with the same name already exists, update the cookie.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=C;"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=C;").IsInclude());
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and
   // a secure cookie with the same name already exists, do not update the cookie
@@ -2877,44 +2936,52 @@
   //
   // With an existing cookie whose path is '/', a cookie with the same name
   // cannot be set on the same domain, regardless of path:
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C; path=/"));
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C; path=/my/path"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C; path=/")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C; path=/my/path")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
 
   // But if the existing cookie has a path somewhere under the root, cookies
   // with the same name may be set for paths which don't overlap the existing
   // cookie.
   EXPECT_TRUE(
       SetCookie(cm.get(), https_url, "WITH_PATH=B; Secure; path=/my/path"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "WITH_PATH=C; path=/"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "WITH_PATH=C; path=/your/path"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "WITH_PATH=C; path=/my/path"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "WITH_PATH=C; path=/my/path/sub"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C")
+                  .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "WITH_PATH=C; path=/")
+          .IsInclude());
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url,
+                                             "WITH_PATH=C; path=/your/path")
+                  .IsInclude());
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url,
+                                             "WITH_PATH=C; path=/my/path")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url,
+                                             "WITH_PATH=C; path=/my/path/sub")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
 
   DeleteAll(cm.get());
 
   // If a secure cookie is set on top of an existing insecure cookie but with a
   // different path, both are retained.
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::INCLUDE,
-      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=B; path=/foo"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url,
-                                           "A=C; Secure; path=/"));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=B; path=/foo")
+          .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=C; Secure; path=/")
+          .IsInclude());
 
   // Querying from an insecure url gets only the insecure cookie, but querying
   // from a secure url returns both.
@@ -2925,11 +2992,15 @@
   // Attempting to set an insecure cookie (from an insecure scheme) that domain-
   // matches and path-matches the secure cookie fails i.e. the secure cookie is
   // left alone...
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=D; path=/foo"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=D; path=/"));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=D; path=/foo")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=D; path=/")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
   EXPECT_THAT(GetCookies(cm.get(), https_foo_url), testing::HasSubstr("A=C"));
 
   // ...but the original insecure cookie is still retained.
@@ -2938,37 +3009,47 @@
               testing::Not(testing::HasSubstr("A=D")));
 
   // Deleting the secure cookie leaves only the original insecure cookie.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(
-                cm.get(), https_url,
-                "A=C; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(
+                  cm.get(), https_url,
+                  "A=C; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT")
+                  .IsInclude());
   EXPECT_EQ("A=B", GetCookies(cm.get(), https_foo_url));
 
   // If a non-secure cookie is created from a URL with an insecure scheme, and
   // a secure cookie with the same name already exists, if the domain strings
   // domain-match, do not update the cookie.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "A=C; domain=foo.com"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "A=C; domain=www.foo.com"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "A=C; domain=foo.com")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url,
+                                             "A=C; domain=www.foo.com")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
 
   // Since A=B was set above with no domain string, set a different cookie here
   // so the insecure examples aren't trying to overwrite the one above.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url,
-                                           "B=C; Secure; domain=foo.com"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url,
-                                           "B=D; domain=foo.com"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-            CreateAndSetCookieReturnStatus(cm.get(), http_url, "B=D"));
-  EXPECT_EQ(
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-      CreateAndSetCookieReturnStatus(cm.get(), http_superdomain_url, "B=D"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url,
+                                             "B=C; Secure; domain=foo.com")
+                  .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_url, "B=D; domain=foo.com")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), http_url, "B=D")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_SECURE}));
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), http_superdomain_url, "B=D")
+          .HasExactlyExclusionReasonsForTesting(
+              {CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
 
   // Verify that if an httponly version of the cookie exists, adding a Secure
   // version of the cookie still does not overwrite it.
@@ -2978,8 +3059,10 @@
                                  include_httponly));
   // Note that the lack of an explicit options object below uses the default,
   // which in this case includes "exclude_httponly = true".
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "C=E; Secure"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "C=E; Secure")
+                  .HasExactlyExclusionReasonsForTesting(
+                      {CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_OVERWRITE_HTTP_ONLY}));
 
   auto entries = net_log_.GetEntries();
   ExpectLogContainsSomewhere(
@@ -3119,20 +3202,20 @@
 
   // Tests that non-equivalent cookies because of the path attribute can be set
   // successfully.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url,
-                                           "A=C; path=/some/other/path"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url,
+                                             "A=C; path=/some/other/path")
+                  .IsInclude());
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; path=/some/other/path"));
 
   // Tests that non-equivalent cookies because of the domain attribute can be
   // set successfully.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            CreateAndSetCookieReturnStatus(cm.get(), https_url,
-                                           "A=C; domain=foo.com"));
+  EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=B; Secure")
+                  .IsInclude());
+  EXPECT_TRUE(
+      CreateAndSetCookieReturnStatus(cm.get(), https_url, "A=C; domain=foo.com")
+          .IsInclude());
   EXPECT_FALSE(SetCookie(cm.get(), http_url, "A=D; domain=foo.com"));
 }
 
@@ -3265,15 +3348,15 @@
       CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
                               base::nullopt /* server_time */, &status);
   ASSERT_TRUE(cookie != nullptr);
-  ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+  ASSERT_TRUE(status.IsInclude());
 
   // ... but the environment is checked on set, so this may be rejected then.
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
   cm.SetCanonicalCookieAsync(std::move(cookie), "http", env_cross_site,
                              callback.MakeCallback());
   callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
-            callback.result());
+  EXPECT_TRUE(callback.result().HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX}));
 }
 
 TEST_F(CookieMonsterTest, RejectCreatedSecureCookieOnSet) {
@@ -3289,15 +3372,15 @@
                               base::nullopt /* server_time */, &status);
 
   ASSERT_TRUE(cookie != nullptr);
-  ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+  ASSERT_TRUE(status.IsInclude());
 
   // Cookie is rejected when attempting to set from a non-secure scheme.
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
   cm.SetCanonicalCookieAsync(std::move(cookie), "http", CookieOptions(),
                              callback.MakeCallback());
   callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            callback.result());
+  EXPECT_TRUE(callback.result().HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 }
 
 TEST_F(CookieMonsterTest, RejectCreatedHttpOnlyCookieOnSet) {
@@ -3312,7 +3395,7 @@
                               base::nullopt /* server_time */, &status);
 
   ASSERT_TRUE(cookie != nullptr);
-  ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
+  ASSERT_TRUE(status.IsInclude());
 
   // Cookie is rejected when attempting to set with a CookieOptions that does
   // not allow httponly.
@@ -3322,8 +3405,8 @@
   cm.SetCanonicalCookieAsync(std::move(cookie), "http", options_no_httponly,
                              callback.MakeCallback());
   callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-            callback.result());
+  EXPECT_TRUE(callback.result().HasExactlyExclusionReasonsForTesting(
+      {CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 }
 
 // Test the CookiesWithoutSameSiteMustBeSecure experimental option (in
@@ -3344,71 +3427,76 @@
       // Feature enabled:
       // Cookie set from a secure URL with SameSite enabled is not rejected.
       {true, true, "A=B; SameSite=Lax",
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE},
       // Cookie set from a secure URL which is defaulted into Lax is not
       // rejected.
       {true, true, "A=B",  // recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE, kShortAge},
       {true, true, "A=B",  // not-recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE,
+       kLongAge},
       // Cookie set from a secure URL with SameSite=None and Secure is set.
       {true, true, "A=B; SameSite=None; Secure",
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::NO_RESTRICTION},
       // Cookie set from a secure URL with SameSite=None but not specifying
       // Secure is rejected.
       {true, true, "A=B; SameSite=None",
-       CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE},
+       CanonicalCookie::CookieInclusionStatus(
+           CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_NONE_INSECURE,
+           CanonicalCookie::CookieInclusionStatus::
+               WARN_SAMESITE_NONE_INSECURE)},
       // Cookie set from an insecure URL which defaults into LAX_MODE is not
       // rejected.
       {true, false, "A=B",  // recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE, kShortAge},
       {true, false, "A=B",  // not-recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE,
+       kLongAge},
       {true, false, "A=B; Max-Age=1000000",  // recently-set persistent cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE, kShortAge},
       {true, false,
        "A=B; Max-Age=1000000",  // not-recently-set persistent cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE,
+       kLongAge},
 
       // Feature not enabled (but SameSiteByDefaultCookies is still enabled):
       // Cookie set from a secure URL with SameSite enabled is not rejected.
       {false, true, "A=B; SameSite=Lax",
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE},
       // Cookie set from a secure URL which is defaulted into Lax is not
       // rejected.
       {false, true, "A=B",  // recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE, kShortAge},
       {false, true, "A=B",  // not-recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE,
+       kLongAge},
       // Cookie set from a secure URL with SameSite=None and Secure is set.
       {false, true, "A=B; SameSite=None; Secure",
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::NO_RESTRICTION},
       // Cookie set from an insecure URL with SameSite=None (which can't ever be
       // secure because it's an insecure URL) is NOT rejected, because
       // CookiesWithoutSameSiteMustBeSecure is not enabled.
       {false, false, "A=B; SameSite=None",
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+           std::vector<
+               CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
+           CanonicalCookie::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE),
        CookieSameSite::NO_RESTRICTION},
       // Cookie set from an insecure URL which is defaulted into Lax is not
       // rejected.
       {false, false, "A=B",  // recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
+       CanonicalCookie::CookieInclusionStatus(),
        CookieSameSite::LAX_MODE_ALLOW_UNSAFE, kShortAge},
       {false, false, "A=B",  // not-recently-set session cookie.
-       CanonicalCookie::CookieInclusionStatus::INCLUDE,
-       CookieSameSite::LAX_MODE, kLongAge},
+       CanonicalCookie::CookieInclusionStatus(), CookieSameSite::LAX_MODE,
+       kLongAge},
   };
 
   auto cm = std::make_unique<CookieMonster>(nullptr, nullptr);
@@ -3447,7 +3535,7 @@
             true /* can_modify_httponly (irrelevant) */);
     EXPECT_EQ(test.expected_set_cookie_result, result)
         << "Test case " << i << " failed.";
-    if (result == CanonicalCookie::CookieInclusionStatus::INCLUDE) {
+    if (result.IsInclude()) {
       auto cookies = GetAllCookiesForURL(cm.get(), url);
       ASSERT_EQ(1u, cookies.size());
       EXPECT_EQ(test.expected_effective_samesite,
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index 79f61fcf..8fe683929 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -193,7 +193,7 @@
     cs->SetCanonicalCookieAsync(std::move(cookie), url.scheme(), options,
                                 callback.MakeCallback());
     callback.WaitUntilDone();
-    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   bool SetCanonicalCookie(CookieStore* cs,
@@ -210,7 +210,7 @@
     cs->SetCanonicalCookieAsync(std::move(cookie), std::move(source_scheme),
                                 options, callback.MakeCallback());
     callback.WaitUntilDone();
-    return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   bool SetCookieWithServerTime(CookieStore* cs,
@@ -544,14 +544,16 @@
       "http", true));
 
   // A secure source is required for setting secure cookies.
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            this->SetCanonicalCookieReturnStatus(
-                cs,
-                std::make_unique<CanonicalCookie>(
-                    "E", "F", http_foo_host, "/", base::Time(), base::Time(),
-                    base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
-                    COOKIE_PRIORITY_DEFAULT),
-                "http", true));
+  EXPECT_TRUE(
+      this->SetCanonicalCookieReturnStatus(
+              cs,
+              std::make_unique<CanonicalCookie>(
+                  "E", "F", http_foo_host, "/", base::Time(), base::Time(),
+                  base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
+                  COOKIE_PRIORITY_DEFAULT),
+              "http", true)
+          .HasExclusionReason(
+              CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
 
   // A Secure cookie can be created from an insecure URL, but is rejected upon
   // setting.
@@ -560,10 +562,11 @@
       this->http_www_foo_.url(), "foo=1; Secure", base::Time::Now(),
       base::nullopt /* server_time */, &status);
   EXPECT_TRUE(cookie->IsSecure());
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            this->SetCanonicalCookieReturnStatus(cs, std::move(cookie), "http",
-                                                 true));
+  EXPECT_TRUE(status.IsInclude());
+  EXPECT_TRUE(
+      this->SetCanonicalCookieReturnStatus(cs, std::move(cookie), "http", true)
+          .HasExclusionReason(
+              CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
 
   // A secure source is also required for overwriting secure cookies.  Writing
   // a secure cookie then overwriting it from a non-secure source should fail.
@@ -575,27 +578,31 @@
           CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
       "https", true /* modify_http_only */));
 
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-            this->SetCanonicalCookieReturnStatus(
-                cs,
-                std::make_unique<CanonicalCookie>(
-                    "E", "F", http_foo_host, "/", base::Time(), base::Time(),
-                    base::Time(), true /* secure */, false /* httponly */,
-                    CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
-                "http", true /* modify_http_only */));
+  EXPECT_TRUE(
+      this->SetCanonicalCookieReturnStatus(
+              cs,
+              std::make_unique<CanonicalCookie>(
+                  "E", "F", http_foo_host, "/", base::Time(), base::Time(),
+                  base::Time(), true /* secure */, false /* httponly */,
+                  CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
+              "http", true /* modify_http_only */)
+          .HasExclusionReason(
+              CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
 
   if (TypeParam::supports_http_only) {
     // Permission to modify http only cookies is required to set an
     // httponly cookie.
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+    EXPECT_TRUE(
         this->SetCanonicalCookieReturnStatus(
-            cs,
-            std::make_unique<CanonicalCookie>(
-                "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
-                base::Time(), false /* secure */, true /* httponly */,
-                CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
-            "http", false /* modify_http_only */));
+                cs,
+                std::make_unique<CanonicalCookie>(
+                    "G", "H", http_foo_host, "/unique", base::Time(),
+                    base::Time(), base::Time(), false /* secure */,
+                    true /* httponly */, CookieSameSite::NO_RESTRICTION,
+                    COOKIE_PRIORITY_DEFAULT),
+                "http", false /* modify_http_only */)
+            .HasExclusionReason(
+                CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
 
     // A HttpOnly cookie can be created, but is rejected
     // upon setting if the options do not specify include_httponly.
@@ -604,10 +611,12 @@
                                      "bar=1; HttpOnly", base::Time::Now(),
                                      base::nullopt /* server_time */, &status);
     EXPECT_TRUE(c->IsHttpOnly());
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-              this->SetCanonicalCookieReturnStatus(
-                  cs, std::move(c), "http", false /* can_modify_httponly */));
+    EXPECT_TRUE(status.IsInclude());
+    EXPECT_TRUE(
+        this->SetCanonicalCookieReturnStatus(cs, std::move(c), "http",
+                                             false /* can_modify_httponly */)
+            .HasExclusionReason(
+                CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
 
     // Permission to modify httponly cookies is also required to overwrite
     // an httponly cookie.
@@ -619,15 +628,17 @@
             CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
         "http", true /* modify_http_only */));
 
-    EXPECT_EQ(
-        CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
+    EXPECT_TRUE(
         this->SetCanonicalCookieReturnStatus(
-            cs,
-            std::make_unique<CanonicalCookie>(
-                "G", "H", http_foo_host, "/unique", base::Time(), base::Time(),
-                base::Time(), false /* secure */, true /* httponly */,
-                CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
-            "http", false /* modify_http_only */));
+                cs,
+                std::make_unique<CanonicalCookie>(
+                    "G", "H", http_foo_host, "/unique", base::Time(),
+                    base::Time(), base::Time(), false /* secure */,
+                    true /* httponly */, CookieSameSite::NO_RESTRICTION,
+                    COOKIE_PRIORITY_DEFAULT),
+                "http", false /* modify_http_only */)
+            .HasExclusionReason(
+                CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY));
   } else {
     // Leave store in same state as if the above tests had been run.
     EXPECT_TRUE(this->SetCanonicalCookie(
diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc
index d423de2..19dafb80 100644
--- a/net/cookies/cookie_util.cc
+++ b/net/cookies/cookie_util.cc
@@ -482,28 +482,6 @@
     return CookieOptions::SameSiteCookieContext::CROSS_SITE;
 }
 
-CanonicalCookie::CookieInclusionStatus CookieWouldBeExcludedDueToSameSite(
-    const CanonicalCookie& cookie,
-    const CookieOptions& options) {
-  // Check if cookie would be excluded under SameSiteByDefaultCookies.
-  bool cross_site_context = options.same_site_cookie_context() ==
-                            CookieOptions::SameSiteCookieContext::CROSS_SITE;
-  if (cross_site_context && cookie.SameSite() == CookieSameSite::UNSPECIFIED) {
-    DCHECK(cookie.IsEffectivelySameSiteNone());
-    return CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX;
-  }
-
-  // Check if cookie would be excluded under CookiesWithoutSameSiteMustBeSecure.
-  if (cookie.SameSite() == CookieSameSite::NO_RESTRICTION &&
-      !cookie.IsSecure()) {
-    return CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE;
-  }
-
-  return CanonicalCookie::CookieInclusionStatus::INCLUDE;
-}
-
 bool IsSameSiteByDefaultCookiesEnabled() {
   return base::FeatureList::IsEnabled(features::kSameSiteByDefaultCookies);
 }
@@ -519,8 +497,7 @@
   return base::BindOnce(
       [](base::OnceCallback<void(bool)> inner_callback,
          const net::CanonicalCookie::CookieInclusionStatus status) {
-        bool success =
-            (status == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+        bool success = status.IsInclude();
         std::move(inner_callback).Run(success);
       },
       std::move(callback));
diff --git a/net/cookies/cookie_util.h b/net/cookies/cookie_util.h
index 0582da4..57cc28f 100644
--- a/net/cookies/cookie_util.h
+++ b/net/cookies/cookie_util.h
@@ -144,25 +144,13 @@
 ComputeSameSiteContextForSubresource(const GURL& url,
                                      const GURL& site_for_cookies);
 
-// Checks whether a cookie would be excluded due to SameSite restrictions,
-// assuming SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure
-// were turned on. This should be called on a cookie that is in fact included,
-// (presumably because SameSiteByDefaultCookies and
-// CookiesWithoutSameSiteMustBeSecure are not actually enabled). If the
-// return value is not INCLUDE, the cookie should be added to the excluded
-// cookies list so that an appropriate warning message can be shown in the
-// console.
-NET_EXPORT CanonicalCookie::CookieInclusionStatus
-CookieWouldBeExcludedDueToSameSite(const CanonicalCookie& cookie,
-                                   const CookieOptions& options);
-
 // Returns whether the respective SameSite feature is enabled.
 NET_EXPORT bool IsSameSiteByDefaultCookiesEnabled();
 NET_EXPORT bool IsCookiesWithoutSameSiteMustBeSecureEnabled();
 
 // Takes a callback accepting a CookieInclusionStatus and returns a callback
 // that accepts a bool, setting the bool to true if the CookieInclusionStatus
-// was set to INCLUDE, else sending false.
+// was set to "include", else sending false.
 //
 // Can be used with SetCanonicalCookie when you don't need to know why a cookie
 // was blocked, only whether it was blocked.
diff --git a/net/cookies/cookie_util_unittest.cc b/net/cookies/cookie_util_unittest.cc
index 5ac2aa3..10dd9c5 100644
--- a/net/cookies/cookie_util_unittest.cc
+++ b/net/cookies/cookie_util_unittest.cc
@@ -416,7 +416,8 @@
           cookie_util::AdaptCookieInclusionStatusToBool(std::move(callback));
 
   std::move(adapted_callback)
-      .Run(CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+      .Run(CanonicalCookie::CookieInclusionStatus(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
 
   EXPECT_FALSE(result_out);
 
@@ -427,8 +428,7 @@
   adapted_callback =
       cookie_util::AdaptCookieInclusionStatusToBool(std::move(callback));
 
-  std::move(adapted_callback)
-      .Run(CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  std::move(adapted_callback).Run(CanonicalCookie::CookieInclusionStatus());
 
   EXPECT_TRUE(result_out);
 }
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index e1ef1f54..93bd17c 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -1757,7 +1757,7 @@
       : result_(false), loop_to_quit_(std::make_unique<base::RunLoop>()) {}
 
   void SetCookieCallback(CanonicalCookie::CookieInclusionStatus result) {
-    result_ = (result == CanonicalCookie::CookieInclusionStatus::INCLUDE);
+    result_ = result.IsInclude();
     loop_to_quit_->Quit();
   }
 
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 251efce..12039b1 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -1243,8 +1243,7 @@
                          CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
   set_cookie_callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookie_callback.result());
+  EXPECT_TRUE(set_cookie_callback.result().IsInclude());
 
   // Also insert a whole bunch of cookies to slow down the background loading of
   // all the cookies.
@@ -1261,8 +1260,7 @@
                            CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&set_cookie_callback2)));
     set_cookie_callback2.WaitUntilDone();
-    EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              set_cookie_callback2.result());
+    EXPECT_TRUE(set_cookie_callback2.result().IsInclude());
   }
 
   net::TestClosure flush_closure;
@@ -1317,8 +1315,7 @@
                          CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
   set_cookie_callback.WaitUntilDone();
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            set_cookie_callback.result());
+  EXPECT_TRUE(set_cookie_callback.result().IsInclude());
 
   // Things should commit once going out of scope.
 }
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 2b7cdb00..a00e8075 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -525,8 +525,8 @@
         /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
         quic::QuicTime::Delta::FromMilliseconds(
             kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
-        /*migrate_idle_session=*/false, kDefaultIdleSessionMigrationPeriod,
-        kMaxTimeOnNonDefaultNetwork,
+        /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
+        kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
         kMaxMigrationsToNonDefaultNetworkOnWriteError,
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         kQuicYieldAfterPacketsRead,
diff --git a/net/quic/platform/impl/quic_default_proof_providers_impl.cc b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
index bf932ac..23d6833 100644
--- a/net/quic/platform/impl/quic_default_proof_providers_impl.cc
+++ b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
@@ -19,6 +19,12 @@
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
 
+DEFINE_QUIC_COMMAND_LINE_FLAG(
+    bool,
+    allow_unknown_root_cert,
+    false,
+    "If true, don't restrict cert verification to known roots");
+
 DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
                               certificate_file,
                               "",
@@ -36,15 +42,27 @@
 
 namespace quic {
 
+namespace {
+
+std::set<std::string> UnknownRootAllowlistForHost(std::string host) {
+  if (!GetQuicFlag(FLAGS_allow_unknown_root_cert)) {
+    return std::set<std::string>();
+  }
+  return {host};
+}
+
+}  // namespace
+
 class ProofVerifierChromiumWithOwnership : public net::ProofVerifierChromium {
  public:
   ProofVerifierChromiumWithOwnership(
-      std::unique_ptr<net::CertVerifier> cert_verifier)
+      std::unique_ptr<net::CertVerifier> cert_verifier,
+      std::string host)
       : net::ProofVerifierChromium(cert_verifier.get(),
                                    &ct_policy_enforcer_,
                                    &transport_security_state_,
                                    &ct_verifier_,
-                                   std::set<std::string>()),
+                                   UnknownRootAllowlistForHost(host)),
         cert_verifier_(std::move(cert_verifier)) {}
 
  private:
@@ -55,11 +73,11 @@
 };
 
 std::unique_ptr<ProofVerifier> CreateDefaultProofVerifierImpl(
-    const std::string& /*host*/) {
+    const std::string& host) {
   std::unique_ptr<net::CertVerifier> cert_verifier =
       net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr);
   return QuicMakeUnique<ProofVerifierChromiumWithOwnership>(
-      std::move(cert_verifier));
+      std::move(cert_verifier), host);
 }
 
 std::unique_ptr<ProofSource> CreateDefaultProofSourceImpl() {
diff --git a/net/quic/platform/impl/quic_default_proof_providers_impl.h b/net/quic/platform/impl/quic_default_proof_providers_impl.h
index 8ae9623..f490e53 100644
--- a/net/quic/platform/impl/quic_default_proof_providers_impl.h
+++ b/net/quic/platform/impl/quic_default_proof_providers_impl.h
@@ -15,5 +15,7 @@
 std::unique_ptr<ProofVerifier> CreateDefaultProofVerifierImpl(
     const std::string& host);
 std::unique_ptr<ProofSource> CreateDefaultProofSourceImpl();
+
 }  // namespace quic
+
 #endif  // NET_QUIC_PLATFORM_IMPL_QUIC_DEFAULT_PROOF_PROVIDERS_IMPL_H_
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 433a626..e92e00c 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -700,6 +700,7 @@
     NetworkChangeNotifier::NetworkHandle default_network,
     quic::QuicTime::Delta retransmittable_on_wire_timeout,
     bool migrate_idle_session,
+    bool allow_port_migration,
     base::TimeDelta idle_migration_period,
     base::TimeDelta max_time_on_non_default_network,
     int max_migrations_to_non_default_network_on_write_error,
@@ -730,6 +731,7 @@
       migrate_session_on_network_change_v2_(
           migrate_sessions_on_network_change_v2),
       migrate_idle_session_(migrate_idle_session),
+      allow_port_migration_(allow_port_migration),
       idle_migration_period_(idle_migration_period),
       max_time_on_non_default_network_(max_time_on_non_default_network),
       max_migrations_to_non_default_network_on_write_error_(
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index 59ab035..4206c13 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -384,6 +384,7 @@
       NetworkChangeNotifier::NetworkHandle default_network,
       quic::QuicTime::Delta retransmittable_on_wire_timeout,
       bool migrate_idle_session,
+      bool allow_port_migration,
       base::TimeDelta idle_migration_period,
       base::TimeDelta max_time_on_non_default_network,
       int max_migrations_to_non_default_network_on_write_error,
@@ -762,6 +763,7 @@
   bool migrate_session_early_v2_;
   bool migrate_session_on_network_change_v2_;
   bool migrate_idle_session_;
+  bool allow_port_migration_;
   // Session can be migrated if its idle time is within this period.
   base::TimeDelta idle_migration_period_;
   base::TimeDelta max_time_on_non_default_network_;
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 2bb4990..ccbe8a5 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -156,8 +156,8 @@
         /*defaulet_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
         quic::QuicTime::Delta::FromMilliseconds(
             kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
-        /*migrate_idle_session=*/false, kDefaultIdleSessionMigrationPeriod,
-        kMaxTimeOnNonDefaultNetwork,
+        /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
+        kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
         kMaxMigrationsToNonDefaultNetworkOnWriteError,
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         kQuicYieldAfterPacketsRead,
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 88cd76e..53ba0e6 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -334,8 +334,8 @@
         /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
         quic::QuicTime::Delta::FromMilliseconds(
             kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
-        /*migrate_idle_session=*/false, kDefaultIdleSessionMigrationPeriod,
-        kMaxTimeOnNonDefaultNetwork,
+        /*migrate_idle_session=*/false, /*allow_port_migration=*/false,
+        kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
         kMaxMigrationsToNonDefaultNetworkOnWriteError,
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         kQuicYieldAfterPacketsRead,
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index 6d3dbb85..94f5439 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -227,8 +227,8 @@
         /*default_network=*/NetworkChangeNotifier::kInvalidNetworkHandle,
         quic::QuicTime::Delta::FromMilliseconds(
             kDefaultRetransmittableOnWireTimeout.InMilliseconds()),
-        /*migrate_idle_session=*/true, kDefaultIdleSessionMigrationPeriod,
-        kMaxTimeOnNonDefaultNetwork,
+        /*migrate_idle_session=*/true, /*allow_port_migration=*/false,
+        kDefaultIdleSessionMigrationPeriod, kMaxTimeOnNonDefaultNetwork,
         kMaxMigrationsToNonDefaultNetworkOnWriteError,
         kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
         kQuicYieldAfterPacketsRead,
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 16efbc0..0d7f615 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -1146,8 +1146,10 @@
   bool retry_on_alternate_network_before_handshake =
       params_.retry_on_alternate_network_before_handshake;
   bool migrate_idle_sessions = params_.migrate_idle_sessions;
+  bool allow_port_migration = params_.allow_port_migration;
   params_.migrate_sessions_on_network_change_v2 = false;
   params_.migrate_sessions_early_v2 = false;
+  params_.allow_port_migration = false;
   params_.retry_on_alternate_network_before_handshake = false;
   params_.migrate_idle_sessions = false;
 
@@ -1167,6 +1169,13 @@
   if (handle_ip_change)
     NetworkChangeNotifier::AddIPAddressObserver(this);
 
+  // Port migration and early migration both act on path degrading and thus can
+  // not be simultaneously set.
+  DCHECK(!allow_port_migration || !migrate_sessions_early);
+
+  if (allow_port_migration)
+    params_.allow_port_migration = true;
+
   if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
     return;
 
@@ -1179,9 +1188,10 @@
 
   // Enable migration on platform notifications.
   params_.migrate_sessions_on_network_change_v2 = true;
+
   if (!migrate_sessions_early) {
-    DCHECK(!retry_on_alternate_network_before_handshake &&
-           !migrate_idle_sessions);
+    DCHECK(!migrate_idle_sessions &&
+           !retry_on_alternate_network_before_handshake);
     return;
   }
 
@@ -1918,7 +1928,7 @@
       params_.max_allowed_push_id, params_.migrate_sessions_early_v2,
       params_.migrate_sessions_on_network_change_v2, default_network_,
       retransmittable_on_wire_timeout_, params_.migrate_idle_sessions,
-      params_.idle_session_migration_period,
+      params_.allow_port_migration, params_.idle_session_migration_period,
       params_.max_time_on_non_default_network,
       params_.max_migrations_to_non_default_network_on_write_error,
       params_.max_migrations_to_non_default_network_on_path_degrading,
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 22551ed9..691f920 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -178,6 +178,9 @@
   // If true, an idle session will be migrated within the idle migration
   // period.
   bool migrate_idle_sessions = false;
+  // If true, sessions with open streams will attempt to migrate to a different
+  // port when the current path is poor.
+  bool allow_port_migration = false;
   // A session can be migrated if its idle time is within this period.
   base::TimeDelta idle_session_migration_period =
       kDefaultIdleSessionMigrationPeriod;
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc
index f57f9daa..d6aad04 100644
--- a/net/reporting/reporting_uploader_unittest.cc
+++ b/net/reporting/reporting_uploader_unittest.cc
@@ -449,8 +449,7 @@
       std::move(cookie), url.scheme(), CookieOptions(),
       cookie_callback.MakeCallback());
   cookie_callback.WaitUntilDone();
-  ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            cookie_callback.result());
+  ASSERT_TRUE(cookie_callback.result().IsInclude());
 
   TestUploadCallback upload_callback;
   uploader_->StartUpload(kOrigin, server_.GetURL("/"), kUploadBody, 0,
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 3f81a43..da86e5f7 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -416,9 +416,9 @@
   ProcessStrictTransportSecurityHeader();
   ProcessExpectCTHeader();
 
-  // Clear |cs_status_list_| after any processing in case
+  // Clear |set_cookie_status_list_| after any processing in case
   // SaveCookiesAndNotifyHeadersComplete is called again.
-  request_->set_maybe_stored_cookies(std::move(cs_status_list_));
+  request_->set_maybe_stored_cookies(std::move(set_cookie_status_list_));
 
   // The HTTP transaction may be restarted several times for the purposes
   // of sending authorization information. Each time it restarts, we get
@@ -642,20 +642,20 @@
     const CookieStatusList& cookies_with_status_list,
     const CookieStatusList& excluded_list) {
   DCHECK(request_->maybe_sent_cookies().empty());
-  CookieStatusList maybe_sent_cookies = excluded_list;
 
-  // TODO(crbug.com/993843): Pass in meaningful statuses, then actually use the
-  // statuses passed in.
+  // TODO(chlily): This is just for passing to CanGetCookies(), however the
+  // CookieList parameter of CanGetCookies(), which eventually gets passed to
+  // the NetworkDelegate, never actually gets used anywhere except in tests. The
+  // parameter should be removed.
   CookieList cookie_list =
       net::cookie_util::StripStatuses(cookies_with_status_list);
 
-  net::CanonicalCookie::CookieInclusionStatus status_for_cookie_list =
-      CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
-  if (!cookie_list.empty() && CanGetCookies(cookie_list)) {
-    status_for_cookie_list = CanonicalCookie::CookieInclusionStatus::INCLUDE;
+  bool can_get_cookies = CanGetCookies(cookie_list);
+  if (!cookies_with_status_list.empty() && can_get_cookies) {
     LogCookieUMA(cookie_list, *request_, request_info_);
 
-    std::string cookie_line = CanonicalCookie::BuildCookieLine(cookie_list);
+    std::string cookie_line =
+        CanonicalCookie::BuildCookieLine(cookies_with_status_list);
     UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
     request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
                                           cookie_line);
@@ -664,30 +664,28 @@
     request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
   }
 
-  // Report status for things in |cookie_list| after the delegate got a chance
-  // to block them.
-  for (const auto& cookie : cookie_list)
-    maybe_sent_cookies.push_back({cookie, status_for_cookie_list});
-
-  // Copy any cookies that would not be sent under SameSiteByDefaultCookies
-  // and/or CookiesWithoutSameSiteMustBeSecure with an informative status into
-  // the |maybe_sent_cookies| list so that we can display appropriate console
-  // warning messages about them. I.e. they are still included in the Cookie
-  // header, but they are *also* copied into |maybe_sent_cookies| with the
-  // CookieInclusionStatus that *would* apply. This special-casing will go away
-  // once SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure are on
-  // by default, as the affected cookies will just be excluded in the first
-  // place.
-  for (const CanonicalCookie& cookie : cookie_list) {
-    CanonicalCookie::CookieInclusionStatus
-        include_but_maybe_would_exclude_status =
-            cookie_util::CookieWouldBeExcludedDueToSameSite(cookie, options);
-    if (include_but_maybe_would_exclude_status !=
-        CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-      maybe_sent_cookies.push_back(
-          {cookie, include_but_maybe_would_exclude_status});
+  // Report status for things in |excluded_list| and |cookies_with_status_list|
+  // after the delegate got a chance to block them.
+  CookieStatusList maybe_sent_cookies = excluded_list;
+  // CanGetCookies only looks at the fields of the URLRequest, not the cookies
+  // it is passed, so if CanGetCookies(cookie_list) is false, then
+  // CanGetCookies(excluded_list) would also be false, so tag also the
+  // excluded cookies as having been blocked by user preferences.
+  if (!can_get_cookies) {
+    for (CookieStatusList::iterator it = maybe_sent_cookies.begin();
+         it != maybe_sent_cookies.end(); ++it) {
+      it->status.AddExclusionReason(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
     }
   }
+  for (const auto& cookie_with_status : cookies_with_status_list) {
+    CanonicalCookie::CookieInclusionStatus status = cookie_with_status.status;
+    if (!can_get_cookies) {
+      status.AddExclusionReason(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+    }
+    maybe_sent_cookies.push_back({cookie_with_status.cookie, status});
+  }
 
   request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies));
 
@@ -695,7 +693,7 @@
 }
 
 void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
-  DCHECK(cs_status_list_.empty());
+  DCHECK(set_cookie_status_list_.empty());
   DCHECK_EQ(0, num_cookie_lines_left_);
 
   // End of the call started in OnStartCompleted.
@@ -753,29 +751,26 @@
         request_->url(), cookie_string, base::Time::Now(), server_time,
         &returned_status);
 
-    if (returned_status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-      OnSetCookieResult(options, base::nullopt, std::move(cookie_string),
+    base::Optional<CanonicalCookie> cookie_to_return = base::nullopt;
+    if (returned_status.IsInclude()) {
+      DCHECK(cookie);
+      // Make a copy of the cookie if we successfully made one.
+      cookie_to_return = *cookie;
+    }
+    if (cookie && !CanSetCookie(*cookie, &options)) {
+      returned_status.AddExclusionReason(
+          CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+    }
+    if (!returned_status.IsInclude()) {
+      OnSetCookieResult(options, cookie_to_return, std::move(cookie_string),
                         returned_status);
       continue;
     }
-    DCHECK(cookie);
-
-    if (!CanSetCookie(*cookie, &options)) {
-      OnSetCookieResult(
-          options, base::make_optional<CanonicalCookie>(*cookie),
-          std::move(cookie_string),
-          CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
-      continue;
-    }
-
-    // Make a copy for the make_optional.
-    CanonicalCookie cookie_copy = *cookie;
 
     request_->context()->cookie_store()->SetCanonicalCookieAsync(
         std::move(cookie), request_->url().scheme(), options,
         base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
-                       weak_factory_.GetWeakPtr(), options,
-                       base::make_optional<CanonicalCookie>(cookie_copy),
+                       weak_factory_.GetWeakPtr(), options, cookie_to_return,
                        cookie_string));
   }
   // Removing the 1 that |num_cookie_lines_left| started with, signifing that
@@ -791,34 +786,14 @@
     base::Optional<CanonicalCookie> cookie,
     std::string cookie_string,
     CanonicalCookie::CookieInclusionStatus status) {
-  cs_status_list_.emplace_back(std::move(cookie), std::move(cookie_string),
-                               status);
-
-  if (status == CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-    DCHECK(cookie.has_value());
-    // Copy any cookies that would not be sent under SameSiteByDefaultCookies
-    // and/or CookiesWithoutSameSiteMustBeSecure into |cs_status_list_| with a
-    // descriptive status so that we can display appropriate console warning
-    // messages about them. I.e. they are still set, but they are *also* copied
-    // into |cs_status_list_| with the CookieInclusionStatus that *would* apply.
-    // This special-casing will go away once SameSiteByDefaultCookies and
-    // CookiesWithoutSameSiteMustBeSecure are on by default, as the affected
-    // cookies will just be excluded in the first place.
-    CanonicalCookie::CookieInclusionStatus
-        include_but_maybe_would_exclude_status =
-            cookie_util::CookieWouldBeExcludedDueToSameSite(cookie.value(),
-                                                            options);
-    if (include_but_maybe_would_exclude_status !=
-        CanonicalCookie::CookieInclusionStatus::INCLUDE) {
-      cs_status_list_.emplace_back(std::move(cookie), std::move(cookie_string),
-                                   include_but_maybe_would_exclude_status);
-    }
-  }
+  set_cookie_status_list_.emplace_back(std::move(cookie),
+                                       std::move(cookie_string), status);
 
   num_cookie_lines_left_--;
 
-  // If all the cookie lines have been handled, |cs_status_list_| now reflects
-  // the result of all Set-Cookie lines, and the request can be continued.
+  // If all the cookie lines have been handled, |set_cookie_status_list_| now
+  // reflects the result of all Set-Cookie lines, and the request can be
+  // continued.
   if (num_cookie_lines_left_ == 0)
     NotifyHeadersComplete();
 }
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 0edc2ef..e501fb9 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -158,7 +158,7 @@
                          std::string cookie_string,
                          CanonicalCookie::CookieInclusionStatus status);
   int num_cookie_lines_left_;
-  CookieAndLineStatusList cs_status_list_;
+  CookieAndLineStatusList set_cookie_status_list_;
 
   // Some servers send the body compressed, but specify the content length as
   // the uncompressed size. If this is the case, we return true in order
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 1693eed..5fc1291d 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -8430,15 +8430,14 @@
     ASSERT_EQ(3u, req->maybe_stored_cookies().size());
     EXPECT_EQ("not_stored_cookie",
               req->maybe_stored_cookies()[0].cookie->Name());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        req->maybe_stored_cookies()[0].status);
+    EXPECT_TRUE(req->maybe_stored_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
     EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              req->maybe_stored_cookies()[1].status);
+    EXPECT_TRUE(req->maybe_stored_cookies()[1].status.IsInclude());
     EXPECT_EQ("stored_cookie", req->maybe_stored_cookies()[1].cookie->Name());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              req->maybe_stored_cookies()[2].status);
+    EXPECT_TRUE(req->maybe_stored_cookies()[2].status.IsInclude());
     EXPECT_EQ("path_cookie", req->maybe_stored_cookies()[2].cookie->Name());
   }
   {
@@ -8456,12 +8455,17 @@
 
     ASSERT_EQ(2u, req->maybe_sent_cookies().size());
     EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-              req->maybe_sent_cookies()[0].status);
+    EXPECT_TRUE(req->maybe_sent_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_NOT_ON_PATH,
+                         net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
     EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        req->maybe_sent_cookies()[1].status);
+    EXPECT_TRUE(req->maybe_sent_cookies()[1]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
   }
 
   network_delegate.unset_block_get_cookies();
@@ -8480,11 +8484,12 @@
 
     ASSERT_EQ(2u, req->maybe_sent_cookies().size());
     EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-              req->maybe_sent_cookies()[0].status);
+    EXPECT_TRUE(req->maybe_sent_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_NOT_ON_PATH}));
     EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              req->maybe_sent_cookies()[1].status);
+    EXPECT_TRUE(req->maybe_sent_cookies()[1].status.IsInclude());
   }
 }
 
@@ -8510,9 +8515,10 @@
 
   delegate.RunUntilAuthRequired();
   ASSERT_EQ(1u, request->maybe_stored_cookies().size());
-  EXPECT_EQ(
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-      request->maybe_stored_cookies()[0].status);
+  EXPECT_TRUE(request->maybe_stored_cookies()[0]
+                  .status.HasExactlyExclusionReasonsForTesting(
+                      {net::CanonicalCookie::CookieInclusionStatus::
+                           EXCLUDE_USER_PREFERENCES}));
   EXPECT_EQ("got_challenged=true",
             request->maybe_stored_cookies()[0].cookie_string);
 
@@ -8552,9 +8558,11 @@
 
     // The number of cookies blocked from the most recent round trip.
     ASSERT_EQ(1u, request->maybe_stored_cookies().size());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_stored_cookies().front().status);
+    EXPECT_TRUE(request->maybe_stored_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
 
     // Now check the second round trip
     request->SetAuth(AuthCredentials(kUser, kSecret));
@@ -8605,9 +8613,11 @@
     EXPECT_EQ("another_cookie",
               request->maybe_sent_cookies().front().cookie.Name());
     EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_sent_cookies().front().status);
+    EXPECT_TRUE(request->maybe_sent_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
 
     // Check maybe_sent_cookies on second roundtrip.
     request->set_maybe_sent_cookies({});
@@ -8637,9 +8647,11 @@
     ASSERT_EQ(1u, request->maybe_sent_cookies().size());
     EXPECT_EQ("one_more_cookie",
               request->maybe_sent_cookies().front().cookie.Name());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_sent_cookies().front().status);
+    EXPECT_TRUE(request->maybe_sent_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
   }
 }
 
@@ -8951,9 +8963,11 @@
     EXPECT_EQ("server-redirect",
               request->maybe_stored_cookies().front().cookie->Name());
     EXPECT_EQ("true", request->maybe_stored_cookies().front().cookie->Value());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_stored_cookies().front().status);
+    EXPECT_TRUE(request->maybe_stored_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
 
     // Check maybe_stored_cookies on second round trip (and clearing from the
     // first).
@@ -8972,9 +8986,11 @@
     EXPECT_EQ("server-redirect",
               request->maybe_stored_cookies().front().cookie->Name());
     EXPECT_EQ("other", request->maybe_stored_cookies().front().cookie->Value());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_stored_cookies().front().status);
+    EXPECT_TRUE(request->maybe_stored_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
   }
 
   // Check maybe_sent_cookies on first round trip.
@@ -9008,9 +9024,11 @@
     ASSERT_EQ(1u, request->maybe_sent_cookies().size());
     EXPECT_EQ("another_cookie",
               request->maybe_sent_cookies().front().cookie.Name());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_sent_cookies().front().status);
+    EXPECT_TRUE(request->maybe_sent_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
 
     // Check maybe_sent_cookies on second round trip
     request->set_maybe_sent_cookies({});
@@ -9036,9 +9054,11 @@
     EXPECT_EQ("one_more_cookie",
               request->maybe_sent_cookies().front().cookie.Name());
     EXPECT_EQ("true", request->maybe_sent_cookies().front().cookie.Value());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        request->maybe_sent_cookies().front().status);
+    EXPECT_TRUE(request->maybe_sent_cookies()
+                    .front()
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
   }
 }
 
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
index fb52e5f..37d5655e 100644
--- a/net/websockets/websocket_stream_cookie_test.cc
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -89,7 +89,7 @@
       base::WeakPtr<bool> weak_result,
       CanonicalCookie::CookieInclusionStatus status) {
     *weak_is_called = true;
-    *weak_result = (status == CanonicalCookie::CookieInclusionStatus::INCLUDE);
+    *weak_result = status.IsInclude();
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
   }
 };
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index 71d5b8f..73a5e19 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -203,6 +203,7 @@
         "pdfium/accessibility_unittest.cc",
         "pdfium/findtext_unittest.cc",
         "pdfium/pdfium_engine_exports_unittest.cc",
+        "pdfium/pdfium_engine_unittest.cc",
         "pdfium/pdfium_page_unittest.cc",
         "pdfium/pdfium_permissions_unittest.cc",
         "pdfium/pdfium_print_unittest.cc",
diff --git a/pdf/document_layout.cc b/pdf/document_layout.cc
index c1ef704..835dd271 100644
--- a/pdf/document_layout.cc
+++ b/pdf/document_layout.cc
@@ -59,7 +59,7 @@
   for (size_t i = 0; i < page_sizes.size(); ++i) {
     if (i != 0) {
       // Add space for bottom separator.
-      EnlargeHeight(kBottomSeparator);
+      size_.Enlarge(0, kBottomSeparator);
     }
 
     const pp::Size& page_size = page_sizes[i];
@@ -89,22 +89,18 @@
     } else {
       page_rect = draw_utils::GetRightRectForTwoUpView(
           page_size, {size_.width(), size_.height()});
-      EnlargeHeight(std::max(page_size.height(), page_sizes[i - 1].height()));
+      size_.Enlarge(0,
+                    std::max(page_size.height(), page_sizes[i - 1].height()));
     }
     page_layouts_[i].outer_rect = page_rect;
     page_layouts_[i].inner_rect = InsetRect(page_rect, page_insets);
   }
 
   if (page_sizes.size() % 2 == 1) {
-    EnlargeHeight(page_sizes.back().height());
+    size_.Enlarge(0, page_sizes.back().height());
   }
 
   size_.set_width(2 * size_.width());
 }
 
-void DocumentLayout::EnlargeHeight(int height) {
-  DCHECK_GE(height, 0);
-  size_.Enlarge(0, height);
-}
-
 }  // namespace chrome_pdf
diff --git a/pdf/document_layout.h b/pdf/document_layout.h
index 5b395d6..f657342 100644
--- a/pdf/document_layout.h
+++ b/pdf/document_layout.h
@@ -99,11 +99,6 @@
   // TODO(kmoon): Control layout type using an option.
   void ComputeTwoUpViewLayout(const std::vector<pp::Size>& page_sizes);
 
-  // Increases the layout's total height by |height|.
-  //
-  // TODO(kmoon): Delete or make this private.
-  void EnlargeHeight(int height);
-
  private:
   // Layout of a single page.
   struct PageLayout {
diff --git a/pdf/document_layout_unittest.cc b/pdf/document_layout_unittest.cc
index 1e4a5a4..45f7f07 100644
--- a/pdf/document_layout_unittest.cc
+++ b/pdf/document_layout_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "pdf/document_layout.h"
 
-#include "base/test/gtest_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chrome_pdf {
@@ -21,8 +20,6 @@
   DocumentLayout layout_;
 };
 
-using DocumentLayoutDeathTest = DocumentLayoutTest;
-
 // TODO(kmoon): Need to use this with EXPECT_PRED2 instead of just using
 // EXPECT_EQ, due to ADL issues with pp::Size's operator== (defined in global
 // namespace, instead of in "pp").
@@ -110,14 +107,6 @@
   EXPECT_PRED2(PpSizeEq, layout_.size(), pp::Size(1, 2));
 }
 
-TEST_F(DocumentLayoutTest, EnlargeHeight) {
-  layout_.EnlargeHeight(5);
-  EXPECT_PRED2(PpSizeEq, layout_.size(), pp::Size(0, 5));
-
-  layout_.EnlargeHeight(11);
-  EXPECT_PRED2(PpSizeEq, layout_.size(), pp::Size(0, 16));
-}
-
 TEST_F(DocumentLayoutTest, ComputeSingleViewLayout) {
   std::vector<pp::Size> page_sizes{
       {300, 400}, {400, 500}, {300, 400}, {200, 300}};
@@ -218,10 +207,6 @@
   EXPECT_PRED2(PpSizeEq, pp::Size(800, 1300), layout_.size());
 }
 
-TEST_F(DocumentLayoutDeathTest, EnlargeHeightNegativeIncrement) {
-  EXPECT_DCHECK_DEATH(layout_.EnlargeHeight(-5));
-}
-
 }  // namespace
 
 }  // namespace chrome_pdf
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index f438a8a..db6d0806 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -385,7 +385,7 @@
 
   // Append blank pages to make a 1-page document to a |num_pages| document.
   // Always retain the first page data.
-  virtual void AppendBlankPages(int num_pages) = 0;
+  virtual void AppendBlankPages(size_t num_pages) = 0;
   // Append the first page of the document loaded with the |engine| to this
   // document at page |index|.
   virtual void AppendPage(PDFEngine* engine, int index) = 0;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 79f7174..21a0c36 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -699,7 +699,7 @@
     if (pages_[i]->available())
       continue;
 
-    pages_[i]->set_available(true);
+    pages_[i]->MarkAvailable();
     // We still need to call IsPageAvail() even if the whole document is
     // already downloaded.
     FPDFAvail_IsPageAvail(fpdf_availability(), i, &download_hints);
@@ -2226,9 +2226,8 @@
   return true;
 }
 
-// TODO(kmoon): Rewrite this to use DocumentLayout properly.
-void PDFiumEngine::AppendBlankPages(int num_pages) {
-  DCHECK_NE(num_pages, 0);
+void PDFiumEngine::AppendBlankPages(size_t num_pages) {
+  DCHECK_GT(num_pages, 0U);
 
   if (!doc())
     return;
@@ -2242,49 +2241,26 @@
     FPDFPage_Delete(doc(), pages_.size());
   }
 
-  // Calculate document size and all page sizes.
-  std::vector<pp::Rect> page_rects;
-  pp::Size page_size = GetPageSize(0);
-  page_size.Enlarge(DocumentLayout::kSingleViewInsets.left +
-                        DocumentLayout::kSingleViewInsets.right,
-                    DocumentLayout::kSingleViewInsets.top +
-                        DocumentLayout::kSingleViewInsets.bottom);
-  pp::Size old_document_size = layout_.size();
-  layout_.set_size(pp::Size(page_size.width(), 0));
-  for (int i = 0; i < num_pages; ++i) {
-    if (i != 0) {
-      // Add space for bottom separator.
-      layout_.EnlargeHeight(DocumentLayout::kBottomSeparator);
-    }
+  // Create blank pages with the same size as the first page.
+  pp::Size page_0_size = GetPageSize(0);
+  double page_0_width_in_points =
+      ConvertUnitDouble(page_0_size.width(), kPixelsPerInch, kPointsPerInch);
+  double page_0_height_in_points =
+      ConvertUnitDouble(page_0_size.height(), kPixelsPerInch, kPointsPerInch);
 
-    pp::Rect rect(pp::Point(0, layout_.size().height()), page_size);
-    page_rects.push_back(rect);
-
-    layout_.EnlargeHeight(page_size.height());
-  }
-
-  // Create blank pages.
-  for (int i = 1; i < num_pages; ++i) {
-    pp::Rect page_rect(page_rects[i]);
-    page_rect.Inset(DocumentLayout::kSingleViewInsets.left,
-                    DocumentLayout::kSingleViewInsets.top,
-                    DocumentLayout::kSingleViewInsets.right,
-                    DocumentLayout::kSingleViewInsets.bottom);
-    double width_in_points =
-        ConvertUnitDouble(page_rect.width(), kPixelsPerInch, kPointsPerInch);
-    double height_in_points =
-        ConvertUnitDouble(page_rect.height(), kPixelsPerInch, kPointsPerInch);
+  for (size_t i = 1; i < num_pages; ++i) {
     {
       // Add a new page to the document, but delete the FPDF_PAGE object.
-      ScopedFPDFPage temp_page(
-          FPDFPage_New(doc(), i, width_in_points, height_in_points));
+      ScopedFPDFPage temp_page(FPDFPage_New(doc(), i, page_0_width_in_points,
+                                            page_0_height_in_points));
     }
-    pages_.push_back(std::make_unique<PDFiumPage>(this, i, page_rect, true));
+
+    auto page = std::make_unique<PDFiumPage>(this, i);
+    page->MarkAvailable();
+    pages_.push_back(std::move(page));
   }
 
-  CalculateVisiblePages();
-  if (layout_.size() != old_document_size)
-    client_->DocumentSizeUpdated(layout_.size());
+  LoadPageInfo(true);
 }
 
 void PDFiumEngine::LoadDocument() {
@@ -2386,32 +2362,25 @@
     FinishLoadingDocument();
 }
 
-void PDFiumEngine::LoadPagesInCurrentLayout(std::vector<pp::Size> page_sizes,
-                                            bool reload) {
-  if (two_up_view_) {
-    layout_.ComputeTwoUpViewLayout(page_sizes);
-  } else {
-    layout_.ComputeSingleViewLayout(page_sizes);
-  }
-
-  ApplyCurrentLayoutToPages(reload);
-}
-
 // TODO(kmoon): This should be the only method that sets |PDFiumPage::rect_|.
 void PDFiumEngine::ApplyCurrentLayoutToPages(bool reload) {
   for (size_t i = 0; i < layout_.page_count(); ++i) {
     const pp::Rect& page_rect = layout_.page_bounds_rect(i);
     if (!reload) {
-      // The page is marked as not being available even if |doc_complete| is
+      // The page is not marked as being available even if |doc_complete| is
       // true because FPDFAvail_IsPageAvail() still has to be called for this
       // page, which will be done in FinishLoadingDocument().
-      pages_.push_back(std::make_unique<PDFiumPage>(this, i, page_rect, false));
+      auto page = std::make_unique<PDFiumPage>(this, i);
+      page->set_rect(page_rect);
+      pages_.push_back(std::move(page));
     } else if (i < pages_.size()) {
       pages_[i]->set_rect(page_rect);
     } else {
-      bool available = FPDFAvail_IsPageAvail(fpdf_availability(), i, nullptr);
-      pages_.push_back(
-          std::make_unique<PDFiumPage>(this, i, page_rect, available));
+      auto page = std::make_unique<PDFiumPage>(this, i);
+      page->set_rect(page_rect);
+      if (FPDFAvail_IsPageAvail(fpdf_availability(), i, nullptr))
+        page->MarkAvailable();
+      pages_.push_back(std::move(page));
     }
   }
 }
@@ -2452,7 +2421,13 @@
     page_sizes.push_back(size);
   }
 
-  LoadPagesInCurrentLayout(page_sizes, reload);
+  if (two_up_view_) {
+    layout_.ComputeTwoUpViewLayout(page_sizes);
+  } else {
+    layout_.ComputeSingleViewLayout(page_sizes);
+  }
+
+  ApplyCurrentLayoutToPages(reload);
 
   // Remove pages that do not exist anymore.
   if (pages_.size() > new_page_count) {
@@ -2607,7 +2582,7 @@
   }
 
   if (index < num_pages)
-    pages_[index]->set_available(true);
+    pages_[index]->MarkAvailable();
   if (default_page_size_.IsEmpty())
     default_page_size_ = GetPageSize(index);
   return true;
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 7309ddba..13fc41c5 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -120,7 +120,7 @@
   int GetCopiesToPrint() override;
   int GetDuplexType() override;
   bool GetPageSizeAndUniformity(pp::Size* size) override;
-  void AppendBlankPages(int num_pages) override;
+  void AppendBlankPages(size_t num_pages) override;
   void AppendPage(PDFEngine* engine, int index) override;
   std::string GetMetadata(const std::string& key) override;
   std::vector<uint8_t> GetSaveData() override;
@@ -233,10 +233,6 @@
   // If this has been run once, it will not notify the client again.
   void FinishLoadingDocument();
 
-  // Formats the pages of |page_sizes| and appends them to |pages_|. Formats to
-  // two-up view if |two_up_view_| is true, else formats to single-view.
-  void LoadPagesInCurrentLayout(std::vector<pp::Size> page_sizes, bool reload);
-
   // Applies the current layout to the PDFiumPage objects. This primarily
   // involves updating the PDFiumPage rectangles from the corresponding layout
   // page rectangles.
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
new file mode 100644
index 0000000..c1761c4
--- /dev/null
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -0,0 +1,99 @@
+// 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 "pdf/pdfium/pdfium_engine.h"
+
+#include "pdf/pdfium/pdfium_page.h"
+#include "pdf/pdfium/pdfium_test_base.h"
+#include "pdf/test/test_client.h"
+#include "pdf/test/test_utils.h"
+#include "ppapi/cpp/size.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_pdf {
+namespace {
+
+using ::testing::InSequence;
+using ::testing::NiceMock;
+
+class MockTestClient : public TestClient {
+ public:
+  // TODO(crbug.com/989095): MOCK_METHOD() triggers static_assert on Windows.
+  MOCK_METHOD1(DocumentSizeUpdated, void(const pp::Size& size));
+};
+
+class PDFiumEngineTest : public PDFiumTestBase {
+ protected:
+  void ExpectPageRect(PDFiumEngine* engine,
+                      size_t page_index,
+                      const pp::Rect& expected_rect) {
+    PDFiumPage* page = GetPDFiumPageForTest(engine, page_index);
+    ASSERT_TRUE(page);
+    CompareRect(expected_rect, page->rect());
+  }
+};
+
+TEST_F(PDFiumEngineTest, InitializeWithRectanglesMultiPagesPdf) {
+  NiceMock<MockTestClient> client;
+  EXPECT_CALL(client, DocumentSizeUpdated(pp::Size(343, 1664)));
+
+  std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
+      &client, FILE_PATH_LITERAL("rectangles_multi_pages.pdf"));
+  ASSERT_TRUE(engine);
+  ASSERT_EQ(5, engine->GetNumberOfPages());
+
+  ExpectPageRect(engine.get(), 0, {38, 3, 266, 333});
+  ExpectPageRect(engine.get(), 1, {5, 350, 333, 266});
+  ExpectPageRect(engine.get(), 2, {38, 630, 266, 333});
+  ExpectPageRect(engine.get(), 3, {38, 977, 266, 333});
+  ExpectPageRect(engine.get(), 4, {38, 1324, 266, 333});
+}
+
+TEST_F(PDFiumEngineTest, AppendBlankPagesWithFewerPages) {
+  NiceMock<MockTestClient> client;
+  {
+    InSequence normal_then_append;
+    EXPECT_CALL(client, DocumentSizeUpdated(pp::Size(343, 1664)));
+    EXPECT_CALL(client, DocumentSizeUpdated(pp::Size(276, 1037)));
+  }
+
+  std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
+      &client, FILE_PATH_LITERAL("rectangles_multi_pages.pdf"));
+  ASSERT_TRUE(engine);
+
+  engine->AppendBlankPages(3);
+  ASSERT_EQ(3, engine->GetNumberOfPages());
+
+  ExpectPageRect(engine.get(), 0, {5, 3, 266, 333});
+  ExpectPageRect(engine.get(), 1, {5, 350, 266, 333});
+  ExpectPageRect(engine.get(), 2, {5, 697, 266, 333});
+}
+
+TEST_F(PDFiumEngineTest, AppendBlankPagesWithMorePages) {
+  NiceMock<MockTestClient> client;
+  {
+    InSequence normal_then_append;
+    EXPECT_CALL(client, DocumentSizeUpdated(pp::Size(343, 1664)));
+    EXPECT_CALL(client, DocumentSizeUpdated(pp::Size(276, 2425)));
+  }
+
+  std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
+      &client, FILE_PATH_LITERAL("rectangles_multi_pages.pdf"));
+  ASSERT_TRUE(engine);
+
+  engine->AppendBlankPages(7);
+  ASSERT_EQ(7, engine->GetNumberOfPages());
+
+  ExpectPageRect(engine.get(), 0, {5, 3, 266, 333});
+  ExpectPageRect(engine.get(), 1, {5, 350, 266, 333});
+  ExpectPageRect(engine.get(), 2, {5, 697, 266, 333});
+  ExpectPageRect(engine.get(), 3, {5, 1044, 266, 333});
+  ExpectPageRect(engine.get(), 4, {5, 1391, 266, 333});
+  ExpectPageRect(engine.get(), 5, {5, 1738, 266, 333});
+  ExpectPageRect(engine.get(), 6, {5, 2085, 266, 333});
+}
+
+}  // namespace
+}  // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc
index 5329892..8cc124df 100644
--- a/pdf/pdfium/pdfium_page.cc
+++ b/pdf/pdfium/pdfium_page.cc
@@ -192,14 +192,8 @@
 
 PDFiumPage::LinkTarget::~LinkTarget() = default;
 
-PDFiumPage::PDFiumPage(PDFiumEngine* engine,
-                       int i,
-                       const pp::Rect& r,
-                       bool available)
-    : engine_(engine),
-      index_(i),
-      rect_(r),
-      available_(available) {}
+PDFiumPage::PDFiumPage(PDFiumEngine* engine, int i)
+    : engine_(engine), index_(i), available_(false) {}
 
 PDFiumPage::PDFiumPage(PDFiumPage&& that) = default;
 
diff --git a/pdf/pdfium/pdfium_page.h b/pdf/pdfium/pdfium_page.h
index 0816187..ae7695c 100644
--- a/pdf/pdfium/pdfium_page.h
+++ b/pdf/pdfium/pdfium_page.h
@@ -31,7 +31,7 @@
 // Wrapper around a page from the document.
 class PDFiumPage {
  public:
-  PDFiumPage(PDFiumEngine* engine, int i, const pp::Rect& r, bool available);
+  PDFiumPage(PDFiumEngine* engine, int i);
   PDFiumPage(PDFiumPage&& that);
   ~PDFiumPage();
 
@@ -123,10 +123,15 @@
   const PDFEngine::PageFeatures* GetPageFeatures();
 
   int index() const { return index_; }
+
   const pp::Rect& rect() const { return rect_; }
   void set_rect(const pp::Rect& r) { rect_ = r; }
+
+  // Availability is a one-way transition: A page can become available, but it
+  // cannot become unavailable (unless deleted entirely).
   bool available() const { return available_; }
-  void set_available(bool available) { available_ = available; }
+  void MarkAvailable() { available_ = true; }
+
   void set_calculated_links(bool calculated_links) {
     calculated_links_ = calculated_links;
   }
diff --git a/pdf/pdfium/pdfium_page_unittest.cc b/pdf/pdfium/pdfium_page_unittest.cc
index d2887dd..e41cee2f 100644
--- a/pdf/pdfium/pdfium_page_unittest.cc
+++ b/pdf/pdfium/pdfium_page_unittest.cc
@@ -17,14 +17,14 @@
 
 namespace {
 
-TEST(PDFiumPageTest, ToPDFiumRotation) {
+TEST(PDFiumPageHelperTest, ToPDFiumRotation) {
   EXPECT_EQ(ToPDFiumRotation(PageOrientation::kOriginal), 0);
   EXPECT_EQ(ToPDFiumRotation(PageOrientation::kClockwise90), 1);
   EXPECT_EQ(ToPDFiumRotation(PageOrientation::kClockwise180), 2);
   EXPECT_EQ(ToPDFiumRotation(PageOrientation::kClockwise270), 3);
 }
 
-TEST(PDFiumPageDeathTest, ToPDFiumRotation) {
+TEST(PDFiumPageHelperDeathTest, ToPDFiumRotation) {
   PageOrientation invalid_orientation = static_cast<PageOrientation>(-1);
 #if DCHECK_IS_ON()
   EXPECT_DCHECK_DEATH(ToPDFiumRotation(invalid_orientation));
@@ -35,6 +35,15 @@
 
 }  // namespace
 
+using PDFiumPageTest = PDFiumTestBase;
+
+TEST_F(PDFiumPageTest, Constructor) {
+  PDFiumPage page(/*engine=*/nullptr, 2);
+  EXPECT_EQ(page.index(), 2);
+  EXPECT_TRUE(page.rect().IsEmpty());
+  EXPECT_FALSE(page.available());
+}
+
 class PDFiumPageLinkTest : public PDFiumTestBase {
  public:
   PDFiumPageLinkTest() = default;
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc
index faac644..b0753ea1 100644
--- a/printing/backend/print_backend_win.cc
+++ b/printing/backend/print_backend_win.cc
@@ -26,6 +26,12 @@
 
 namespace {
 
+ScopedPrinterHandle GetPrinterHandle(const std::string& printer_name) {
+  ScopedPrinterHandle handle;
+  handle.OpenPrinterWithName(base::UTF8ToWide(printer_name).c_str());
+  return handle;
+}
+
 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) {
   DCHECK(stream);
   DCHECK(out);
@@ -223,11 +229,9 @@
 
 bool PrintBackendWin::GetPrinterBasicInfo(const std::string& printer_name,
                                           PrinterBasicInfo* printer_info) {
-  ScopedPrinterHandle printer_handle;
-  if (!printer_handle.OpenPrinterWithName(
-          base::UTF8ToWide(printer_name).c_str())) {
+  ScopedPrinterHandle printer_handle = GetPrinterHandle(printer_name);
+  if (!printer_handle.IsValid())
     return false;
-  }
 
   if (!InitBasicPrinterInfo(printer_handle.Get(), printer_info))
     return false;
@@ -240,9 +244,8 @@
 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults(
     const std::string& printer_name,
     PrinterSemanticCapsAndDefaults* printer_info) {
-  ScopedPrinterHandle printer_handle;
-  if (!printer_handle.OpenPrinterWithName(
-          base::UTF8ToWide(printer_name).c_str())) {
+  ScopedPrinterHandle printer_handle = GetPrinterHandle(printer_name);
+  if (!printer_handle.IsValid()) {
     LOG(WARNING) << "Failed to open printer, error = " << GetLastError();
     return false;
   }
@@ -378,16 +381,13 @@
 // Gets the information about driver for a specific printer.
 std::string PrintBackendWin::GetPrinterDriverInfo(
     const std::string& printer_name) {
-  ScopedPrinterHandle printer;
-  if (!printer.OpenPrinterWithName(base::UTF8ToWide(printer_name).c_str()))
-    return std::string();
-  return GetDriverInfo(printer.Get());
+  ScopedPrinterHandle printer = GetPrinterHandle(printer_name);
+  return printer.IsValid() ? GetDriverInfo(printer.Get()) : std::string();
 }
 
 bool PrintBackendWin::IsValidPrinter(const std::string& printer_name) {
-  ScopedPrinterHandle printer_handle;
-  return printer_handle.OpenPrinterWithName(
-      base::UTF8ToWide(printer_name).c_str());
+  ScopedPrinterHandle printer_handle = GetPrinterHandle(printer_name);
+  return printer_handle.IsValid();
 }
 
 // static
diff --git a/remoting/branding_Chrome b/remoting/branding_Chrome
index c6dcef7..e028256 100644
--- a/remoting/branding_Chrome
+++ b/remoting/branding_Chrome
@@ -11,9 +11,9 @@
 MAC_HOST_LEGACY_BUNDLE_NAME=ChromeRemoteDesktopHost.bundle
 MAC_HOST_PACKAGE_NAME=Chrome Remote Desktop Host
 MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID=com.google.chrome.remote_desktop.native-messaging-host
-MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.bundle
-MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=com.google.chrome.remote_desktop.remote-assistance-host
-MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=RemoteAssistanceHost.bundle
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.app
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=com.google.chrome.remote_desktop.remote-assistance-host-v2
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=RemoteAssistanceHost.app
 MAC_UNINSTALLER_BUNDLE_ID=com.google.chromeremotedesktop.me2me-host-uninstaller
 MAC_UNINSTALLER_BUNDLE_PREFIX=com.google.pkg
 MAC_UNINSTALLER_NAME=Chrome Remote Desktop Host Uninstaller
diff --git a/remoting/branding_Chromium b/remoting/branding_Chromium
index 1b3d3cc..f12feb3 100644
--- a/remoting/branding_Chromium
+++ b/remoting/branding_Chromium
@@ -11,9 +11,9 @@
 MAC_HOST_LEGACY_BUNDLE_NAME=ChromotingHost.bundle
 MAC_HOST_PACKAGE_NAME=Chromoting Host
 MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID=org.chromium.chromoting.native-messaging-host
-MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.bundle
-MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=org.chromium.chromoting.remote-assistance-host
-MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=RemoteAssistanceHost.bundle
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.app
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=org.chromium.chromoting.remote-assistance-host-v2
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=RemoteAssistanceHost.app
 MAC_UNINSTALLER_BUNDLE_ID=org.chromium.chromoting.me2me-host-uninstaller
 MAC_UNINSTALLER_BUNDLE_PREFIX=org.chromium.pkg
 MAC_UNINSTALLER_NAME=Chromoting Host Uninstaller
diff --git a/remoting/host/installer/mac/Keystone/GoogleSoftwareUpdate.pkg b/remoting/host/installer/mac/Keystone/GoogleSoftwareUpdate.pkg
index 7ce47cf..19f96e5 100644
--- a/remoting/host/installer/mac/Keystone/GoogleSoftwareUpdate.pkg
+++ b/remoting/host/installer/mac/Keystone/GoogleSoftwareUpdate.pkg
Binary files differ
diff --git a/services/device/geolocation/geolocation_context.cc b/services/device/geolocation/geolocation_context.cc
index 3b8e0bc..abdbabc4 100644
--- a/services/device/geolocation/geolocation_context.cc
+++ b/services/device/geolocation/geolocation_context.cc
@@ -22,8 +22,9 @@
                           std::move(request));
 }
 
-void GeolocationContext::BindGeolocation(mojom::GeolocationRequest request) {
-  GeolocationImpl* impl = new GeolocationImpl(std::move(request), this);
+void GeolocationContext::BindGeolocation(
+    mojo::PendingReceiver<mojom::Geolocation> receiver) {
+  GeolocationImpl* impl = new GeolocationImpl(std::move(receiver), this);
   impls_.push_back(base::WrapUnique<GeolocationImpl>(impl));
   if (geoposition_override_)
     impl->SetOverride(*geoposition_override_);
diff --git a/services/device/geolocation/geolocation_context.h b/services/device/geolocation/geolocation_context.h
index a4418c1..110ec3e 100644
--- a/services/device/geolocation/geolocation_context.h
+++ b/services/device/geolocation/geolocation_context.h
@@ -29,7 +29,8 @@
   static void Create(mojom::GeolocationContextRequest request);
 
   // mojom::GeolocationContext implementation:
-  void BindGeolocation(mojom::GeolocationRequest request) override;
+  void BindGeolocation(
+      mojo::PendingReceiver<mojom::Geolocation> receiver) override;
   void SetOverride(mojom::GeopositionPtr geoposition) override;
   void ClearOverride() override;
 
diff --git a/services/device/geolocation/geolocation_impl.cc b/services/device/geolocation/geolocation_impl.cc
index a0cac0fb..c439c0e 100644
--- a/services/device/geolocation/geolocation_impl.cc
+++ b/services/device/geolocation/geolocation_impl.cc
@@ -59,14 +59,14 @@
 
 }  // namespace
 
-GeolocationImpl::GeolocationImpl(mojo::InterfaceRequest<Geolocation> request,
+GeolocationImpl::GeolocationImpl(mojo::PendingReceiver<Geolocation> receiver,
                                  GeolocationContext* context)
-    : binding_(this, std::move(request)),
+    : receiver_(this, std::move(receiver)),
       context_(context),
       high_accuracy_(false),
       has_position_to_report_(false) {
   DCHECK(context_);
-  binding_.set_connection_error_handler(base::BindOnce(
+  receiver_.set_disconnect_handler(base::BindOnce(
       &GeolocationImpl::OnConnectionError, base::Unretained(this)));
 }
 
diff --git a/services/device/geolocation/geolocation_impl.h b/services/device/geolocation/geolocation_impl.h
index 53f74d8..e19e504b 100644
--- a/services/device/geolocation/geolocation_impl.h
+++ b/services/device/geolocation/geolocation_impl.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "services/device/geolocation/geolocation_provider_impl.h"
 #include "services/device/public/mojom/geolocation.mojom.h"
 
@@ -21,7 +21,7 @@
 class GeolocationImpl : public mojom::Geolocation {
  public:
   // |context| must outlive this object.
-  GeolocationImpl(mojo::InterfaceRequest<mojom::Geolocation> request,
+  GeolocationImpl(mojo::PendingReceiver<mojom::Geolocation> receiver,
                   GeolocationContext* context);
   ~GeolocationImpl() override;
 
@@ -47,7 +47,7 @@
   void ReportCurrentPosition();
 
   // The binding between this object and the other end of the pipe.
-  mojo::Binding<mojom::Geolocation> binding_;
+  mojo::Receiver<mojom::Geolocation> receiver_;
 
   // Owns this object.
   GeolocationContext* context_;
diff --git a/services/device/geolocation/public_ip_address_geolocation_provider.cc b/services/device/geolocation/public_ip_address_geolocation_provider.cc
index 44fc46c3..84fd0f9 100644
--- a/services/device/geolocation/public_ip_address_geolocation_provider.cc
+++ b/services/device/geolocation/public_ip_address_geolocation_provider.cc
@@ -25,25 +25,25 @@
 PublicIpAddressGeolocationProvider::~PublicIpAddressGeolocationProvider() {}
 
 void PublicIpAddressGeolocationProvider::Bind(
-    mojom::PublicIpAddressGeolocationProviderRequest request) {
+    mojo::PendingReceiver<mojom::PublicIpAddressGeolocationProvider> receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(public_ip_address_location_notifier_);
-  provider_binding_set_.AddBinding(this, std::move(request));
+  provider_receiver_set_.Add(this, std::move(receiver));
 }
 
 void PublicIpAddressGeolocationProvider::CreateGeolocation(
     const net::MutablePartialNetworkTrafficAnnotationTag& tag,
-    mojom::GeolocationRequest request) {
+    mojo::PendingReceiver<mojom::Geolocation> receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(public_ip_address_location_notifier_);
-  geolocation_binding_set_.AddBinding(
+  geolocation_receiver_set_.Add(
       std::make_unique<PublicIpAddressGeolocator>(
           static_cast<net::PartialNetworkTrafficAnnotationTag>(tag),
           public_ip_address_location_notifier_.get(),
           base::Bind(
-              &mojo::StrongBindingSet<mojom::Geolocation>::ReportBadMessage,
-              base::Unretained(&geolocation_binding_set_))),
-      std::move(request));
+              &mojo::UniqueReceiverSet<mojom::Geolocation>::ReportBadMessage,
+              base::Unretained(&geolocation_receiver_set_))),
+      std::move(receiver));
 }
 
 }  // namespace device
diff --git a/services/device/geolocation/public_ip_address_geolocation_provider.h b/services/device/geolocation/public_ip_address_geolocation_provider.h
index 687824d32..a803ac7 100644
--- a/services/device/geolocation/public_ip_address_geolocation_provider.h
+++ b/services/device/geolocation/public_ip_address_geolocation_provider.h
@@ -8,8 +8,8 @@
 #include <string>
 
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/geolocation/public_ip_address_geolocator.h"
 #include "services/device/geolocation/public_ip_address_location_notifier.h"
@@ -41,7 +41,8 @@
   ~PublicIpAddressGeolocationProvider() override;
 
   // Binds a PublicIpAddressGeolocationProvider request to this instance.
-  void Bind(mojom::PublicIpAddressGeolocationProviderRequest request);
+  void Bind(mojo::PendingReceiver<mojom::PublicIpAddressGeolocationProvider>
+                receiver);
 
  private:
   SEQUENCE_CHECKER(sequence_checker_);
@@ -50,7 +51,7 @@
   // Provides a Geolocation instance that performs IP-geolocation only.
   void CreateGeolocation(
       const net::MutablePartialNetworkTrafficAnnotationTag& tag,
-      mojom::GeolocationRequest request) override;
+      mojo::PendingReceiver<mojom::Geolocation> receiver) override;
 
   // Central PublicIpAddressLocationNotifier for use by all implementations of
   // mojom::Geolocation provided by the CreateGeolocation method.
@@ -59,10 +60,10 @@
   std::unique_ptr<PublicIpAddressLocationNotifier>
       public_ip_address_location_notifier_;
 
-  mojo::BindingSet<mojom::PublicIpAddressGeolocationProvider>
-      provider_binding_set_;
+  mojo::ReceiverSet<mojom::PublicIpAddressGeolocationProvider>
+      provider_receiver_set_;
 
-  mojo::StrongBindingSet<mojom::Geolocation> geolocation_binding_set_;
+  mojo::UniqueReceiverSet<mojom::Geolocation> geolocation_receiver_set_;
 
   DISALLOW_COPY_AND_ASSIGN(PublicIpAddressGeolocationProvider);
 };
diff --git a/services/device/public/cpp/test/scoped_geolocation_overrider.cc b/services/device/public/cpp/test/scoped_geolocation_overrider.cc
index 27c2ae1c..cc720935 100644
--- a/services/device/public/cpp/test/scoped_geolocation_overrider.cc
+++ b/services/device/public/cpp/test/scoped_geolocation_overrider.cc
@@ -26,7 +26,8 @@
   void BindForOverrideService(mojom::GeolocationContextRequest request);
 
   // mojom::GeolocationContext implementation:
-  void BindGeolocation(mojom::GeolocationRequest request) override;
+  void BindGeolocation(
+      mojo::PendingReceiver<mojom::Geolocation> receiver) override;
   void SetOverride(mojom::GeopositionPtr geoposition) override;
   void ClearOverride() override;
 
@@ -39,7 +40,7 @@
 
 class ScopedGeolocationOverrider::FakeGeolocation : public mojom::Geolocation {
  public:
-  FakeGeolocation(mojom::GeolocationRequest request,
+  FakeGeolocation(mojo::PendingReceiver<mojom::Geolocation> receiver,
                   const FakeGeolocationContext* context);
   ~FakeGeolocation() override;
 
@@ -53,7 +54,7 @@
   const FakeGeolocationContext* context_;
   bool has_new_position_;
   QueryNextPositionCallback position_callback_;
-  mojo::Binding<mojom::Geolocation> binding_;
+  mojo::Receiver<mojom::Geolocation> receiver_{this};
 };
 
 ScopedGeolocationOverrider::ScopedGeolocationOverrider(
@@ -141,8 +142,9 @@
 }
 
 void ScopedGeolocationOverrider::FakeGeolocationContext::BindGeolocation(
-    mojom::GeolocationRequest request) {
-  impls_.push_back(std::make_unique<FakeGeolocation>(std::move(request), this));
+    mojo::PendingReceiver<mojom::Geolocation> receiver) {
+  impls_.push_back(
+      std::make_unique<FakeGeolocation>(std::move(receiver), this));
 }
 
 void ScopedGeolocationOverrider::FakeGeolocationContext::SetOverride(
@@ -165,10 +167,10 @@
 }
 
 ScopedGeolocationOverrider::FakeGeolocation::FakeGeolocation(
-    mojom::GeolocationRequest request,
+    mojo::PendingReceiver<mojom::Geolocation> receiver,
     const FakeGeolocationContext* context)
-    : context_(context), has_new_position_(true), binding_(this) {
-  binding_.Bind(std::move(request));
+    : context_(context), has_new_position_(true) {
+  receiver_.Bind(std::move(receiver));
 }
 
 ScopedGeolocationOverrider::FakeGeolocation::~FakeGeolocation() {}
diff --git a/services/device/public/cpp/test/scoped_geolocation_overrider.h b/services/device/public/cpp/test/scoped_geolocation_overrider.h
index abb366d..5533a4d 100644
--- a/services/device/public/cpp/test/scoped_geolocation_overrider.h
+++ b/services/device/public/cpp/test/scoped_geolocation_overrider.h
@@ -6,8 +6,8 @@
 #define SERVICES_DEVICE_PUBLIC_CPP_TEST_SCOPED_GEOLOCATION_OVERRIDER_H_
 
 #include "base/bind.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "services/device/public/mojom/geolocation.mojom.h"
 #include "services/device/public/mojom/geolocation_context.mojom.h"
 #include "services/device/public/mojom/geoposition.mojom.h"
diff --git a/services/device/public/mojom/geolocation_context.mojom b/services/device/public/mojom/geolocation_context.mojom
index 00ca070..2123c45c 100644
--- a/services/device/public/mojom/geolocation_context.mojom
+++ b/services/device/public/mojom/geolocation_context.mojom
@@ -12,7 +12,7 @@
 // instances created by this context.
 interface GeolocationContext {
   // Creates a Geolocation instance that is bound to the |request|.
-  BindGeolocation(Geolocation& request);
+  BindGeolocation(pending_receiver<Geolocation> receiver);
 
   // Enables geolocation override. This method can be used to trigger possible
   // location-specific behavior in GeolocationImpl created by this
diff --git a/services/device/public/mojom/public_ip_address_geolocation_provider.mojom b/services/device/public/mojom/public_ip_address_geolocation_provider.mojom
index 145e2e4..26be39a 100644
--- a/services/device/public/mojom/public_ip_address_geolocation_provider.mojom
+++ b/services/device/public/mojom/public_ip_address_geolocation_provider.mojom
@@ -14,5 +14,5 @@
 // WARNING: DO NOT USE WITHOUT PRIVACY REVIEW.
 interface PublicIpAddressGeolocationProvider {
   CreateGeolocation(network.mojom.MutablePartialNetworkTrafficAnnotationTag tag,
-                    Geolocation& request);
+                    pending_receiver<Geolocation> receiver);
 };
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc
index b8e0093..6794f77 100644
--- a/services/network/cookie_manager_unittest.cc
+++ b/services/network/cookie_manager_unittest.cc
@@ -120,8 +120,8 @@
                           std::string source_scheme,
                           bool modify_http_only) {
     base::RunLoop run_loop;
-    net::CanonicalCookie::CookieInclusionStatus result_out =
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+    net::CanonicalCookie::CookieInclusionStatus result_out(
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
     net::CookieOptions options;
     options.set_same_site_cookie_context(
         net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
@@ -137,7 +137,7 @@
             }));
 
     run_loop.Run();
-    return result_out == net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return result_out.IsInclude();
   }
 
   net::CanonicalCookie::CookieInclusionStatus SetCanonicalCookieWithStatus(
@@ -150,8 +150,8 @@
         net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
     if (modify_http_only)
       options.set_include_httponly();
-    net::CanonicalCookie::CookieInclusionStatus result_out =
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+    net::CanonicalCookie::CookieInclusionStatus result_out(
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
     cookie_service_->SetCanonicalCookie(
         cookie, std::move(source_scheme), options,
         base::BindLambdaForTesting(
@@ -245,8 +245,7 @@
                            net::CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result() ==
-           net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   std::string DumpAllCookies() {
@@ -492,8 +491,8 @@
 
   EXPECT_EQ("HttpOnly", excluded_cookies[0].cookie.Name());
   EXPECT_EQ("F", excluded_cookies[0].cookie.Value());
-  EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-            excluded_cookies[0].status);
+  EXPECT_TRUE(excluded_cookies[0].status.HasExactlyExclusionReasonsForTesting(
+      {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 }
 
 TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
@@ -717,14 +716,18 @@
 }
 
 TEST_F(CookieManagerTest, ConfirmSecureSetFails) {
-  EXPECT_EQ(service_wrapper()->SetCanonicalCookieWithStatus(
-                net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
-                                     base::Time(), base::Time(),
-                                     /*secure=*/true, /*httponly=*/false,
-                                     net::CookieSameSite::NO_RESTRICTION,
-                                     net::COOKIE_PRIORITY_MEDIUM),
-                "http", false),
-            net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
+  EXPECT_TRUE(
+      service_wrapper()
+          ->SetCanonicalCookieWithStatus(
+              net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
+                                   base::Time(), base::Time(),
+                                   /*secure=*/true, /*httponly=*/false,
+                                   net::CookieSameSite::NO_RESTRICTION,
+                                   net::COOKIE_PRIORITY_MEDIUM),
+              "http", false)
+          .HasExactlyExclusionReasonsForTesting(
+              {net::CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_SECURE_ONLY}));
   std::vector<net::CanonicalCookie> cookies =
       service_wrapper()->GetAllCookies();
 
@@ -732,14 +735,18 @@
 }
 
 TEST_F(CookieManagerTest, ConfirmHttpOnlySetFails) {
-  EXPECT_EQ(service_wrapper()->SetCanonicalCookieWithStatus(
-                net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
-                                     base::Time(), base::Time(),
-                                     /*secure=*/false, /*httponly=*/true,
-                                     net::CookieSameSite::NO_RESTRICTION,
-                                     net::COOKIE_PRIORITY_MEDIUM),
-                "http", false),
-            net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
+  EXPECT_TRUE(
+      service_wrapper()
+          ->SetCanonicalCookieWithStatus(
+              net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
+                                   base::Time(), base::Time(),
+                                   /*secure=*/false, /*httponly=*/true,
+                                   net::CookieSameSite::NO_RESTRICTION,
+                                   net::COOKIE_PRIORITY_MEDIUM),
+              "http", false)
+          .HasExactlyExclusionReasonsForTesting(
+              {net::CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_HTTP_ONLY}));
   std::vector<net::CanonicalCookie> cookies =
       service_wrapper()->GetAllCookies();
 
@@ -755,15 +762,18 @@
           net::COOKIE_PRIORITY_MEDIUM),
       "https", true));
 
-  EXPECT_EQ(
-      service_wrapper()->SetCanonicalCookieWithStatus(
-          net::CanonicalCookie(
-              "Secure", "Nope", kCookieDomain, "/with/path", base::Time(),
-              base::Time(), base::Time(), /*secure=*/false,
-              /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION,
-              net::COOKIE_PRIORITY_MEDIUM),
-          "http", false),
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE);
+  EXPECT_TRUE(
+      service_wrapper()
+          ->SetCanonicalCookieWithStatus(
+              net::CanonicalCookie(
+                  "Secure", "Nope", kCookieDomain, "/with/path", base::Time(),
+                  base::Time(), base::Time(), /*secure=*/false,
+                  /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION,
+                  net::COOKIE_PRIORITY_MEDIUM),
+              "http", false)
+          .HasExactlyExclusionReasonsForTesting(
+              {net::CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_SECURE}));
 
   std::vector<net::CanonicalCookie> cookies =
       service_wrapper()->GetAllCookies();
@@ -782,15 +792,18 @@
           net::COOKIE_PRIORITY_MEDIUM),
       "http", true));
 
-  EXPECT_EQ(
-      service_wrapper()->SetCanonicalCookieWithStatus(
-          net::CanonicalCookie(
-              "HttpOnly", "Nope", kCookieDomain, "/with/path", base::Time(),
-              base::Time(), base::Time(), /*secure=*/false,
-              /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION,
-              net::COOKIE_PRIORITY_MEDIUM),
-          "https", false),
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY);
+  EXPECT_TRUE(
+      service_wrapper()
+          ->SetCanonicalCookieWithStatus(
+              net::CanonicalCookie(
+                  "HttpOnly", "Nope", kCookieDomain, "/with/path", base::Time(),
+                  base::Time(), base::Time(), /*secure=*/false,
+                  /*httponly=*/false, net::CookieSameSite::NO_RESTRICTION,
+                  net::COOKIE_PRIORITY_MEDIUM),
+              "https", false)
+          .HasExactlyExclusionReasonsForTesting(
+              {net::CanonicalCookie::CookieInclusionStatus::
+                   EXCLUDE_OVERWRITE_HTTP_ONLY}));
 
   std::vector<net::CanonicalCookie> cookies =
       service_wrapper()->GetAllCookies();
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index cf21a63..9cda901 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -2089,8 +2089,7 @@
 void SetCookieCallback(base::RunLoop* run_loop,
                        bool* result_out,
                        net::CanonicalCookie::CookieInclusionStatus result) {
-  *result_out =
-      (result == net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  *result_out = result.IsInclude();
   run_loop->Quit();
 }
 
diff --git a/services/network/public/cpp/cookie_manager.typemap b/services/network/public/cpp/cookie_manager.typemap
index 3dab226..de9384bd 100644
--- a/services/network/public/cpp/cookie_manager.typemap
+++ b/services/network/public/cpp/cookie_manager.typemap
@@ -19,7 +19,8 @@
   "network.mojom.CookieSameSiteContext=::net::CookieOptions::SameSiteCookieContext",
   "network.mojom.CookieOptions=::net::CookieOptions",
   "network.mojom.CanonicalCookie=::net::CanonicalCookie",
-  "network.mojom.CookieInclusionStatus=::net::CanonicalCookie::CookieInclusionStatus",
+  "network.mojom.CookieInclusionStatusWarningReason=::net::CanonicalCookie::CookieInclusionStatus::WarningReason",
+  "network.mojom.CookieInclusionStatus=::net::CanonicalCookie::CookieInclusionStatus[move_only]",
   "network.mojom.CookieWithStatus=::net::CookieWithStatus",
   "network.mojom.CookieAndLineWithStatus=::net::CookieAndLineWithStatus",
 ]
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.cc b/services/network/public/cpp/cookie_manager_mojom_traits.cc
index bddaca7..014a3c9 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -86,136 +86,55 @@
   return false;
 }
 
-network::mojom::CookieInclusionStatus
-EnumTraits<network::mojom::CookieInclusionStatus,
-           net::CanonicalCookie::CookieInclusionStatus>::
-    ToMojom(net::CanonicalCookie::CookieInclusionStatus input) {
+network::mojom::CookieInclusionStatusWarningReason
+EnumTraits<network::mojom::CookieInclusionStatusWarningReason,
+           net::CanonicalCookie::CookieInclusionStatus::WarningReason>::
+    ToMojom(net::CanonicalCookie::CookieInclusionStatus::WarningReason input) {
   switch (input) {
-    case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-      return network::mojom::CookieInclusionStatus::INCLUDE;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-      return network::mojom::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE:
-      return network::mojom::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_NONE_INSECURE;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
-
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_NONCOOKIEABLE_SCHEME:
-      return network::mojom::CookieInclusionStatus::
-          EXCLUDE_NONCOOKIEABLE_SCHEME;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_OVERWRITE_HTTP_ONLY:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
-
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
-      return network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+    case net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+        DO_NOT_WARN:
+      return network::mojom::CookieInclusionStatusWarningReason::DO_NOT_WARN;
+    case net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+        WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT:
+      return network::mojom::CookieInclusionStatusWarningReason::
+          WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT;
+    case net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+        WARN_SAMESITE_NONE_INSECURE:
+      return network::mojom::CookieInclusionStatusWarningReason::
+          WARN_SAMESITE_NONE_INSECURE;
+    case net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+        WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE:
+      return network::mojom::CookieInclusionStatusWarningReason::
+          WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE;
   }
   NOTREACHED();
-  return network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+  return network::mojom::CookieInclusionStatusWarningReason::DO_NOT_WARN;
 }
 
-bool EnumTraits<network::mojom::CookieInclusionStatus,
-                net::CanonicalCookie::CookieInclusionStatus>::
-    FromMojom(network::mojom::CookieInclusionStatus input,
-              net::CanonicalCookie::CookieInclusionStatus* output) {
+bool EnumTraits<network::mojom::CookieInclusionStatusWarningReason,
+                net::CanonicalCookie::CookieInclusionStatus::WarningReason>::
+    FromMojom(
+        network::mojom::CookieInclusionStatusWarningReason input,
+        net::CanonicalCookie::CookieInclusionStatus::WarningReason* output) {
   switch (input) {
-    case network::mojom::CookieInclusionStatus::INCLUDE:
-      *output = net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    case network::mojom::CookieInclusionStatusWarningReason::DO_NOT_WARN:
+      *output = net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+          DO_NOT_WARN;
       return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_HTTP_ONLY:
-      *output = net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY;
+    case network::mojom::CookieInclusionStatusWarningReason::
+        WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT:
+      *output = net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+          WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT;
       return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_SECURE_ONLY:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY;
+    case network::mojom::CookieInclusionStatusWarningReason::
+        WARN_SAMESITE_NONE_INSECURE:
+      *output = net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+          WARN_SAMESITE_NONE_INSECURE;
       return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED:
-      *output = net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_EXTENDED;
-      return true;
-    case network::mojom::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-      *output = net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE:
-      *output = net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_NONE_INSECURE;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME:
-      *output = net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_NONCOOKIEABLE_SCHEME;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY:
-      *output = net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_OVERWRITE_HTTP_ONLY;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX;
-      return true;
-    case network::mojom::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR:
-      *output =
-          net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR;
+    case network::mojom::CookieInclusionStatusWarningReason::
+        WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE:
+      *output = net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+          WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE;
       return true;
   }
   NOTREACHED();
@@ -334,6 +253,21 @@
   return out->IsCanonical();
 }
 
+bool StructTraits<network::mojom::CookieInclusionStatusDataView,
+                  net::CanonicalCookie::CookieInclusionStatus>::
+    Read(network::mojom::CookieInclusionStatusDataView status,
+         net::CanonicalCookie::CookieInclusionStatus* out) {
+  *out = net::CanonicalCookie::CookieInclusionStatus();
+  out->set_exclusion_reasons(status.exclusion_reasons());
+
+  net::CanonicalCookie::CookieInclusionStatus::WarningReason warning;
+  if (!status.ReadWarning(&warning))
+    return false;
+  out->set_warning(warning);
+
+  return out->IsValid();
+}
+
 bool StructTraits<
     network::mojom::CookieWithStatusDataView,
     net::CookieWithStatus>::Read(network::mojom::CookieWithStatusDataView c,
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.h b/services/network/public/cpp/cookie_manager_mojom_traits.h
index a324f71..e5a345b 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -29,12 +29,13 @@
 };
 
 template <>
-struct EnumTraits<network::mojom::CookieInclusionStatus,
-                  net::CanonicalCookie::CookieInclusionStatus> {
-  static network::mojom::CookieInclusionStatus ToMojom(
-      net::CanonicalCookie::CookieInclusionStatus input);
-  static bool FromMojom(network::mojom::CookieInclusionStatus input,
-                        net::CanonicalCookie::CookieInclusionStatus* output);
+struct EnumTraits<network::mojom::CookieInclusionStatusWarningReason,
+                  net::CanonicalCookie::CookieInclusionStatus::WarningReason> {
+  static network::mojom::CookieInclusionStatusWarningReason ToMojom(
+      net::CanonicalCookie::CookieInclusionStatus::WarningReason input);
+  static bool FromMojom(
+      network::mojom::CookieInclusionStatusWarningReason input,
+      net::CanonicalCookie::CookieInclusionStatus::WarningReason* output);
 };
 
 template <>
@@ -105,6 +106,21 @@
 };
 
 template <>
+struct StructTraits<network::mojom::CookieInclusionStatusDataView,
+                    net::CanonicalCookie::CookieInclusionStatus> {
+  static uint32_t exclusion_reasons(
+      const net::CanonicalCookie::CookieInclusionStatus& s) {
+    return s.exclusion_reasons();
+  }
+  static net::CanonicalCookie::CookieInclusionStatus::WarningReason warning(
+      const net::CanonicalCookie::CookieInclusionStatus& s) {
+    return s.warning();
+  }
+  static bool Read(network::mojom::CookieInclusionStatusDataView status,
+                   net::CanonicalCookie::CookieInclusionStatus* out);
+};
+
+template <>
 struct StructTraits<network::mojom::CookieWithStatusDataView,
                     net::CookieWithStatus> {
   static const net::CanonicalCookie& cookie(const net::CookieWithStatus& c) {
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
index 94632c61..78dcf9b 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
@@ -22,43 +22,6 @@
   return mojo::EnumTraits<MojoType, NativeType>::FromMojom(intermediate, out);
 }
 
-TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
-  std::vector<net::CanonicalCookie::CookieInclusionStatus> statuses = {
-      net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_EXTENDED,
-      net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
-      net::CanonicalCookie::CookieInclusionStatus::
-          EXCLUDE_SAMESITE_NONE_INSECURE,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
-  };
-
-  for (auto status : statuses) {
-    int32_t serialized = -1;
-    using CookieInclusionStatusSerializer =
-        mojo::internal::Serializer<mojom::CookieInclusionStatus,
-                                   net::CanonicalCookie::CookieInclusionStatus>;
-    CookieInclusionStatusSerializer::Serialize(status, &serialized);
-    EXPECT_EQ(static_cast<int>(status), serialized);
-    net::CanonicalCookie::CookieInclusionStatus deserialized;
-    CookieInclusionStatusSerializer::Deserialize(serialized, &deserialized);
-    EXPECT_EQ(serialized, static_cast<int>(deserialized));
-  }
-}
-
 TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) {
   net::CanonicalCookie original(
       "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
@@ -93,13 +56,44 @@
       &original, &copied));
 }
 
+TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
+  // This status + warning combo doesn't really make sense. It's just an
+  // arbitrary selection of values to test the serialization/deserialization.
+  net::CanonicalCookie::CookieInclusionStatus original =
+      net::CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
+          {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+           net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+           net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY},
+          net::CanonicalCookie::CookieInclusionStatus::
+              WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
+
+  net::CanonicalCookie::CookieInclusionStatus copied;
+
+  EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieInclusionStatus>(
+      &original, &copied));
+  EXPECT_TRUE(copied.HasExactlyExclusionReasonsForTesting(
+      {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+       net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+       net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
+  EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::
+                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+            copied.warning());
+
+  net::CanonicalCookie::CookieInclusionStatus invalid;
+  invalid.set_exclusion_reasons(~0u);
+
+  EXPECT_FALSE(
+      mojo::test::SerializeAndDeserialize<mojom::CookieInclusionStatus>(
+          &invalid, &copied));
+}
+
 TEST(CookieManagerTraitsTest, Roundtrips_CookieWithStatus) {
   net::CanonicalCookie original_cookie(
       "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false,
       false, net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
 
   net::CookieWithStatus original = {
-      original_cookie, net::CanonicalCookie::CookieInclusionStatus::INCLUDE};
+      original_cookie, net::CanonicalCookie::CookieInclusionStatus()};
 
   net::CookieWithStatus copied;
 
@@ -129,7 +123,9 @@
                                                                    &roundtrip));
     EXPECT_EQ(cookie_state, roundtrip);
   }
+}
 
+TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSiteContext) {
   for (net::CookieOptions::SameSiteCookieContext context_state :
        {net::CookieOptions::SameSiteCookieContext::CROSS_SITE,
         net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
@@ -141,6 +137,23 @@
   }
 }
 
+TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatusWarningReason) {
+  for (net::CanonicalCookie::CookieInclusionStatus::WarningReason warning :
+       {net::CanonicalCookie::CookieInclusionStatus::WarningReason::DO_NOT_WARN,
+        net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+            WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+        net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+            WARN_SAMESITE_NONE_INSECURE,
+        net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+            WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE}) {
+    net::CanonicalCookie::CookieInclusionStatus::WarningReason roundtrip;
+    ASSERT_TRUE(
+        SerializeAndDeserializeEnum<mojom::CookieInclusionStatusWarningReason>(
+            warning, &roundtrip));
+    EXPECT_EQ(warning, roundtrip);
+  }
+}
+
 TEST(CookieManagerTraitsTest, Roundtrips_CookieOptions) {
   {
     net::CookieOptions least_trusted, copy;
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom
index da1897f..69903ebd 100644
--- a/services/network/public/mojom/cookie_manager.mojom
+++ b/services/network/public/mojom/cookie_manager.mojom
@@ -86,30 +86,20 @@
   CookiePriority priority = MEDIUM;
 };
 
-// Keep values here in sync with net::CanonicalCookie::CookieInclusionStatus.
-enum CookieInclusionStatus {
-  INCLUDE,
-  EXCLUDE_HTTP_ONLY,
-  EXCLUDE_SECURE_ONLY,
-  EXCLUDE_DOMAIN_MISMATCH,
-  EXCLUDE_NOT_ON_PATH,
-  EXCLUDE_SAMESITE_STRICT,
-  EXCLUDE_SAMESITE_LAX,
-  EXCLUDE_SAMESITE_EXTENDED,
-  EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
-  EXCLUDE_SAMESITE_NONE_INSECURE,
-  EXCLUDE_USER_PREFERENCES,
+// Keep values here in sync with
+// net::CanonicalCookie::CookieInclusionStatus::WarningReason.
+enum CookieInclusionStatusWarningReason {
+  DO_NOT_WARN = 0,
+  WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+  WARN_SAMESITE_NONE_INSECURE,
+  WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE
+};
 
-  // Statuses specific to setting cookies
-  EXCLUDE_FAILURE_TO_STORE,
-  EXCLUDE_NONCOOKIEABLE_SCHEME,
-  EXCLUDE_OVERWRITE_SECURE,
-  EXCLUDE_OVERWRITE_HTTP_ONLY,
-  EXCLUDE_INVALID_DOMAIN,
-  EXCLUDE_INVALID_PREFIX,
-
-  // Please keep last
-  EXCLUDE_UNKNOWN_ERROR
+// Exclusion reasons can be found in
+// net::CanonicalCookie::CookieInclusionStatus::ExclusionReason.
+struct CookieInclusionStatus {
+  uint32 exclusion_reasons;
+  CookieInclusionStatusWarningReason warning;
 };
 
 struct CookieWithStatus {
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc
index 3c658574..af31dce3 100644
--- a/services/network/restricted_cookie_manager.cc
+++ b/services/network/restricted_cookie_manager.cc
@@ -114,8 +114,7 @@
   void OnCookieChange(const net::CanonicalCookie& cookie,
                       net::CookieChangeCause cause) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    if (cookie.IncludeForRequestURL(url_, options_) !=
-        CookieInclusionStatus::INCLUDE)
+    if (!cookie.IncludeForRequestURL(url_, options_).IsInclude())
       return;
 
     // When a user blocks a site's access to cookies, the existing cookies are
@@ -237,11 +236,7 @@
   // TODO(https://crbug.com/977040): Remove once samesite tightening up is
   // rolled out.
   for (const auto& cookie_and_status : excluded_cookies) {
-    if (cookie_and_status.status ==
-            CookieInclusionStatus::
-                EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX ||
-        cookie_and_status.status ==
-            CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE) {
+    if (cookie_and_status.status.ShouldWarn()) {
       result_with_status.push_back(
           {cookie_and_status.cookie, cookie_and_status.status});
     }
@@ -254,6 +249,7 @@
   // TODO(https://crbug.com/993843): Use the statuses passed in |cookie_list|.
   for (size_t i = 0; i < cookie_list.size(); ++i) {
     const net::CanonicalCookie& cookie = cookie_list[i].cookie;
+    CookieInclusionStatus status = cookie_list[i].status;
     const std::string& cookie_name = cookie.Name();
 
     if (match_type == mojom::CookieMatchType::EQUALS) {
@@ -269,24 +265,12 @@
     }
 
     if (blocked) {
-      result_with_status.push_back(
-          {cookie, CookieInclusionStatus::EXCLUDE_USER_PREFERENCES});
+      status.AddExclusionReason(
+          CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
     } else {
       result.push_back(cookie);
-      // TODO(https://crbug.com/993843): Use the actual status passed in. (For
-      // now it should always be INCLUDE so it doesn't matter.)
-      result_with_status.push_back({cookie, CookieInclusionStatus::INCLUDE});
-
-      // Warn about upcoming deprecations.
-      // TODO(https://crbug.com/977040): Remove once samesite tightening up is
-      // rolled out.
-      CookieInclusionStatus eventual_status =
-          net::cookie_util::CookieWouldBeExcludedDueToSameSite(cookie,
-                                                               net_options);
-      if (eventual_status != CookieInclusionStatus::INCLUDE) {
-        result_with_status.push_back({cookie, eventual_status});
-      }
     }
+    result_with_status.push_back({cookie, status});
   }
 
   if (network_context_client_) {
@@ -324,7 +308,8 @@
     if (network_context_client_) {
       std::vector<net::CookieWithStatus> result_with_status;
       result_with_status.push_back(
-          {cookie, CookieInclusionStatus::EXCLUDE_USER_PREFERENCES});
+          {cookie, CookieInclusionStatus(
+                       CookieInclusionStatus::EXCLUDE_USER_PREFERENCES)});
       network_context_client_->OnCookiesChanged(
           is_service_worker_, process_id_, frame_id_, url, site_for_cookies,
           result_with_status);
@@ -360,32 +345,18 @@
   std::vector<net::CookieWithStatus> notify;
   // TODO(https://crbug.com/977040): Only report pure INCLUDE once samesite
   // tightening up is rolled out.
-  DCHECK_NE(status, CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+  DCHECK(!status.HasExclusionReason(
+      CookieInclusionStatus::EXCLUDE_USER_PREFERENCES));
 
   if (network_context_client_) {
-    switch (status) {
-      case CookieInclusionStatus::INCLUDE: {
-        CookieInclusionStatus eventual_status =
-            net::cookie_util::CookieWouldBeExcludedDueToSameSite(cookie,
-                                                                 net_options);
-        if (eventual_status != CookieInclusionStatus::INCLUDE) {
-          notify.push_back({cookie, eventual_status});
-        }
-        FALLTHROUGH;
-      }
-      case CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-      case CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE:
-        notify.push_back({cookie, status});
-        network_context_client_->OnCookiesChanged(
-            is_service_worker_, process_id_, frame_id_, url, site_for_cookies,
-            std::move(notify));
-        break;
-
-      default:
-        break;
+    if (status.IsInclude() || status.ShouldWarn()) {
+      notify.push_back({cookie, status});
+      network_context_client_->OnCookiesChanged(
+          is_service_worker_, process_id_, frame_id_, url, site_for_cookies,
+          std::move(notify));
     }
   }
-  std::move(user_callback).Run(status == CookieInclusionStatus::INCLUDE);
+  std::move(user_callback).Run(status.IsInclude());
 }
 
 void RestrictedCookieManager::AddChangeListener(
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc
index 3b865bb..5cc987d 100644
--- a/services/network/restricted_cookie_manager_unittest.cc
+++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -205,14 +205,13 @@
                            net::CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&callback)));
     callback.WaitUntilDone();
-    return callback.result() ==
-           net::CanonicalCookie::CookieInclusionStatus::INCLUDE;
+    return callback.result().IsInclude();
   }
 
   // Simplified helper for SetCanonicalCookie.
   //
   // Creates a CanonicalCookie that is not secure, not http-only,
-  // and not restricted to first parties. Crashes if the creation fails.
+  // and has SameSite=None. Crashes if the creation fails.
   void SetSessionCookie(const char* name,
                         const char* value,
                         const char* domain,
@@ -439,26 +438,16 @@
     EXPECT_EQ("cookie-value", cookies[0].Value());
   }
 
-  ASSERT_EQ(2u, recorded_activity().size());
+  ASSERT_EQ(1u, recorded_activity().size());
   EXPECT_EQ(recorded_activity()[0].get, true);
   EXPECT_EQ(recorded_activity()[0].url, "http://example.com/test/");
   EXPECT_EQ(recorded_activity()[0].site_for_cookies, "http://notexample.com/");
   EXPECT_THAT(recorded_activity()[0].cookie,
               net::MatchesCookieLine("cookie-name=cookie-value"));
-  EXPECT_EQ(recorded_activity()[0].status,
-            net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
-
-  // Duplicated for exclusion warning.
-  EXPECT_EQ(recorded_activity()[1].get, true);
-  EXPECT_EQ(recorded_activity()[1].url, "http://example.com/test/");
-  EXPECT_EQ(recorded_activity()[1].site_for_cookies, "http://notexample.com/");
-  EXPECT_THAT(recorded_activity()[1].cookie,
-              net::MatchesCookieLine("cookie-name=cookie-value"));
-  // SetSessionCookie uses net::CookieSameSite::NO_RESTRICTION, but this is an
-  // insecure cookie.
-  EXPECT_EQ(recorded_activity()[1].status,
-            net::CanonicalCookie::CookieInclusionStatus::
-                EXCLUDE_SAMESITE_NONE_INSECURE);
+  EXPECT_TRUE(recorded_activity()[0].status.IsInclude());
+  EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+                WARN_SAMESITE_NONE_INSECURE,
+            recorded_activity()[0].status.warning());
 
   // Disabing getting third-party cookies works correctly.
   cookie_settings_.set_block_third_party_cookies(true);
@@ -473,15 +462,16 @@
     ASSERT_THAT(cookies, testing::SizeIs(0));
   }
 
-  ASSERT_EQ(3u, recorded_activity().size());
-  EXPECT_EQ(recorded_activity()[2].get, true);
-  EXPECT_EQ(recorded_activity()[2].url, "http://example.com/test/");
-  EXPECT_EQ(recorded_activity()[2].site_for_cookies, "http://notexample.com/");
-  EXPECT_THAT(recorded_activity()[2].cookie,
+  ASSERT_EQ(2u, recorded_activity().size());
+  EXPECT_EQ(recorded_activity()[1].get, true);
+  EXPECT_EQ(recorded_activity()[1].url, "http://example.com/test/");
+  EXPECT_EQ(recorded_activity()[1].site_for_cookies, "http://notexample.com/");
+  EXPECT_THAT(recorded_activity()[1].cookie,
               net::MatchesCookieLine("cookie-name=cookie-value"));
-  EXPECT_EQ(
-      recorded_activity()[2].status,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+  EXPECT_TRUE(
+      recorded_activity()[1].status.HasExactlyExclusionReasonsForTesting(
+          {net::CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_USER_PREFERENCES}));
 }
 
 TEST_P(RestrictedCookieManagerTest, GetAllForUrlPolicyWarnActual) {
@@ -511,9 +501,10 @@
   EXPECT_EQ(recorded_activity()[0].site_for_cookies, "http://notexample.com/");
   EXPECT_THAT(recorded_activity()[0].cookie,
               net::MatchesCookieLine("cookie-name=cookie-value"));
-  EXPECT_EQ(recorded_activity()[0].status,
-            net::CanonicalCookie::CookieInclusionStatus::
-                EXCLUDE_SAMESITE_NONE_INSECURE);
+  EXPECT_TRUE(
+      recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
+          {net::CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_NONE_INSECURE}));
 }
 
 TEST_P(RestrictedCookieManagerTest, SetCanonicalCookie) {
@@ -614,21 +605,15 @@
         *cookie, GURL("http://example.com"), GURL("http://notexample.com")));
   }
 
-  ASSERT_EQ(2u, recorded_activity().size());
+  ASSERT_EQ(1u, recorded_activity().size());
   EXPECT_EQ(recorded_activity()[0].get, false);
   EXPECT_EQ(recorded_activity()[0].url, "http://example.com/");
   EXPECT_EQ(recorded_activity()[0].site_for_cookies, "http://notexample.com/");
   EXPECT_THAT(recorded_activity()[0].cookie, net::MatchesCookieLine("A=B"));
-  EXPECT_EQ(recorded_activity()[0].status,
-            net::CanonicalCookie::CookieInclusionStatus::
-                EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
-
-  EXPECT_EQ(recorded_activity()[1].get, false);
-  EXPECT_EQ(recorded_activity()[1].url, "http://example.com/");
-  EXPECT_EQ(recorded_activity()[1].site_for_cookies, "http://notexample.com/");
-  EXPECT_THAT(recorded_activity()[1].cookie, net::MatchesCookieLine("A=B"));
-  EXPECT_EQ(recorded_activity()[1].status,
-            net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  EXPECT_TRUE(recorded_activity()[0].status.IsInclude());
+  EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+            recorded_activity()[0].status.warning());
 
   {
     // Not if third-party cookies are disabled, though.
@@ -640,15 +625,16 @@
         *cookie, GURL("http://example.com"), GURL("http://otherexample.com")));
   }
 
-  ASSERT_EQ(3u, recorded_activity().size());
-  EXPECT_EQ(recorded_activity()[2].get, false);
-  EXPECT_EQ(recorded_activity()[2].url, "http://example.com/");
-  EXPECT_EQ(recorded_activity()[2].site_for_cookies,
+  ASSERT_EQ(2u, recorded_activity().size());
+  EXPECT_EQ(recorded_activity()[1].get, false);
+  EXPECT_EQ(recorded_activity()[1].url, "http://example.com/");
+  EXPECT_EQ(recorded_activity()[1].site_for_cookies,
             "http://otherexample.com/");
-  EXPECT_THAT(recorded_activity()[2].cookie, net::MatchesCookieLine("A2=B2"));
-  EXPECT_EQ(
-      recorded_activity()[2].status,
-      net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+  EXPECT_THAT(recorded_activity()[1].cookie, net::MatchesCookieLine("A2=B2"));
+  EXPECT_TRUE(
+      recorded_activity()[1].status.HasExactlyExclusionReasonsForTesting(
+          {net::CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_USER_PREFERENCES}));
 
   // Read back, in first-party context
   auto options = mojom::CookieManagerGetOptions::New();
@@ -662,13 +648,12 @@
   EXPECT_EQ("A", cookies[0].Name());
   EXPECT_EQ("B", cookies[0].Value());
 
-  ASSERT_EQ(4u, recorded_activity().size());
-  EXPECT_EQ(recorded_activity()[3].get, true);
-  EXPECT_EQ(recorded_activity()[3].url, "http://example.com/test/");
-  EXPECT_EQ(recorded_activity()[3].site_for_cookies, "http://example.com/");
-  EXPECT_THAT(recorded_activity()[3].cookie, net::MatchesCookieLine("A=B"));
-  EXPECT_EQ(recorded_activity()[3].status,
-            net::CanonicalCookie::CookieInclusionStatus::INCLUDE);
+  ASSERT_EQ(3u, recorded_activity().size());
+  EXPECT_EQ(recorded_activity()[2].get, true);
+  EXPECT_EQ(recorded_activity()[2].url, "http://example.com/test/");
+  EXPECT_EQ(recorded_activity()[2].site_for_cookies, "http://example.com/");
+  EXPECT_THAT(recorded_activity()[2].cookie, net::MatchesCookieLine("A=B"));
+  EXPECT_TRUE(recorded_activity()[2].status.IsInclude());
 }
 
 TEST_P(RestrictedCookieManagerTest, SetCanonicalCookiePolicyWarnActual) {
@@ -688,9 +673,10 @@
   EXPECT_EQ(recorded_activity()[0].url, "http://example.com/");
   EXPECT_EQ(recorded_activity()[0].site_for_cookies, "http://notexample.com/");
   EXPECT_THAT(recorded_activity()[0].cookie, net::MatchesCookieLine("A=B"));
-  EXPECT_EQ(recorded_activity()[0].status,
-            net::CanonicalCookie::CookieInclusionStatus::
-                EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
+  EXPECT_TRUE(
+      recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
+          {net::CanonicalCookie::CookieInclusionStatus::
+               EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
 }
 
 TEST_P(RestrictedCookieManagerTest, CookiesEnabledFor) {
diff --git a/services/network/test/test_cookie_manager.cc b/services/network/test/test_cookie_manager.cc
index ac231feb..2de701e 100644
--- a/services/network/test/test_cookie_manager.cc
+++ b/services/network/test/test_cookie_manager.cc
@@ -21,8 +21,8 @@
     const net::CookieOptions& cookie_options,
     SetCanonicalCookieCallback callback) {
   if (callback) {
-    std::move(callback).Run(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+    std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus(
+        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
   }
 }
 
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index f5b203ca..c1ea0bc02 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -311,20 +311,11 @@
 bool ShouldNotifyAboutCookie(
     net::CanonicalCookie::CookieInclusionStatus status) {
   // Notify about cookies actually used, and those blocked by preferences ---
-  // for purposes of cookie UI --- as well those pertaining to the
-  // samesite-by-default and samesite-none-must-be-secure features, in order
-  // to issue a deprecation warning for them.
-  switch (status) {
-    case net::CanonicalCookie::CookieInclusionStatus::INCLUDE:
-    case net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES:
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX:
-    case net::CanonicalCookie::CookieInclusionStatus::
-        EXCLUDE_SAMESITE_NONE_INSECURE:
-      return true;
-    default:
-      return false;
-  }
+  // for purposes of cookie UI --- as well those carrying warnings pertaining to
+  // SameSite features, in order to issue a deprecation warning for them.
+  return status.IsInclude() || status.ShouldWarn() ||
+         status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
+                                       EXCLUDE_USER_PREFERENCES);
 }
 
 }  // namespace
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index a308649..9f8f162 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -3665,8 +3665,8 @@
     EXPECT_EQ(
         "b",
         network_context_client.reported_response_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_context_client.reported_response_cookies()[0].status);
+    EXPECT_TRUE(network_context_client.reported_response_cookies()[0]
+                    .status.IsInclude());
   }
 
   {
@@ -3699,8 +3699,8 @@
     EXPECT_EQ(
         "b",
         network_context_client.reported_request_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_context_client.reported_request_cookies()[0].status);
+    EXPECT_TRUE(network_context_client.reported_request_cookies()[0]
+                    .status.IsInclude());
   }
 }
 
@@ -3748,8 +3748,8 @@
   EXPECT_EQ(
       "true",
       network_context_client.reported_response_cookies()[0].cookie.Value());
-  EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            network_context_client.reported_response_cookies()[0].status);
+  EXPECT_TRUE(
+      network_context_client.reported_response_cookies()[0].status.IsInclude());
 }
 
 TEST_F(URLLoaderTest, CookieReportingAuth) {
@@ -3790,8 +3790,8 @@
     EXPECT_EQ(
         "true",
         network_context_client.reported_response_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_context_client.reported_response_cookies()[0].status);
+    EXPECT_TRUE(network_context_client.reported_response_cookies()[0]
+                    .status.IsInclude());
   }
 }
 
@@ -3835,8 +3835,8 @@
               network_service_client.raw_request_cookies()[0].cookie.Name());
     EXPECT_EQ("b",
               network_service_client.raw_request_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_service_client.raw_request_cookies()[0].status);
+    EXPECT_TRUE(
+        network_service_client.raw_request_cookies()[0].status.IsInclude());
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -3884,8 +3884,10 @@
               network_service_client.raw_request_cookies()[0].cookie.Name());
     EXPECT_EQ("b",
               network_service_client.raw_request_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
-              network_service_client.raw_request_cookies()[0].status);
+    EXPECT_TRUE(network_service_client.raw_request_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_NOT_ON_PATH}));
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -3924,8 +3926,8 @@
               network_service_client.raw_response_cookies()[0].cookie->Name());
     EXPECT_EQ("b",
               network_service_client.raw_response_cookies()[0].cookie->Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(
+        network_service_client.raw_response_cookies()[0].status.IsInclude());
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
 
@@ -3967,9 +3969,10 @@
     network_service_client.WaitUntilRawResponse(1u);
     // On these failures the cookie object is not created
     EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie);
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
-        network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_FAILURE_TO_STORE}));
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -4020,8 +4023,8 @@
               network_service_client.raw_response_cookies()[0].cookie->Name());
     EXPECT_EQ("true",
               network_service_client.raw_response_cookies()[0].cookie->Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(
+        network_service_client.raw_response_cookies()[0].status.IsInclude());
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -4063,8 +4066,10 @@
     // On these failures the cookie object is created but not included.
     EXPECT_TRUE(
         network_service_client.raw_response_cookies()[0].cookie->IsSecure());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-              network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_SECURE_ONLY}));
   }
 }
 
@@ -4106,8 +4111,8 @@
               network_service_client.raw_response_cookies()[0].cookie->Name());
     EXPECT_EQ("true",
               network_service_client.raw_response_cookies()[0].cookie->Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(
+        network_service_client.raw_response_cookies()[0].status.IsInclude());
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -4147,8 +4152,10 @@
     // On these failures the cookie object is created but not included.
     EXPECT_TRUE(
         network_service_client.raw_response_cookies()[0].cookie->IsSecure());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
-              network_service_client.raw_response_cookies()[0].status);
+    EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_SECURE_ONLY}));
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -4221,27 +4228,19 @@
     loader_client.RunUntilComplete();
     EXPECT_EQ(net::OK, loader_client.completion_status().error_code);
 
-    network_context_client.WaitUntilReportedResponseCookies(2u);
+    network_context_client.WaitUntilReportedResponseCookies(1u);
     EXPECT_EQ(
         "a",
         network_context_client.reported_response_cookies()[0].cookie.Name());
     EXPECT_EQ(
         "b",
         network_context_client.reported_response_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_context_client.reported_response_cookies()[0].status);
-
-    // The cookie is reported twice, once for it actual use, and once for the
-    // warning of its upcoming deprecation.
+    EXPECT_TRUE(network_context_client.reported_response_cookies()[0]
+                    .status.IsInclude());
     EXPECT_EQ(
-        "a",
-        network_context_client.reported_response_cookies()[1].cookie.Name());
-    EXPECT_EQ(
-        "b",
-        network_context_client.reported_response_cookies()[1].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::
-                  EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
-              network_context_client.reported_response_cookies()[1].status);
+        net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+            WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+        network_context_client.reported_response_cookies()[0].status.warning());
   }
 
   // Blocked.
@@ -4280,9 +4279,10 @@
     EXPECT_EQ(
         "b",
         network_context_client.reported_response_cookies()[0].cookie.Value());
-    EXPECT_EQ(
-        net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
-        network_context_client.reported_response_cookies()[0].status);
+    EXPECT_TRUE(network_context_client.reported_response_cookies()[0]
+                    .status.HasExactlyExclusionReasonsForTesting(
+                        {net::CanonicalCookie::CookieInclusionStatus::
+                             EXCLUDE_USER_PREFERENCES}));
 
     test_network_delegate()->set_cookie_options(0);
   }
@@ -4319,8 +4319,8 @@
     EXPECT_EQ(
         "e",
         network_context_client.reported_response_cookies()[0].cookie.Value());
-    EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
-              network_context_client.reported_response_cookies()[0].status);
+    EXPECT_TRUE(network_context_client.reported_response_cookies()[0]
+                    .status.IsInclude());
   }
 }
 
diff --git a/services/tracing/public/cpp/trace_event_args_whitelist.cc b/services/tracing/public/cpp/trace_event_args_whitelist.cc
index 41bdcc7..3892869 100644
--- a/services/tracing/public/cpp/trace_event_args_whitelist.cc
+++ b/services/tracing/public/cpp/trace_event_args_whitelist.cc
@@ -26,6 +26,7 @@
 
 const char* const kScopedBlockingCallAllowedArgs[] = {"file_name",
                                                       "function_name", nullptr};
+const char* const kFallbackFontAllowedArgs[] = {"font_name", nullptr};
 const char* const kGetFallbackFontsAllowedArgs[] = {"script", nullptr};
 const char* const kGPUAllowedArgs[] = {nullptr};
 const char* const kInputLatencyAllowedArgs[] = {"data", nullptr};
@@ -72,6 +73,7 @@
     {TRACE_DISABLED_BY_DEFAULT("memory-infra"), "*", kMemoryDumpAllowedArgs},
     {TRACE_DISABLED_BY_DEFAULT("system_stats"), "*", nullptr},
     {TRACE_DISABLED_BY_DEFAULT("v8.gc"), "*", kV8GCAllowedArgs},
+    {"ui", "RenderTextHarfBuzz::FallbackFont", kFallbackFontAllowedArgs},
     {"ui", "RenderTextHarfBuzz::GetFallbackFonts",
      kGetFallbackFontsAllowedArgs},
     {"ui", "UserEvent", nullptr},
diff --git a/testing/libfuzzer/reproducing.md b/testing/libfuzzer/reproducing.md
index 6bf24b62..19ef5efc 100644
--- a/testing/libfuzzer/reproducing.md
+++ b/testing/libfuzzer/reproducing.md
@@ -107,6 +107,32 @@
 Waiting for a crash to occur may take some time (up to 1hr), but if it happens,
 you will be able to test the fix locally and/or somehow debug the issue.
 
+## Minimizing a crash input (optional)
+
+ClusterFuzz does crash input minimization automatically, and a typical crash
+report has two testcases available for downloading:
+
+* An original testcase that has triggered the crash;
+* A minimized testcase that is smaller than the original but triggers the same
+  crash.
+
+If you would like to further minimize a testcase, run the fuzz target with the
+two additional arguments:
+
+* `-minimize_crash=1`
+* `-exact_artifact_path=<output_filename_for_minimized_testcase>`
+
+The full command would be:
+
+```
+out/fuzz/$FUZZER_NAME -minimize_crash=1 -exact_artifact_path=<minimized_testcase_path> $TESTCASE_PATH
+```
+
+This might be useful for large testcases that make it hard to identify a root
+cause of a crash. You can leave the minimization running locally for a while
+(e.g. overnight) for better results.
+
+
 [ClusterFuzz Reproduce Tool]: https://github.com/google/clusterfuzz-tools
 [File a bug]: https://bugs.chromium.org/p/chromium/issues/entry?component=Tools%3EStability%3ElibFuzzer&comment=What%20problem%20are%20you%20seeing
 [here]: getting_started.md#symbolize-stacktrace
diff --git a/third_party/blink/perf_tests/layout/editing_append.html b/third_party/blink/perf_tests/layout/editing_append.html
new file mode 100644
index 0000000..61aeb76
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/editing_append.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+  width: 120ch;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<pre id="container">A</pre>
+<script>
+const kNumberOfWords = 100;
+const kSampleText = (() => {
+  const words = [];
+  for (let i = 1; i <= kNumberOfWords; ++i) {
+    words.push(TextGenerator.createWord(i % 12 + 3));
+    if (i % 10 === 0)
+      words.push('\n');
+  }
+  return words.join(' ');
+})().repeat(1);
+
+const kCount = 10;
+
+const container = document.getElementById('container');
+const editable = container.firstChild;
+
+PerfTestRunner.measureRunsPerSecond({
+  run: function() {
+    for (let i = 0; i < kCount; ++i) {
+      editable.nodeValue = kSampleText;
+      PerfTestRunner.forceLayout();
+      editable.appendData('xyz');
+      PerfTestRunner.forceLayout();
+    }
+  },
+});
+</script>
diff --git a/third_party/blink/perf_tests/layout/editing_append_single_line.html b/third_party/blink/perf_tests/layout/editing_append_single_line.html
new file mode 100644
index 0000000..aedb8abb
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/editing_append_single_line.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+  width: 120ch;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<pre id="container">A</pre>
+<script>
+const kNumberOfWords = 10;
+const kSampleText = (() => {
+  const words = [];
+  for (let i = 1; i <= kNumberOfWords; ++i) {
+    words.push(TextGenerator.createWord(i % 12 + 3));
+  }
+  return words.join(' ');
+})().repeat(1);
+
+const kCount = 10;
+
+const container = document.getElementById('container');
+const editable = container.firstChild;
+
+PerfTestRunner.measureRunsPerSecond({
+  run: function() {
+    for (let i = 0; i < kCount; ++i) {
+      editable.nodeValue = kSampleText;
+      PerfTestRunner.forceLayout();
+      editable.appendData('XYZ');
+      PerfTestRunner.forceLayout();
+    }
+  },
+});
+</script>
diff --git a/third_party/blink/perf_tests/layout/editing_delete.html b/third_party/blink/perf_tests/layout/editing_delete.html
new file mode 100644
index 0000000..ef915f51
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/editing_delete.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+  width: 120ch;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<pre id="container">A</pre>
+<script>
+const kNumberOfWords = 100;
+const kSampleText = (() => {
+  const words = [];
+  for (let i = 1; i <= kNumberOfWords; ++i) {
+    words.push(TextGenerator.createWord(i % 12 + 3));
+    if (i % 10 === 0)
+      words.push('\n');
+  }
+  return words.join(' ');
+})().repeat(1);
+
+const kCount = 10;
+
+const container = document.getElementById('container');
+const editable = container.firstChild;
+
+PerfTestRunner.measureRunsPerSecond({
+  run: function() {
+    for (let i = 0; i < kCount; ++i) {
+      editable.nodeValue = kSampleText;
+      PerfTestRunner.forceLayout();
+      editable.deleteData(10, 20);
+      PerfTestRunner.forceLayout();
+    }
+  },
+});
+</script>
diff --git a/third_party/blink/perf_tests/layout/editing_insert.html b/third_party/blink/perf_tests/layout/editing_insert.html
new file mode 100644
index 0000000..fb365ea5
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/editing_insert.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+  width: 120ch;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<pre id="container">A</pre>
+<script>
+const kNumberOfWords = 100;
+const kSampleText = (() => {
+  const words = [];
+  for (let i = 1; i <= kNumberOfWords; ++i) {
+    words.push(TextGenerator.createWord(i % 12 + 3));
+    if (i % 10 === 0)
+      words.push('\n');
+  }
+  return words.join(' ');
+})().repeat(1);
+
+const kCount = 10;
+
+const container = document.getElementById('container');
+const editable = container.firstChild;
+
+PerfTestRunner.measureRunsPerSecond({
+  run: function() {
+    for (let i = 0; i < kCount; ++i) {
+      editable.nodeValue = kSampleText;
+      PerfTestRunner.forceLayout();
+      editable.insertData(10, 'xyz');
+      PerfTestRunner.forceLayout();
+    }
+  },
+});
+</script>
diff --git a/third_party/blink/perf_tests/layout/editing_prepend.html b/third_party/blink/perf_tests/layout/editing_prepend.html
new file mode 100644
index 0000000..23b0681
--- /dev/null
+++ b/third_party/blink/perf_tests/layout/editing_prepend.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<body>
+<script src="../resources/runner.js"></script>
+<script src="resources/line-layout-perf-test.js"></script>
+<style>
+#container {
+  width: 120ch;
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<pre id="container">A</pre>
+<script>
+const kNumberOfWords = 100;
+const kSampleText = (() => {
+  const words = [];
+  for (let i = 1; i <= kNumberOfWords; ++i) {
+    words.push(TextGenerator.createWord(i % 12 + 3));
+    if (i % 10 === 0)
+      words.push('\n');
+  }
+  return words.join(' ');
+})().repeat(1);
+
+const kCount = 10;
+
+const container = document.getElementById('container');
+const editable = container.firstChild;
+
+PerfTestRunner.measureRunsPerSecond({
+  run: function() {
+    for (let i = 0; i < kCount; ++i) {
+      editable.nodeValue = kSampleText;
+      PerfTestRunner.forceLayout();
+      editable.insertData(0, 'xyz');
+      PerfTestRunner.forceLayout();
+    }
+  },
+});
+</script>
diff --git a/third_party/blink/public/mojom/geolocation/geolocation_service.mojom b/third_party/blink/public/mojom/geolocation/geolocation_service.mojom
index 7cb6f89..fc3a4d1 100644
--- a/third_party/blink/public/mojom/geolocation/geolocation_service.mojom
+++ b/third_party/blink/public/mojom/geolocation/geolocation_service.mojom
@@ -16,6 +16,6 @@
   // request (GRANTED or DENIED).
   // This may not be called a second time until the Geolocation instance has
   // been created.
-  CreateGeolocation(device.mojom.Geolocation& request, bool user_gesture)
+  CreateGeolocation(pending_receiver<device.mojom.Geolocation> receiver, bool user_gesture)
       => (PermissionStatus status);
 };
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 8518334..c0aeb41 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -144,6 +144,7 @@
   BLINK_PLATFORM_EXPORT static void EnablePermissionsAPI(bool);
   BLINK_PLATFORM_EXPORT static void EnablePictureInPicture(bool);
   BLINK_PLATFORM_EXPORT static void EnablePictureInPictureAPI(bool);
+  BLINK_PLATFORM_EXPORT static void EnablePointerLockOptions(bool);
   BLINK_PLATFORM_EXPORT static void EnablePortals(bool);
   BLINK_PLATFORM_EXPORT static void EnablePreciseMemoryInfo(bool);
   BLINK_PLATFORM_EXPORT static void EnablePrintBrowser(bool);
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
index 0a8efd2b..013c8ea0 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
@@ -8,6 +8,7 @@
 from .composition_parts import WithComponent
 from .composition_parts import WithDebugInfo
 from .composition_parts import WithExtendedAttributes
+from .composition_parts import WithOwner
 from .constant import Constant
 from .idl_type import IdlType
 from .ir_map import IRMap
@@ -32,6 +33,7 @@
                      attributes=None,
                      constants=None,
                      operations=None,
+                     stringifier=None,
                      iterable=None,
                      maplike=None,
                      setlike=None,
@@ -46,6 +48,8 @@
             assert attributes is None or isinstance(attributes, (list, tuple))
             assert constants is None or isinstance(constants, (list, tuple))
             assert operations is None or isinstance(operations, (list, tuple))
+            assert stringifier is None or isinstance(stringifier,
+                                                     Stringifier.IR)
             assert iterable is None or isinstance(iterable, Iterable)
             assert maplike is None or isinstance(maplike, Maplike)
             assert setlike is None or isinstance(setlike, Setlike)
@@ -87,6 +91,7 @@
             self.constants = list(constants)
             self.operations = list(operations)
             self.operation_groups = []
+            self.stringifier = stringifier
             self.iterable = iterable
             self.maplike = maplike
             self.setlike = setlike
@@ -123,6 +128,21 @@
                        self._operations),
                 owner=self) for operation_group_ir in ir.operation_groups
         ])
+        self._stringifier = None
+        if ir.stringifier:
+            operations = filter(lambda x: x.is_stringifier, self._operations)
+            assert len(operations) == 1
+            attributes = [None]
+            if ir.stringifier.attribute:
+                attr_id = ir.stringifier.attribute.identifier
+                attributes = filter(lambda x: x.identifier == attr_id,
+                                    self._attributes)
+            assert len(attributes) == 1
+            self._stringifier = Stringifier(
+                ir.stringifier,
+                operation=operations[0],
+                attribute=attributes[0],
+                owner=self)
         self._iterable = ir.iterable
         self._maplike = ir.maplike
         self._setlike = ir.setlike
@@ -201,11 +221,8 @@
 
     @property
     def stringifier(self):
-        """
-        Returns stringifier if it is defined. Returns None otherwise.
-        @return TBD?
-        """
-        assert False, "Not implemented yet."
+        """Returns a Stringifier or None."""
+        return self._stringifier
 
     @property
     def iterable(self):
@@ -228,6 +245,39 @@
         return True
 
 
+class Stringifier(WithOwner, WithDebugInfo):
+    """https://heycam.github.io/webidl/#idl-stringifiers"""
+
+    class IR(WithDebugInfo):
+        def __init__(self, operation=None, attribute=None, debug_info=None):
+            assert isinstance(operation, Operation.IR)
+            assert attribute is None or isinstance(attribute, Attribute.IR)
+
+            WithDebugInfo.__init__(self, debug_info)
+
+            self.operation = operation
+            self.attribute = attribute
+
+    def __init__(self, ir, operation, attribute, owner):
+        assert isinstance(ir, Stringifier.IR)
+        assert isinstance(operation, Operation)
+        assert attribute is None or isinstance(attribute, Attribute)
+
+        WithOwner.__init__(self, owner)
+        WithDebugInfo.__init__(self, ir.debug_info)
+
+        self._operation = operation
+        self._attribute = attribute
+
+    @property
+    def operation(self):
+        return self._operation
+
+    @property
+    def attribute(self):
+        return self._attribute
+
+
 class Iterable(WithDebugInfo):
     """https://heycam.github.io/webidl/#idl-iterable"""
 
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
index 1a265616..e8c2c24 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -23,6 +23,7 @@
 from .interface import Iterable
 from .interface import Maplike
 from .interface import Setlike
+from .interface import Stringifier
 from .literal_constant import LiteralConstant
 from .namespace import Namespace
 from .operation import Operation
@@ -105,11 +106,10 @@
 
         child_nodes = list(node.GetChildren())
         inherited = self._take_inheritance(child_nodes)
+        stringifier = self._take_stringifier(child_nodes)
         iterable = self._take_iterable(child_nodes)
         maplike = self._take_maplike(child_nodes)
         setlike = self._take_setlike(child_nodes)
-        # TODO(peria): Implement stringifier.
-        _ = self._take_stringifier(child_nodes)
         extended_attributes = self._take_extended_attributes(child_nodes)
 
         members = map(self._build_interface_or_namespace_member, child_nodes)
@@ -126,8 +126,12 @@
                 constants.append(member)
             else:
                 assert False
-        # TODO(peria): Implement indexed/named property handlers from
-        # |property_handlers|.
+
+        if stringifier:
+            operations.append(stringifier.operation)
+            if stringifier.attribute:
+                attributes.append(stringifier.attribute)
+        # TODO(peria): Create indexed/named property handlers from |operations|.
 
         return Interface.IR(
             identifier=Identifier(node.GetName()),
@@ -137,6 +141,7 @@
             attributes=attributes,
             constants=constants,
             operations=operations,
+            stringifier=stringifier,
             iterable=iterable,
             maplike=maplike,
             setlike=setlike,
@@ -152,11 +157,13 @@
             component=self._component,
             debug_info=self._build_debug_info(node))
 
-    def _build_interface_or_namespace_member(self, node):
+    def _build_interface_or_namespace_member(
+            self, node, fallback_extended_attributes=None):
         def build_attribute(node):
             child_nodes = list(node.GetChildren())
             idl_type = self._take_type(child_nodes)
-            extended_attributes = self._take_extended_attributes(child_nodes)
+            extended_attributes = self._take_extended_attributes(
+                child_nodes) or fallback_extended_attributes
             assert len(child_nodes) == 0
             return Attribute.IR(
                 identifier=Identifier(node.GetName()),
@@ -171,7 +178,8 @@
         def build_constant(node):
             child_nodes = list(node.GetChildren())
             value = self._take_constant_value(child_nodes)
-            extended_attributes = self._take_extended_attributes(child_nodes)
+            extended_attributes = self._take_extended_attributes(
+                child_nodes) or fallback_extended_attributes
             assert len(child_nodes) == 1, child_nodes[0].GetClass()
             # idl_parser doesn't produce a 'Type' node for the type of a
             # constant, hence we need to skip one level.
@@ -188,7 +196,8 @@
             child_nodes = list(node.GetChildren())
             arguments = self._take_arguments(child_nodes)
             return_type = self._take_type(child_nodes)
-            extended_attributes = self._take_extended_attributes(child_nodes)
+            extended_attributes = self._take_extended_attributes(
+                child_nodes) or fallback_extended_attributes
             assert len(child_nodes) == 0
             return Operation.IR(
                 identifier=Identifier(node.GetName()),
@@ -479,8 +488,42 @@
             debug_info=self._build_debug_info(node))
 
     def _build_stringifier(self, node):
+        # There are three forms of stringifier declaration;
+        #   a. [ExtAttrs] stringifier;
+        #   b. [ExtAttrs] stringifier DOMString foo();
+        #   c. [ExtAttrs] stringifier attribute DOMString bar;
+        # and we apply [ExtAttrs] to an operation in cases a and b, or to an
+        # attribute in case c.
+
         assert node.GetClass() == 'Stringifier'
-        return None
+        child_nodes = node.GetChildren()
+        extended_attributes = self._take_extended_attributes(child_nodes)
+        assert len(child_nodes) <= 1
+
+        member = None
+        if len(child_nodes) == 1:
+            member = self._build_interface_or_namespace_member(
+                child_nodes[0], extended_attributes)
+            extended_attributes = None
+        operation = member if isinstance(member, Operation.IR) else None
+        attribute = member if isinstance(member, Attribute.IR) else None
+
+        if operation is None:
+            return_type = self._idl_type_factory.simple_type(
+                name='DOMString', debug_info=self._build_debug_info(node))
+            operation = Operation.IR(
+                identifier=Identifier(''),
+                arguments=[],
+                return_type=return_type,
+                extended_attributes=extended_attributes,
+                component=self._component,
+                debug_info=self._build_debug_info(node))
+        operation.is_stringifier = True
+
+        return Stringifier.IR(
+            operation=operation,
+            attribute=attribute,
+            debug_info=self._build_debug_info(node))
 
     def _build_type(self,
                     node,
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/operation.py b/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
index 33697df..2d6a332a 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
@@ -43,6 +43,8 @@
                 self, component=component, components=components)
             WithDebugInfo.__init__(self, debug_info)
 
+            self.is_stringifier = False
+
     def __init__(self, ir, owner):
         assert isinstance(ir, Operation.IR)
 
@@ -54,6 +56,12 @@
         WithComponent.__init__(self, components=ir.components)
         WithDebugInfo.__init__(self, ir.debug_info)
 
+        self._is_stringifier = ir.is_stringifier
+
+    @property
+    def is_stringifier(self):
+        return self._is_stringifier
+
 
 class OperationGroup(OverloadGroup, WithCodeGeneratorInfo, WithOwner,
                      WithDebugInfo):
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 0a0de7c..56e3f5d3 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1359,6 +1359,7 @@
     "layout/ng/exclusions/ng_exclusion_space_test.cc",
     "layout/ng/geometry/ng_box_strut_test.cc",
     "layout/ng/geometry/ng_static_position_test.cc",
+    "layout/ng/inline/layout_ng_text_test.cc",
     "layout/ng/inline/ng_baseline_test.cc",
     "layout/ng/inline/ng_caret_position_test.cc",
     "layout/ng/inline/ng_fragment_item_test.cc",
@@ -1457,7 +1458,6 @@
     "page/slot_scoped_traversal_test.cc",
     "page/spatial_navigation_test.cc",
     "page/touch_adjustment_test.cc",
-    "page/validation_message_overlay_delegate_test.cc",
     "page/viewport_test.cc",
     "page/window_features_test.cc",
     "page/zoom_test.cc",
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
index 0d7e023..fea1d799 100644
--- a/third_party/blink/renderer/core/animation/animation.cc
+++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -1420,6 +1420,10 @@
   if (!timeline_)
     return false;
 
+  ExecutionContext* context = GetExecutionContext();
+  if (!context || context->IsContextDestroyed())
+    return false;
+
   ClearOutdated();
   bool idle = CalculateAnimationPlayState() == kIdle;
 
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc
index df586b7a..f7af782 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -43,7 +43,6 @@
 #include "third_party/blink/renderer/core/animation/element_animations.h"
 #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
@@ -340,15 +339,8 @@
     const Element& target_element) {
   FailureReasons reasons = kNoFailure;
 
-  // Both of these checks are required. It is legal to enable the compositor
-  // thread but disable threaded animations, and there are situations where
-  // threaded animations are enabled globally but this particular LocalFrame
-  // does not have a compositor (e.g. for overlays).
-  const Settings& settings = *target_element.GetDocument().GetSettings();
-  if (!settings.GetAcceleratedCompositingEnabled() ||
-      !Platform::Current()->IsThreadedAnimationEnabled()) {
+  if (!Platform::Current()->IsThreadedAnimationEnabled())
     reasons |= kAcceleratedAnimationsDisabled;
-  }
 
   if (const auto* layout_object = target_element.GetLayoutObject()) {
     // We query paint property tree state below to determine whether the
diff --git a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
index e5f11ee..a46ed6c 100644
--- a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
@@ -222,27 +222,23 @@
     ConversionCheckers& conversion_checkers) const {
   DCHECK(state);
   if (auto* list_value = DynamicTo<CSSValueList>(value)) {
-    CSSLengthArray length_array;
+    CSSPrimitiveValue::LengthTypeFlags types;
     for (const CSSValue* item : *list_value) {
       const auto& transform_function = To<CSSFunctionValue>(*item);
       if (transform_function.FunctionType() == CSSValueID::kMatrix ||
           transform_function.FunctionType() == CSSValueID::kMatrix3d) {
-        length_array.type_flags.set(CSSPrimitiveValue::kUnitTypePixels);
+        types.set(CSSPrimitiveValue::kUnitTypePixels);
         continue;
       }
       for (const CSSValue* argument : transform_function) {
         const auto& primitive_value = To<CSSPrimitiveValue>(*argument);
         if (!primitive_value.IsLength())
           continue;
-        if (!primitive_value.AccumulateLengthArray(length_array)) {
-          // TODO(crbug.com/991672): Implement interpolation when CSS comparison
-          // functions min/max are involved.
-          return nullptr;
-        }
+        primitive_value.AccumulateLengthUnitTypes(types);
       }
     }
     std::unique_ptr<InterpolationType::ConversionChecker> length_units_checker =
-        LengthUnitsChecker::MaybeCreate(std::move(length_array), *state);
+        LengthUnitsChecker::MaybeCreate(types, *state);
 
     if (length_units_checker)
       conversion_checkers.push_back(std::move(length_units_checker));
diff --git a/third_party/blink/renderer/core/animation/length_units_checker.h b/third_party/blink/renderer/core/animation/length_units_checker.h
index b04df5a..f687891 100644
--- a/third_party/blink/renderer/core/animation/length_units_checker.h
+++ b/third_party/blink/renderer/core/animation/length_units_checker.h
@@ -18,15 +18,16 @@
 class LengthUnitsChecker : public CSSInterpolationType::CSSConversionChecker {
  public:
   static std::unique_ptr<LengthUnitsChecker> MaybeCreate(
-      CSSLengthArray&& length_array,
+      const CSSPrimitiveValue::LengthTypeFlags& length_types,
       const StyleResolverState& state) {
     bool create = false;
     wtf_size_t last_index = 0;
-    for (wtf_size_t i = 0; i < length_array.values.size(); i++) {
-      if (i == CSSPrimitiveValue::kUnitTypePercentage ||
-          !length_array.type_flags[i])
+    CSSLengthArray length_array;
+    for (wtf_size_t i = 0; i < length_types.size(); ++i) {
+      if (i == CSSPrimitiveValue::kUnitTypePercentage || !length_types[i])
         continue;
       length_array.values[i] = LengthUnit(i, state.CssToLengthConversionData());
+      length_array.type_flags.set(i);
       create = true;
       last_index = i;
     }
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 65a4e890..1411e9e 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -617,6 +617,7 @@
                     "dom/get_root_node_options.idl",
                     "dom/idle_request_options.idl",
                     "dom/mutation_observer_init.idl",
+                    "dom/pointer_lock_options.idl",
                     "dom/shadow_root_init.idl",
                     "dom/events/add_event_listener_options.idl",
                     "dom/events/custom_event_init.idl",
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc
index f9c6abe..2077fe5 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -239,6 +239,11 @@
   return value_->AccumulateLengthArray(length_array, multiplier);
 }
 
+void CSSMathExpressionNumericLiteral::AccumulateLengthUnitTypes(
+    CSSPrimitiveValue::LengthTypeFlags& types) const {
+  value_->AccumulateLengthUnitTypes(types);
+}
+
 bool CSSMathExpressionNumericLiteral::operator==(
     const CSSMathExpressionNode& other) const {
   if (!other.IsNumericLiteral())
@@ -587,6 +592,12 @@
   }
 }
 
+void CSSMathExpressionBinaryOperation::AccumulateLengthUnitTypes(
+    CSSPrimitiveValue::LengthTypeFlags& types) const {
+  left_side_->AccumulateLengthUnitTypes(types);
+  right_side_->AccumulateLengthUnitTypes(types);
+}
+
 bool CSSMathExpressionBinaryOperation::IsComputationallyIndependent() const {
   if (Category() != kCalcLength && Category() != kCalcPercentLength)
     return true;
@@ -842,6 +853,12 @@
   return false;
 }
 
+void CSSMathExpressionVariadicOperation::AccumulateLengthUnitTypes(
+    CSSPrimitiveValue::LengthTypeFlags& types) const {
+  for (const auto& operand : operands_)
+    operand->AccumulateLengthUnitTypes(types);
+}
+
 bool CSSMathExpressionVariadicOperation::IsComputationallyIndependent() const {
   for (const auto& operand : operands_) {
     if (!operand->IsComputationallyIndependent())
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h
index 276a364..d9ce4f6 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.h
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -89,6 +89,8 @@
   virtual double ComputeLengthPx(const CSSToLengthConversionData&) const = 0;
   virtual bool AccumulateLengthArray(CSSLengthArray&,
                                      double multiplier) const = 0;
+  virtual void AccumulateLengthUnitTypes(
+      CSSPrimitiveValue::LengthTypeFlags& types) const = 0;
   virtual scoped_refptr<const CalculationExpressionNode>
   ToCalculationExpression(const CSSToLengthConversionData&) const = 0;
 
@@ -167,6 +169,8 @@
       const CSSToLengthConversionData& conversion_data) const final;
   bool AccumulateLengthArray(CSSLengthArray& length_array,
                              double multiplier) const final;
+  void AccumulateLengthUnitTypes(
+      CSSPrimitiveValue::LengthTypeFlags& types) const final;
   bool IsComputationallyIndependent() const final;
   bool operator==(const CSSMathExpressionNode& other) const final;
   CSSPrimitiveValue::UnitType ResolvedUnitType() const final;
@@ -220,6 +224,8 @@
       const CSSToLengthConversionData& conversion_data) const final;
   bool AccumulateLengthArray(CSSLengthArray& length_array,
                              double multiplier) const final;
+  void AccumulateLengthUnitTypes(
+      CSSPrimitiveValue::LengthTypeFlags& types) const final;
   bool IsComputationallyIndependent() const final;
   String CustomCSSText() const final;
   bool operator==(const CSSMathExpressionNode& exp) const final;
@@ -285,6 +291,8 @@
       const CSSToLengthConversionData& conversion_data) const final;
   bool AccumulateLengthArray(CSSLengthArray& length_array,
                              double multiplier) const final;
+  void AccumulateLengthUnitTypes(
+      CSSPrimitiveValue::LengthTypeFlags& types) const final;
   base::Optional<double> ComputeValueInCanonicalUnit() const final;
   bool IsComputationallyIndependent() const final;
   bool operator==(const CSSMathExpressionNode& other) const final;
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.h b/third_party/blink/renderer/core/css/css_math_function_value.h
index 6dc2182..4436f74 100644
--- a/third_party/blink/renderer/core/css/css_math_function_value.h
+++ b/third_party/blink/renderer/core/css/css_math_function_value.h
@@ -80,6 +80,10 @@
   Length ConvertToLength(
       const CSSToLengthConversionData& conversion_data) const;
 
+  void AccumulateLengthUnitTypes(LengthTypeFlags& types) const {
+    expression_->AccumulateLengthUnitTypes(types);
+  }
+
   String CustomCSSText() const;
   bool Equals(const CSSMathFunctionValue& other) const;
 
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
index 23a2661..368f079 100644
--- a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
+++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
@@ -126,6 +126,16 @@
   return true;
 }
 
+void CSSNumericLiteralValue::AccumulateLengthUnitTypes(
+    LengthTypeFlags& types) const {
+  if (!IsLength())
+    return;
+  LengthUnitType length_type;
+  bool conversion_success = UnitTypeToLengthUnitType(GetType(), length_type);
+  DCHECK(conversion_success);
+  types.set(length_type);
+}
+
 bool CSSNumericLiteralValue::IsComputationallyIndependent() const {
   if (!IsLength())
     return true;
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.h b/third_party/blink/renderer/core/css/css_numeric_literal_value.h
index 72f1c03c..64087343 100644
--- a/third_party/blink/renderer/core/css/css_numeric_literal_value.h
+++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.h
@@ -58,6 +58,7 @@
       const CSSToLengthConversionData& conversion_data) const;
   bool AccumulateLengthArray(CSSLengthArray& length_array,
                              double multiplier) const;
+  void AccumulateLengthUnitTypes(LengthTypeFlags& types) const;
 
   String CustomCSSText() const;
   bool Equals(const CSSNumericLiteralValue& other) const;
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.cc b/third_party/blink/renderer/core/css/css_primitive_value.cc
index e5258143..d74e9081 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value.cc
+++ b/third_party/blink/renderer/core/css/css_primitive_value.cc
@@ -289,6 +289,13 @@
                                                                  multiplier);
 }
 
+void CSSPrimitiveValue::AccumulateLengthUnitTypes(
+    LengthTypeFlags& types) const {
+  if (IsCalculated())
+    return To<CSSMathFunctionValue>(this)->AccumulateLengthUnitTypes(types);
+  To<CSSNumericLiteralValue>(this)->AccumulateLengthUnitTypes(types);
+}
+
 double CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(
     UnitType unit_type) {
   double factor = 1.0;
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h
index 83d0a71..b1eb9251 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value.h
+++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -130,18 +130,22 @@
     kLengthUnitTypeCount,
   };
 
+  using LengthTypeFlags = std::bitset<kLengthUnitTypeCount>;
   struct CSSLengthArray {
     CSSLengthArray() : values(kLengthUnitTypeCount) {
     }
 
     Vector<double, CSSPrimitiveValue::kLengthUnitTypeCount> values;
-    std::bitset<kLengthUnitTypeCount> type_flags;
+    LengthTypeFlags type_flags;
   };
 
   // Returns false if the value cannot be represented as a length array, which
   // happens when comparisons are involved (e.g., max(10px, 10%)).
   bool AccumulateLengthArray(CSSLengthArray&, double multiplier = 1) const;
 
+  // Returns all types of length units involved in this value.
+  void AccumulateLengthUnitTypes(LengthTypeFlags& types) const;
+
   enum UnitCategory {
     kUNumber,
     kUPercent,
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index f002357..d9356374 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -299,6 +299,7 @@
 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
+#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -3213,6 +3214,11 @@
   // attached to a frame. Otherwise ContextLifecycleObserver::contextDestroyed
   // wouldn't be fired.
   network_state_observer_ = MakeGarbageCollected<NetworkStateObserver>(*this);
+
+  // Check for frame_ so we only attach execution contexts with its own
+  // scheduler.
+  if (frame_)
+    GetAgent()->AttachExecutionContext(this);
 }
 
 void Document::Shutdown() {
@@ -3362,6 +3368,11 @@
   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
   CHECK(!View()->IsAttached());
 
+  // Check for frame_ so we only detach execution contexts with its own
+  // scheduler.
+  if (frame_)
+    GetAgent()->DetachExecutionContext(this);
+
   // TODO(haraken): Call contextDestroyed() before we start any disruptive
   // operations.
   // TODO(haraken): Currently we call notifyContextDestroyed() only in
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc
index 42d1ef9..6c78c39 100644
--- a/third_party/blink/renderer/core/dom/document_test.cc
+++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -43,10 +43,12 @@
 #include "third_party/blink/renderer/core/css/media_query_list_listener.h"
 #include "third_party/blink/renderer/core/css/media_query_matcher.h"
 #include "third_party/blink/renderer/core/dom/document_fragment.h"
+#include "third_party/blink/renderer/core/dom/dom_implementation.h"
 #include "third_party/blink/renderer/core/dom/node_with_index.h"
 #include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
 #include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/execution_context/agent.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
@@ -62,6 +64,7 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
+#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
@@ -821,6 +824,18 @@
   EXPECT_EQ(1, observer.CountContextDestroyedCalled());
 }
 
+TEST_F(DocumentTest, AttachExecutionContext) {
+  EXPECT_TRUE(
+      GetDocument().GetAgent()->event_loop()->IsSchedulerAttachedForTest(
+          GetDocument().GetScheduler()));
+  Document* doc = GetDocument().implementation().createHTMLDocument("foo");
+  EXPECT_EQ(GetDocument().GetAgent(), doc->GetAgent());
+  GetDocument().Shutdown();
+  EXPECT_FALSE(doc->GetAgent()->event_loop()->IsSchedulerAttachedForTest(
+      doc->GetScheduler()));
+  doc->Shutdown();
+}
+
 // This tests that meta-theme-color can be found correctly
 TEST_F(DocumentTest, ThemeColor) {
   {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 304f933d..23bf3e9 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -77,6 +77,7 @@
 #include "third_party/blink/renderer/core/dom/mutation_record.h"
 #include "third_party/blink/renderer/core/dom/named_node_map.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/dom/pointer_lock_options.h"
 #include "third_party/blink/renderer/core/dom/presentation_attribute_style.h"
 #include "third_party/blink/renderer/core/dom/pseudo_element.h"
 #include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
@@ -5121,9 +5122,17 @@
 }
 
 void Element::requestPointerLock() {
-  if (GetDocument().GetPage())
+  if (GetDocument().GetPage()) {
     GetDocument().GetPage()->GetPointerLockController().RequestPointerLock(
         this);
+  }
+}
+
+void Element::requestPointerLock(const PointerLockOptions* options) {
+  if (GetDocument().GetPage()) {
+    GetDocument().GetPage()->GetPointerLockController().RequestPointerLock(
+        this, options);
+  }
 }
 
 SpellcheckAttributeState Element::GetSpellcheckAttributeState() const {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index f259259..8953beb 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -71,6 +71,7 @@
 class MutableCSSPropertyValueSet;
 class NamedNodeMap;
 class PaintLayerScrollableArea;
+class PointerLockOptions;
 class PseudoElement;
 class PseudoStyleRequest;
 class ResizeObservation;
@@ -846,6 +847,7 @@
   void SetIsInTopLayer(bool);
 
   void requestPointerLock();
+  void requestPointerLock(const PointerLockOptions*);
 
   bool IsSpellCheckingEnabled() const;
 
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl
index 2c5bdde..17550330 100644
--- a/third_party/blink/renderer/core/dom/element.idl
+++ b/third_party/blink/renderer/core/dom/element.idl
@@ -94,6 +94,7 @@
     // Pointer Lock
     // https://w3c.github.io/pointerlock/#extensions-to-the-element-interface
     [MeasureAs=ElementRequestPointerLock] void requestPointerLock();
+    [RuntimeEnabled=PointerLockOptions] void requestPointerLock(PointerLockOptions options);
 
     // CSSOM View Module
     // https://drafts.csswg.org/cssom-view/#extension-to-the-element-interface
diff --git a/third_party/blink/renderer/core/dom/pointer_lock_options.idl b/third_party/blink/renderer/core/dom/pointer_lock_options.idl
new file mode 100644
index 0000000..e166732
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/pointer_lock_options.idl
@@ -0,0 +1,3 @@
+dictionary PointerLockOptions {
+    [RuntimeEnabled=PointerLockOptions]boolean unadjustedMovement = false;
+};
diff --git a/third_party/blink/renderer/core/execution_context/agent.cc b/third_party/blink/renderer/core/execution_context/agent.cc
index 7f72d76..d4684a5 100644
--- a/third_party/blink/renderer/core/execution_context/agent.cc
+++ b/third_party/blink/renderer/core/execution_context/agent.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/execution_context/agent.h"
 
 #include "third_party/blink/renderer/core/dom/mutation_observer.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
 
 namespace blink {
@@ -20,4 +21,12 @@
 
 void Agent::Trace(Visitor* visitor) {}
 
+void Agent::AttachExecutionContext(ExecutionContext* execution_context) {
+  event_loop_->AttachScheduler(execution_context->GetScheduler());
+}
+
+void Agent::DetachExecutionContext(ExecutionContext* execution_context) {
+  event_loop_->DetachScheduler(execution_context->GetScheduler());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/execution_context/agent.h b/third_party/blink/renderer/core/execution_context/agent.h
index 81a6e6e..360f841a 100644
--- a/third_party/blink/renderer/core/execution_context/agent.h
+++ b/third_party/blink/renderer/core/execution_context/agent.h
@@ -19,6 +19,8 @@
 class EventLoop;
 }
 
+class ExecutionContext;
+
 // Corresponding spec concept is:
 // https://html.spec.whatwg.org/C#integration-with-the-javascript-agent-formalism
 //
@@ -51,6 +53,9 @@
 
   virtual void Trace(blink::Visitor*);
 
+  void AttachExecutionContext(ExecutionContext*);
+  void DetachExecutionContext(ExecutionContext*);
+
   const base::UnguessableToken& cluster_id() const { return cluster_id_; }
 
  private:
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 0a53f32..3679ed503 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -42,6 +42,8 @@
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
 #include "gin/wrappable.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
 #include "third_party/blink/public/common/manifest/web_display_mode.h"
@@ -4388,11 +4390,12 @@
 // the ShowUnhandledTapUIIfNeeded notification.
 class MockUnhandledTapNotifierImpl : public mojom::blink::UnhandledTapNotifier {
  public:
-  MockUnhandledTapNotifierImpl() : binding_(this) {}
+  MockUnhandledTapNotifierImpl() = default;
   ~MockUnhandledTapNotifierImpl() override = default;
 
   void Bind(mojo::ScopedMessagePipeHandle handle) {
-    binding_.Bind(mojom::blink::UnhandledTapNotifierRequest(std::move(handle)));
+    receiver_.Bind(mojo::PendingReceiver<mojom::blink::UnhandledTapNotifier>(
+        std::move(handle)));
   }
 
   void ShowUnhandledTapUIIfNeeded(
@@ -4412,7 +4415,7 @@
     tapped_position_ = IntPoint();
     element_text_run_length_ = 0;
     font_size_ = 0;
-    binding_.Close();
+    receiver_.reset();
   }
 
  private:
@@ -4421,7 +4424,7 @@
   int element_text_run_length_ = 0;
   int font_size_ = 0;
 
-  mojo::Binding<mojom::blink::UnhandledTapNotifier> binding_;
+  mojo::Receiver<mojom::blink::UnhandledTapNotifier> receiver_{this};
 };
 
 // A Test Fixture for testing ShowUnhandledTapUIIfNeeded usages.
diff --git a/third_party/blink/renderer/core/frame/frame_overlay.cc b/third_party/blink/renderer/core/frame/frame_overlay.cc
index 784ec82..b80d012 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay.cc
+++ b/third_party/blink/renderer/core/frame/frame_overlay.cc
@@ -109,11 +109,6 @@
   Paint(context);
 }
 
-void FrameOverlay::ServiceScriptedAnimations(
-    base::TimeTicks monotonic_frame_begin_time) {
-  delegate_->ServiceScriptedAnimations(monotonic_frame_begin_time);
-}
-
 String FrameOverlay::DebugName(const GraphicsLayer*) const {
   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
   return "Frame Overlay Content Layer";
diff --git a/third_party/blink/renderer/core/frame/frame_overlay.h b/third_party/blink/renderer/core/frame/frame_overlay.h
index ae0df9d..267312c 100644
--- a/third_party/blink/renderer/core/frame/frame_overlay.h
+++ b/third_party/blink/renderer/core/frame/frame_overlay.h
@@ -56,10 +56,6 @@
     // For CompositeAfterPaint. Invalidates composited layers managed by the
     // delegate if any.
     virtual void Invalidate() {}
-
-    // Service any animations managed by the delegate.
-    virtual void ServiceScriptedAnimations(
-        base::TimeTicks monotonic_frame_begin_time) {}
   };
 
   FrameOverlay(LocalFrame*, std::unique_ptr<FrameOverlay::Delegate>);
@@ -80,9 +76,6 @@
   const Delegate* GetDelegate() const { return delegate_.get(); }
   const LocalFrame& Frame() const { return *frame_; }
 
-  // Services any animations that the overlay may be managing.
-  void ServiceScriptedAnimations(base::TimeTicks monotonic_frame_begin_time);
-
   // DisplayItemClient methods.
   String DebugName() const final { return "FrameOverlay"; }
   IntRect VisualRect() const override;
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 14ca8c4e5..ed6afc8 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -245,8 +245,10 @@
         mime_type, init,
         init.GetFrame() ? init.GetFrame()->InViewSourceMode() : false);
     if (document->IsPluginDocument() &&
-        document->IsSandboxed(WebSandboxFlags::kPlugins))
+        document->IsSandboxed(WebSandboxFlags::kPlugins)) {
+      // document->Shutdown();
       document = MakeGarbageCollected<SinkDocument>(init);
+    }
   }
 
   return document;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 37bdb65..8757eb61 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -129,12 +129,12 @@
 }
 
 void HTMLCanvasElement::Dispose() {
-  if (PlaceholderFrame()) {
-    ReleasePlaceholderFrame();
+  if (OffscreenCanvasFrame()) {
+    ReleaseOffscreenCanvasFrame();
   }
   // It's possible that the placeholder frame has been disposed but its ID still
   // exists. Make sure that it gets unregistered here
-  UnregisterPlaceholder();
+  UnregisterPlaceholderCanvas();
 
   // We need to drop frame dispatcher, to prevent mojo calls from completing.
   frame_dispatcher_ = nullptr;
@@ -191,7 +191,7 @@
 
 void HTMLCanvasElement::setHeight(unsigned value,
                                   ExceptionState& exception_state) {
-  if (IsPlaceholderRegistered()) {
+  if (IsOffscreenCanvasRegistered()) {
     exception_state.ThrowDOMException(
         DOMExceptionCode::kInvalidStateError,
         "Cannot resize canvas after call to transferControlToOffscreen().");
@@ -202,7 +202,7 @@
 
 void HTMLCanvasElement::setWidth(unsigned value,
                                  ExceptionState& exception_state) {
-  if (IsPlaceholderRegistered()) {
+  if (IsOffscreenCanvasRegistered()) {
     exception_state.ThrowDOMException(
         DOMExceptionCode::kInvalidStateError,
         "Cannot resize canvas after call to transferControlToOffscreen().");
@@ -598,7 +598,7 @@
 }
 
 bool HTMLCanvasElement::PaintsIntoCanvasBuffer() const {
-  if (PlaceholderFrame())
+  if (OffscreenCanvasFrame())
     return false;
   DCHECK(context_);
   if (!context_->IsComposited())
@@ -695,7 +695,7 @@
 
   // FIXME: crbug.com/438240; there is a bug with the new CSS blending and
   // compositing feature.
-  if (!context_ && !PlaceholderFrame())
+  if (!context_ && !OffscreenCanvasFrame())
     return;
 
   if (Is3d())
@@ -713,10 +713,10 @@
       return;
   }
 
-  if (PlaceholderFrame()) {
+  if (OffscreenCanvasFrame()) {
     DCHECK(GetDocument().Printing());
     scoped_refptr<StaticBitmapImage> image_for_printing =
-        PlaceholderFrame()->Bitmap()->MakeUnaccelerated();
+        OffscreenCanvasFrame()->Bitmap()->MakeUnaccelerated();
     context.DrawImage(image_for_printing.get(), Image::kSyncDecode,
                       FloatRect(PixelSnappedIntRect(r)));
     return;
@@ -812,9 +812,9 @@
     return nullptr;
 
   scoped_refptr<StaticBitmapImage> image_bitmap = nullptr;
-  if (PlaceholderFrame()) {  // Offscreen Canvas
-    DCHECK(PlaceholderFrame()->OriginClean());
-    image_bitmap = PlaceholderFrame()->Bitmap();
+  if (OffscreenCanvasFrame()) {  // Offscreen Canvas
+    DCHECK(OffscreenCanvasFrame()->OriginClean());
+    image_bitmap = OffscreenCanvasFrame()->Bitmap();
   } else if (Is3d()) {  // WebGL or WebGL2 canvas
     if (context_->CreationAttributes().premultiplied_alpha) {
       context_->PaintRenderingResultsToCanvas(source_buffer);
@@ -985,8 +985,8 @@
       GetDocument().GetSettings()->GetDisableReadingFromCanvas()) {
     return false;
   }
-  if (PlaceholderFrame())
-    return PlaceholderFrame()->OriginClean();
+  if (OffscreenCanvasFrame())
+    return OffscreenCanvasFrame()->OriginClean();
   return origin_clean_;
 }
 
@@ -1193,9 +1193,9 @@
     return nullptr;
   }
 
-  if (PlaceholderFrame()) {
+  if (OffscreenCanvasFrame()) {
     *status = kNormalSourceImageStatus;
-    return PlaceholderFrame()->Bitmap();
+    return OffscreenCanvasFrame()->Bitmap();
   }
 
   if (!context_) {
@@ -1249,8 +1249,8 @@
       return FloatSize(image->width(), image->height());
     return FloatSize(0, 0);
   }
-  if (PlaceholderFrame())
-    return FloatSize(PlaceholderFrame()->Size());
+  if (OffscreenCanvasFrame())
+    return FloatSize(OffscreenCanvasFrame()->Size());
   return FloatSize(width(), height());
 }
 
@@ -1269,15 +1269,15 @@
       script_state, ImageBitmap::Create(this, crop_rect, options));
 }
 
-void HTMLCanvasElement::SetPlaceholderFrame(
+void HTMLCanvasElement::SetOffscreenCanvasFrame(
     scoped_refptr<CanvasResource> image,
     base::WeakPtr<CanvasResourceDispatcher> dispatcher,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     unsigned resource_id) {
-  OffscreenCanvasPlaceholder::SetPlaceholderFrame(
+  OffscreenCanvasPlaceholder::SetOffscreenCanvasFrame(
       std::move(image), std::move(dispatcher), std::move(task_runner),
       resource_id);
-  SetSize(PlaceholderFrame()->Size());
+  SetSize(OffscreenCanvasFrame()->Size());
   NotifyListenersCanvasChanged();
 }
 
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
index 1da326e..dcbd750 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -236,10 +236,10 @@
                                   const ImageBitmapOptions*) override;
 
   // OffscreenCanvasPlaceholder implementation.
-  void SetPlaceholderFrame(scoped_refptr<CanvasResource>,
-                           base::WeakPtr<CanvasResourceDispatcher>,
-                           scoped_refptr<base::SingleThreadTaskRunner>,
-                           unsigned resource_id) override;
+  void SetOffscreenCanvasFrame(scoped_refptr<CanvasResource>,
+                               base::WeakPtr<CanvasResourceDispatcher>,
+                               scoped_refptr<base::SingleThreadTaskRunner>,
+                               unsigned resource_id) override;
   void Trace(Visitor*) override;
 
   void SetResourceProviderForTesting(std::unique_ptr<CanvasResourceProvider>,
diff --git a/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc b/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
index b9b75086..1464bb6 100644
--- a/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
+++ b/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc
@@ -366,15 +366,17 @@
       MakeGarbageCollected<DateTimeEditElement, Document&,
                            DateTimeEditElement::EditControlOwner&>(document,
                                                                    *this));
-  GetElement().UpdateView();
-  container->AppendChild(
-      MakeGarbageCollected<ClearButtonElement, Document&,
-                           ClearButtonElement::ClearButtonOwner&>(document,
+  if (!RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+    GetElement().UpdateView();
+    container->AppendChild(
+        MakeGarbageCollected<ClearButtonElement, Document&,
+                             ClearButtonElement::ClearButtonOwner&>(document,
+                                                                    *this));
+    container->AppendChild(
+        MakeGarbageCollected<SpinButtonElement, Document&,
+                             SpinButtonElement::SpinButtonOwner&>(document,
                                                                   *this));
-  container->AppendChild(
-      MakeGarbageCollected<SpinButtonElement, Document&,
-                           SpinButtonElement::SpinButtonOwner&>(document,
-                                                                *this));
+  }
 
   if (LayoutTheme::GetTheme().SupportsCalendarPicker(
           input_type_->FormControlType()))
@@ -446,7 +448,8 @@
 
 void MultipleFieldsTemporalInputTypeView::DisabledAttributeChanged() {
   EventQueueScope scope;
-  GetSpinButtonElement()->ReleaseCapture();
+  if (SpinButtonElement* spin_button = GetSpinButtonElement())
+    spin_button->ReleaseCapture();
   if (DateTimeEditElement* edit = GetDateTimeEditElement())
     edit->DisabledStateChanged();
 }
@@ -492,7 +495,8 @@
 
 void MultipleFieldsTemporalInputTypeView::ReadonlyAttributeChanged() {
   EventQueueScope scope;
-  GetSpinButtonElement()->ReleaseCapture();
+  if (SpinButtonElement* spin_button = GetSpinButtonElement())
+    spin_button->ReleaseCapture();
   if (DateTimeEditElement* edit = GetDateTimeEditElement())
     edit->ReadOnlyStateChanged();
 }
diff --git a/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc b/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
index 6f3673eb..661eb8c 100644
--- a/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
+++ b/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc
@@ -57,8 +57,12 @@
   DCHECK(!chooser_);
 }
 
-LayoutObject* PickerIndicatorElement::CreateLayoutObject(const ComputedStyle&,
-                                                         LegacyLayout) {
+LayoutObject* PickerIndicatorElement::CreateLayoutObject(
+    const ComputedStyle& style,
+    LegacyLayout legacy) {
+  if (RuntimeEnabledFeatures::FormControlsRefreshEnabled())
+    return HTMLDivElement::CreateLayoutObject(style, legacy);
+
   return new LayoutDetailsMarker(this);
 }
 
diff --git a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc b/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
index 36639b3..0ac94b4 100644
--- a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
@@ -910,6 +910,7 @@
         ScrollOffset(0, kLoadingDistanceThreshold + kViewportHeight),
         kProgrammaticScroll);
     Compositor().BeginFrame();
+    test::RunPendingTasks();
     full_resource.Complete(ReadTestImage());
     ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
         KURL("https://example.com/image.png")));
@@ -1352,6 +1353,7 @@
                             LazyLoadAutomaticImagesTest::kViewportHeight),
         kProgrammaticScroll);
     Compositor().BeginFrame();
+    test::RunPendingTasks();
     auto_image.Complete(ReadTestImage());
     lazy_image.Complete(ReadTestImage());
     test::RunPendingTasks();
@@ -1379,6 +1381,7 @@
     SimSubresourceRequest lazy_image("https://example.com/image_lazy.png",
                                      "image/png");
     Compositor().BeginFrame();
+    test::RunPendingTasks();
     lazy_image.Complete(ReadTestImage());
     test::RunPendingTasks();
     histogram_tester.ExpectTotalCount(
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css
index ff69135..8e5ce9e 100644
--- a/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -106,6 +106,42 @@
   border-radius: 1px 0px 0px 1px;
 }
 
+input[type="date" i]::-webkit-calendar-picker-indicator,
+input[type="datetime-local" i]::-webkit-calendar-picker-indicator,
+input[type="month" i]::-webkit-calendar-picker-indicator,
+input[type="week" i]::-webkit-calendar-picker-indicator {
+  background-image: -webkit-image-set(url(images/calendar_icon.svg) 1x);
+  background-origin: content-box;
+  background-repeat: no-repeat;
+  background-size: contain;
+  height: 1.2em;
+  opacity: 1;
+  outline: none;
+  padding-bottom: 2px;
+  padding-inline-start: 27px;
+  padding-inline-end: 3px;
+  padding-top: 2px;
+  width: 1.2em;
+}
+
+input::-webkit-calendar-picker-indicator:hover {
+  background-color: initial;
+}
+
+/* Remove focus ring from fields and use highlight color */
+input::-webkit-datetime-edit-ampm-field:focus,
+input::-webkit-datetime-edit-day-field:focus,
+input::-webkit-datetime-edit-hour-field:focus,
+input::-webkit-datetime-edit-millisecond-field:focus,
+input::-webkit-datetime-edit-minute-field:focus,
+input::-webkit-datetime-edit-month-field:focus,
+input::-webkit-datetime-edit-second-field:focus,
+input::-webkit-datetime-edit-week-field:focus,
+input::-webkit-datetime-edit-year-field:focus {
+  background-color: rgba(0, 120, 212, 0.4);
+  outline: none;
+}
+
 /* -internal-list-box is how we specify select[multiple] */
 /* select[multiple] is an exception to the prohibition on sizes here
    because it is one of the few controls with borders that grow on zoom
@@ -156,4 +192,4 @@
 select:-internal-list-box option:checked:disabled:hover {
   background-color: #f0f0f0 !important;
   color: #c5c5c5 !important;
-}
\ No newline at end of file
+}
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css
index dc1447c6..c04c938 100644
--- a/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -10,6 +10,7 @@
 
 @media forced-colors {
   body {
+    background-color: Window;
     color: WindowText;
   }
 
diff --git a/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg b/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg
new file mode 100644
index 0000000..f66e72eb
--- /dev/null
+++ b/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6 6H7V7H6V6ZM9 12H10V13H9V12ZM12 6H13V7H12V6ZM9 6H10V7H9V6ZM6 8H7V9H6V8ZM3 8H4V9H3V8ZM12 8H13V9H12V8ZM9 8H10V9H9V8ZM6 10H7V11H6V10ZM3 10H4V11H3V10ZM12 10H13V11H12V10ZM9 10H10V11H9V10ZM6 12H7V13H6V12ZM3 12H4V13H3V12ZM16 1V15H0V1H3V0H4V1H12V0H13V1H16ZM1 2V4H15V2H13V3H12V2H4V3H3V2H1ZM15 14V5H1V14H15Z" fill="#101010"/>
+</svg>
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index 4b3a760..ebf43f8 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/input/gesture_manager.h"
 
 #include "build/build_config.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/public_buildflags.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -468,9 +469,9 @@
   // The Browser may do additional trigger-filtering.
   if (should_trigger) {
     // Start setting up the Mojo interface connection.
-    mojom::blink::UnhandledTapNotifierPtr provider;
+    mojo::Remote<mojom::blink::UnhandledTapNotifier> provider;
     frame_->Client()->GetInterfaceProvider()->GetInterface(
-        mojo::MakeRequest(&provider));
+        provider.BindNewPipeAndPassReceiver());
 
     // Extract text run-length.
     int text_run_length = 0;
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index d560acf..d32c3fc 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1323,6 +1323,7 @@
   void SetNeedsCollectInlines();
   void SetChildNeedsCollectInlines();
   void ClearNeedsCollectInlines() { SetNeedsCollectInlines(false); }
+  void SetNeedsCollectInlines(bool b) { bitfields_.SetNeedsCollectInlines(b); }
 
   void MarkContainerChainForLayout(bool schedule_relayout = true,
                                    SubtreeLayoutScope* = nullptr);
@@ -3242,7 +3243,6 @@
   void SetNeedsSimplifiedNormalFlowLayout(bool b) {
     bitfields_.SetNeedsSimplifiedNormalFlowLayout(b);
   }
-  void SetNeedsCollectInlines(bool b) { bitfields_.SetNeedsCollectInlines(b); }
 
  private:
   friend class LineLayoutItem;
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index a65d8cd38..48de6cf2 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1662,6 +1662,16 @@
     }
   }
 
+  if (NGInlineNode::SetTextWithOffset(this, text, offset, len)) {
+    DCHECK(!NeedsCollectInlines());
+    // Prevent |TextDidChange()| to propagate |NeedsCollectInlines|
+    SetNeedsCollectInlines(true);
+    TextDidChange();
+    valid_ng_items_ = true;
+    ClearNeedsCollectInlines();
+    return;
+  }
+
   unsigned old_len = TextLength();
   unsigned new_len = text->length();
   int delta = new_len - old_len;
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h
index 5683ebd..4282e640 100644
--- a/third_party/blink/renderer/core/layout/layout_text.h
+++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -192,6 +192,7 @@
   void SetTextWithOffset(scoped_refptr<StringImpl>,
                          unsigned offset,
                          unsigned len);
+  void SetTextInternal(scoped_refptr<StringImpl>);
 
   virtual void TransformText();
 
@@ -322,11 +323,12 @@
   void SetHasBidiControlInlineItems() { has_bidi_control_items_ = true; }
   void ClearHasBidiControlInlineItems() { has_bidi_control_items_ = false; }
 
- protected:
   virtual const base::span<NGInlineItem>* GetNGInlineItems() const {
     return nullptr;
   }
   virtual base::span<NGInlineItem>* GetNGInlineItems() { return nullptr; }
+
+ protected:
   void WillBeDestroyed() override;
 
   void StyleWillChange(StyleDifference, const ComputedStyle&) final {}
@@ -334,7 +336,6 @@
 
   void InLayoutNGInlineFormattingContextWillChange(bool) final;
 
-  void SetTextInternal(scoped_refptr<StringImpl>);
   virtual void TextDidChange();
 
   virtual InlineTextBox* CreateTextBox(int start,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc
new file mode 100644
index 0000000..092c03e
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc
@@ -0,0 +1,258 @@
+// 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/layout/ng/inline/layout_ng_text.h"
+
+#include <sstream>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+
+class LayoutNGTextTest : public PageTestBase {
+ protected:
+  std::string GetItemsAsString(const LayoutText& layout_text) {
+    if (layout_text.NeedsCollectInlines())
+      return "LayoutText has NeedsCollectInlines";
+    if (!layout_text.HasValidInlineItems())
+      return "No valid inline items in LayoutText";
+    const LayoutBlockFlow& block_flow = *layout_text.ContainingNGBlockFlow();
+    if (block_flow.NeedsCollectInlines())
+      return "LayoutBlockFlow has NeedsCollectInlines";
+    const NGInlineNodeData& data = *block_flow.GetNGInlineNodeData();
+    std::ostringstream stream;
+    for (const NGInlineItem& item : data.items) {
+      if (item.Type() != NGInlineItem::kText)
+        continue;
+      if (item.GetLayoutObject() == layout_text)
+        stream << "*";
+      stream << "{'"
+             << data.text_content.Substring(item.StartOffset(), item.Length())
+                    .Utf8()
+             << "'";
+      if (item.TextShapeResult()) {
+        stream << ", ShapeResult=" << item.TextShapeResult()->StartIndex()
+               << "+" << item.TextShapeResult()->NumCharacters();
+      }
+      stream << "}" << std::endl;
+    }
+    return stream.str();
+  }
+};
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetAppendCollapseWhiteSpace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>abc </p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.appendData("XYZ");
+
+  EXPECT_EQ("*{'abc XYZ', ShapeResult=0+7}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetAppend) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZ<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.appendData("xyz");
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XYZxyz', ShapeResult=3+6}\n"
+      "{'def', ShapeResult=9+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetDelete) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>xXYZyz<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.deleteData(1, 3, ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'xyz', ShapeResult=3+3}\n"
+      "{'def', ShapeResult=6+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteCollapseWhiteSpace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>ab  XY  cd</p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.deleteData(4, 2, ASSERT_NO_EXCEPTION);  // remove "XY"
+
+  EXPECT_EQ("*{'ab cd', ShapeResult=0+5}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteCollapseWhiteSpaceEnd) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>a bc</p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.deleteData(2, 2, ASSERT_NO_EXCEPTION);  // remove "bc"
+
+  EXPECT_EQ("*{'a', ShapeResult=0+1}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetInsert) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZ<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.insertData(1, "xyz", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XxyzYZ', ShapeResult=3+6}\n"
+      "{'def', ShapeResult=9+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetInsertAfterSpace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>ab cd</p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.insertData(3, " XYZ ", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ("*{'ab XYZ cd', ShapeResult=0+9}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetInserBeforetSpace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>ab cd</p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.insertData(2, " XYZ ", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ("*{'ab XYZ cd', ShapeResult=0+9}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetNoRelocation) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZ<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  // Note: |CharacterData::setData()| is implementation of Node::setNodeValue()
+  // for |CharacterData|.
+  text.setData("xyz");
+
+  EXPECT_EQ("LayoutText has NeedsCollectInlines",
+            GetItemsAsString(*text.GetLayoutObject()))
+      << "There are no optimization for setData()";
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetPrepend) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZ<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.insertData(1, "xyz", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XxyzYZ', ShapeResult=3+6}\n"
+      "{'def', ShapeResult=9+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetReplace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZW<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.replaceData(1, 2, "yz", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XyzW', ShapeResult=3+4}\n"
+      "{'def', ShapeResult=7+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetReplaceCollapseWhiteSpace) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<p id=target>ab  XY  cd</p>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild());
+  text.replaceData(4, 2, " ", ASSERT_NO_EXCEPTION);  // replace "XY" to " "
+
+  EXPECT_EQ("*{'ab cd', ShapeResult=0+5}\n",
+            GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetReplaceToExtend) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZW<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.replaceData(1, 2, "xyz", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XxyzW', ShapeResult=3+5}\n"
+      "{'def', ShapeResult=8+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetReplaceToShrink) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZW<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  text.replaceData(1, 2, "y", ASSERT_NO_EXCEPTION);
+
+  EXPECT_EQ(
+      "{'abc', ShapeResult=0+3}\n"
+      "*{'XyW', ShapeResult=3+3}\n"
+      "{'def', ShapeResult=6+3}\n",
+      GetItemsAsString(*text.GetLayoutObject()));
+}
+
+TEST_F(LayoutNGTextTest, SetTextWithOffsetToEmpty) {
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
+
+  SetBodyInnerHTML(u"<pre id=target><a>abc</a>XYZ<b>def</b></pre>");
+  Text& text = To<Text>(*GetElementById("target")->firstChild()->nextSibling());
+  // Note: |CharacterData::setData()| is implementation of Node::setNodeValue()
+  // for |CharacterData|.
+  // Note: |setData()| detaches layout object from |Text| node since
+  // |Text::TextLayoutObjectIsNeeded()| returns false for empty text.
+  text.setData("");
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_EQ(nullptr, text.GetLayoutObject());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
index 81be1dd..28d5f0c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -250,6 +250,7 @@
   unsigned is_symbol_marker_ : 1;
   unsigned is_generated_for_line_break_ : 1;
   friend class NGInlineNode;
+  friend class NGInlineNodeDataEditor;
 };
 
 inline void NGInlineItem::AssertOffset(unsigned offset) const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index c450c42..748a6fb5 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -131,6 +131,114 @@
   bool has_floating_or_out_of_flow_positioned_ = false;
 };
 
+// Wrapper over ShapeText that re-uses existing shape results for items that
+// haven't changed.
+class ReusingTextShaper final {
+ public:
+  ReusingTextShaper(NGInlineItemsData* data,
+                    const Vector<NGInlineItem>* reusable_items)
+      : data_(*data),
+        reusable_items_(reusable_items),
+        shaper_(data->text_content) {}
+
+  scoped_refptr<ShapeResult> Shape(const NGInlineItem& start_item,
+                                   unsigned end_offset) {
+    const unsigned start_offset = start_item.StartOffset();
+    DCHECK_LT(start_offset, end_offset);
+
+    if (!reusable_items_)
+      return Reshape(start_item, start_offset, end_offset);
+
+    // TODO(yosin): We should support segment text
+    if (data_.segments)
+      return Reshape(start_item, start_offset, end_offset);
+
+    const Vector<const ShapeResult*> reusable_shape_results =
+        CollectReusableShapeResults(start_offset, end_offset);
+    if (reusable_shape_results.IsEmpty())
+      return Reshape(start_item, start_offset, end_offset);
+
+    const scoped_refptr<ShapeResult> shape_result =
+        ShapeResult::CreateEmpty(*reusable_shape_results.front());
+    unsigned offset = start_offset;
+    for (const ShapeResult* reusable_shape_result : reusable_shape_results) {
+      DCHECK_LE(offset, reusable_shape_result->StartIndex());
+      if (offset < reusable_shape_result->StartIndex()) {
+        AppendShapeResult(
+            *Reshape(start_item, offset, reusable_shape_result->StartIndex()),
+            shape_result.get());
+        offset = shape_result->EndIndex();
+      }
+      DCHECK_EQ(offset, reusable_shape_result->StartIndex());
+      DCHECK(shape_result->NumCharacters() == 0 ||
+             shape_result->EndIndex() == offset);
+      reusable_shape_result->CopyRange(
+          offset, std::min(reusable_shape_result->EndIndex(), end_offset),
+          shape_result.get());
+      offset = shape_result->EndIndex();
+      if (offset == end_offset)
+        return shape_result;
+    }
+    DCHECK_LT(offset, end_offset);
+    AppendShapeResult(*Reshape(start_item, offset, end_offset),
+                      shape_result.get());
+    return shape_result;
+  }
+
+ private:
+  void AppendShapeResult(const ShapeResult& shape_result, ShapeResult* target) {
+    DCHECK(target->NumCharacters() == 0 ||
+           target->EndIndex() == shape_result.StartIndex());
+    shape_result.CopyRange(shape_result.StartIndex(), shape_result.EndIndex(),
+                           target);
+  }
+
+  Vector<const ShapeResult*> CollectReusableShapeResults(unsigned start_offset,
+                                                         unsigned end_offset) {
+    DCHECK_LT(start_offset, end_offset);
+    Vector<const ShapeResult*> shape_results;
+    if (!reusable_items_)
+      return shape_results;
+    for (const NGInlineItem *item = std::lower_bound(
+             reusable_items_->begin(), reusable_items_->end(), start_offset,
+             [](const NGInlineItem&item, unsigned offset) {
+               return item.EndOffset() <= offset;
+             });
+         item != reusable_items_->end(); ++item) {
+      DCHECK_LE(start_offset, item->StartOffset());
+      if (end_offset <= item->StartOffset())
+        break;
+      if (item->EndOffset() < start_offset)
+        continue;
+      if (!item->TextShapeResult())
+        continue;
+      shape_results.push_back(item->TextShapeResult());
+    }
+    return shape_results;
+  }
+
+  scoped_refptr<ShapeResult> Reshape(const NGInlineItem& start_item,
+                                     unsigned start_offset,
+                                     unsigned end_offset) {
+    DCHECK_LT(start_offset, end_offset);
+    const TextDirection direction = start_item.Direction();
+    const Font& font = start_item.Style()->GetFont();
+    if (data_.segments) {
+      return data_.segments->ShapeText(&shaper_, &font, direction, start_offset,
+                                       end_offset,
+                                       &start_item - data_.items.begin());
+    }
+    RunSegmenter::RunSegmenterRange range =
+        start_item.CreateRunSegmenterRange();
+    range.end = end_offset;
+    return shaper_.Shape(&font, direction, start_offset, end_offset, range);
+  }
+
+  NGInlineItemsData& data_;
+  const Vector<NGInlineItem>* const reusable_items_;
+  HarfBuzzShaper shaper_;
+};
+
 // The function is templated to indicate the purpose of collected inlines:
 // - With EmptyOffsetMappingBuilder: updating layout;
 // - With NGOffsetMappingBuilder: building offset mapping on clean layout.
@@ -366,7 +474,7 @@
   DCHECK(data);
   CollectInlines(data, previous_data.get(), dirty_lines);
   SegmentText(data);
-  ShapeText(data, previous_data.get());
+  ShapeText(data, &previous_data->text_content);
   ShapeTextForFirstLineIfNeeded(data);
   AssociateItemsWithInlines(data);
   DCHECK_EQ(data, MutableData());
@@ -384,6 +492,288 @@
 #endif
 }
 
+// Building |NGInlineNodeData| for |LayoutText::SetTextWithOffset()| with
+// reusing data.
+class NGInlineNodeDataEditor final {
+  STACK_ALLOCATED();
+
+ public:
+  explicit NGInlineNodeDataEditor(const LayoutText& layout_text)
+      : block_flow_(layout_text.ContainingNGBlockFlow()),
+        layout_text_(layout_text) {
+    DCHECK(layout_text_.HasValidInlineItems());
+  }
+
+  LayoutBlockFlow* GetLayoutBlockFlow() const { return block_flow_; }
+
+  // Note: We can't use |Position| for |layout_text_.GetNode()| because |Text|
+  // node is already changed.
+  NGInlineNodeData* Prepare(unsigned offset, unsigned length) {
+    if (!block_flow_ || block_flow_->NeedsCollectInlines() ||
+        block_flow_->NeedsLayout() ||
+        block_flow_->GetDocument().NeedsLayoutTreeUpdate() ||
+        !block_flow_->GetNGInlineNodeData() ||
+        block_flow_->GetNGInlineNodeData()->text_content.IsNull())
+      return nullptr;
+
+    // Because of current text content has secured text, e.g. whole text is
+    // "***", all characters including collapsed white spaces are marker, and
+    // new text is original text, we can't reuse shape result.
+    if (layout_text_.StyleRef().TextSecurity() != ETextSecurity::kNone)
+      return nullptr;
+
+    // Note: We should compute offset mapping before calling
+    // |LayoutBlockFlow::TakeNGInlineNodeData()|
+    const NGOffsetMapping* const offset_mapping =
+        NGInlineNode::GetOffsetMapping(block_flow_);
+    DCHECK(offset_mapping);
+    const auto units =
+        offset_mapping->GetMappingUnitsForLayoutObject(layout_text_);
+    start_offset_ = ConvertDOMOffsetToTextContent(units, offset);
+    end_offset_ = ConvertDOMOffsetToTextContent(units, offset + length);
+    DCHECK_LE(start_offset_, end_offset_);
+    data_.reset(block_flow_->TakeNGInlineNodeData());
+    return data_.get();
+  }
+
+  void Run() {
+    const NGInlineNodeData& new_data = *block_flow_->GetNGInlineNodeData();
+    const int diff =
+        new_data.text_content.length() - data_->text_content.length();
+    // |inserted_text_length| can be negative when white space is collapsed
+    // after text change.
+    //  * "ab cd ef" => delete "cd" => "ab ef"
+    //    We should not reuse " " before "ef"
+    //  * "a bc" => delete "bc" => "a"
+    //    There are no spaces after "a".
+    const int inserted_text_length = end_offset_ - start_offset_ + diff;
+    DCHECK_GE(inserted_text_length, -1);
+    const unsigned start_offset =
+        inserted_text_length < 0 && end_offset_ == data_->text_content.length()
+            ? start_offset_ - 1
+            : start_offset_;
+    const unsigned end_offset =
+        inserted_text_length < 0 && start_offset_ == start_offset
+            ? end_offset_ + 1
+            : end_offset_;
+    DCHECK_LE(end_offset, data_->text_content.length());
+    DCHECK_LE(start_offset, end_offset);
+#if DCHECK_IS_ON()
+    if (start_offset_ != start_offset) {
+      DCHECK_EQ(data_->text_content[start_offset], ' ');
+      DCHECK_EQ(end_offset, end_offset_);
+    }
+    if (end_offset_ != end_offset) {
+      DCHECK_EQ(data_->text_content[end_offset_], ' ');
+      DCHECK_EQ(start_offset, start_offset_);
+    }
+#endif
+    Vector<NGInlineItem> items;
+    // +3 for before and after replaced text.
+    items.ReserveInitialCapacity(data_->items.size() + 3);
+
+    // Copy items before replaced range
+    auto* it = data_->items.begin();
+    while (it->end_offset_ < start_offset ||
+           it->layout_object_ != layout_text_) {
+      DCHECK(it != data_->items.end());
+      items.push_back(*it);
+      ++it;
+    }
+
+    DCHECK_EQ(it->layout_object_, layout_text_);
+
+    // Copy part of item before replaced range.
+    if (it->start_offset_ < start_offset)
+      items.push_back(CopyItemBefore(*it, start_offset));
+
+    // Skip items in replaced range.
+    while (it->end_offset_ < end_offset)
+      ++it;
+    DCHECK_EQ(it->layout_object_, layout_text_);
+
+    // Inserted text
+    if (inserted_text_length > 0) {
+      const unsigned inserted_start_offset =
+          items.IsEmpty() ? 0 : items.back().end_offset_;
+      const unsigned inserted_end_offset =
+          inserted_start_offset + inserted_text_length;
+      items.push_back(NGInlineItem(*it, inserted_start_offset,
+                                   inserted_end_offset, nullptr));
+    }
+
+    // Copy part of item after replaced range.
+    if (end_offset < it->end_offset_) {
+      items.push_back(CopyItemAfter(*it, end_offset));
+      ShiftItem(&items.back(), diff);
+    }
+
+    // Copy items after replaced range
+    ++it;
+    while (it != data_->items.end()) {
+      DCHECK_NE(it->layout_object_, layout_text_);
+      DCHECK_LE(end_offset, it->start_offset_);
+      items.push_back(*it);
+      ShiftItem(&items.back(), diff);
+      ++it;
+    }
+
+    VerifyItems(items);
+    data_->items = std::move(items);
+    data_->text_content = new_data.text_content;
+  }
+
+ private:
+  static unsigned AdjustOffset(unsigned offset, int delta) {
+    if (delta > 0)
+      return offset + delta;
+    return offset - (-delta);
+  }
+
+  static unsigned ConvertDOMOffsetToTextContent(
+      base::span<const NGOffsetMappingUnit> units,
+      unsigned offset) {
+    auto it = std::find_if(
+        units.begin(), units.end(), [offset](const NGOffsetMappingUnit& unit) {
+          return unit.DOMStart() <= offset && offset <= unit.DOMEnd();
+        });
+    DCHECK(it != units.end());
+    return it->ConvertDOMOffsetToTextContent(offset);
+  }
+
+  // Returns copy of |item| after |start_offset| (inclusive).
+  NGInlineItem CopyItemAfter(const NGInlineItem& item,
+                             unsigned start_offset) const {
+    DCHECK_LE(item.start_offset_, start_offset);
+    DCHECK_LT(start_offset, item.end_offset_);
+    DCHECK_EQ(item.layout_object_, layout_text_);
+    if (item.start_offset_ == start_offset)
+      return item;
+    const unsigned end_offset = item.end_offset_;
+    if (!item.shape_result_)
+      return NGInlineItem(item, start_offset, end_offset, nullptr);
+    // TODO(yosin): We should handle |shape_result| doesn't have safe-to-break
+    // at start and end, because of |ShapeText()| splits |ShapeResult| ignoring
+    // safe-to-break offset.
+    item.shape_result_->EnsurePositionData();
+    const unsigned safe_start_offset =
+        item.shape_result_->CachedNextSafeToBreakOffset(start_offset);
+    if (end_offset == safe_start_offset)
+      return NGInlineItem(item, start_offset, end_offset, nullptr);
+    return NGInlineItem(
+        item, start_offset, end_offset,
+        item.shape_result_->SubRange(safe_start_offset, end_offset));
+  }
+
+  // Returns copy of |item| before |end_offset| (exclusive).
+  NGInlineItem CopyItemBefore(const NGInlineItem& item,
+                              unsigned end_offset) const {
+    DCHECK_LT(item.start_offset_, end_offset);
+    DCHECK_LE(end_offset, item.end_offset_);
+    DCHECK_EQ(item.layout_object_, layout_text_);
+    if (item.end_offset_ == end_offset)
+      return item;
+    const unsigned start_offset = item.start_offset_;
+    if (!item.shape_result_)
+      return NGInlineItem(item, start_offset, end_offset, nullptr);
+    // TODO(yosin): We should handle |shape_result| doesn't have safe-to-break
+    // at start and end, because of |ShapeText()| splits |ShapeResult| ignoring
+    // safe-to-break offset.
+    item.shape_result_->EnsurePositionData();
+    const unsigned safe_end_offset =
+        item.shape_result_->CachedPreviousSafeToBreakOffset(end_offset);
+    if (start_offset == safe_end_offset)
+      return NGInlineItem(item, start_offset, end_offset, nullptr);
+    return NGInlineItem(
+        item, start_offset, end_offset,
+        item.shape_result_->SubRange(start_offset, safe_end_offset));
+  }
+
+  static void ShiftItem(NGInlineItem* item, int delta) {
+    if (delta == 0)
+      return;
+    item->start_offset_ = AdjustOffset(item->start_offset_, delta);
+    item->end_offset_ = AdjustOffset(item->end_offset_, delta);
+    if (!item->shape_result_)
+      return;
+    item->shape_result_ =
+        item->shape_result_->CopyAdjustedOffset(item->start_offset_);
+  }
+
+  void VerifyItems(const Vector<NGInlineItem>& items) const {
+#if DCHECK_IS_ON()
+    unsigned last_offset = items.front().start_offset_;
+    for (const NGInlineItem& item : items) {
+      DCHECK_LE(item.start_offset_, item.end_offset_);
+      DCHECK_EQ(last_offset, item.start_offset_);
+      last_offset = item.end_offset_;
+      if (!item.shape_result_ || item.layout_object_ != layout_text_)
+        continue;
+      DCHECK_LT(item.start_offset_, item.end_offset_);
+      if (item.shape_result_->StartIndex() == item.start_offset_) {
+        DCHECK_LE(item.shape_result_->EndIndex(), item.end_offset_);
+      } else {
+        DCHECK_LE(item.start_offset_, item.shape_result_->StartIndex());
+        DCHECK_EQ(item.end_offset_, item.shape_result_->EndIndex());
+      }
+    }
+    DCHECK_EQ(last_offset,
+              block_flow_->GetNGInlineNodeData()->text_content.length());
+#endif
+  }
+
+  std::unique_ptr<NGInlineNodeData> data_;
+  LayoutBlockFlow* const block_flow_;
+  const LayoutText& layout_text_;
+  unsigned start_offset_ = 0;
+  unsigned end_offset_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(NGInlineNodeDataEditor);
+};
+
+// static
+bool NGInlineNode::SetTextWithOffset(LayoutText* layout_text,
+                                     scoped_refptr<StringImpl> new_text_in,
+                                     unsigned offset,
+                                     unsigned length) {
+  if (!layout_text->HasValidInlineItems() ||
+      !layout_text->IsInLayoutNGInlineFormattingContext())
+    return false;
+  const String old_text = layout_text->GetText();
+  if (offset == 0 && length == old_text.length()) {
+    // We'll run collect inline items since whole text of |layout_text| is
+    // changed.
+    return false;
+  }
+
+  NGInlineNodeDataEditor editor(*layout_text);
+  NGInlineNodeData* const previous_data = editor.Prepare(offset, length);
+  if (!previous_data)
+    return false;
+
+  String new_text(std::move(new_text_in));
+  layout_text->StyleRef().ApplyTextTransform(&new_text,
+                                             layout_text->PreviousCharacter());
+  layout_text->SetTextInternal(new_text.Impl());
+
+  NGInlineNode node(editor.GetLayoutBlockFlow());
+  NGInlineNodeData* data = node.MutableData();
+  data->items.ReserveCapacity(previous_data->items.size());
+  NGInlineItemsBuilder builder(&data->items, nullptr);
+  // TODO(yosin): We should reuse before/after |layout_text| during collecting
+  // inline items.
+  layout_text->ClearInlineItems();
+  CollectInlinesInternal(node.GetLayoutBlockFlow(), &builder, previous_data);
+  data->text_content = builder.ToString();
+  // Relocates |ShapeResult| in |previous_data| after |offset|+|length|
+  editor.Run();
+  node.SegmentText(data);
+  node.ShapeText(data, &previous_data->text_content, &previous_data->items);
+  node.ShapeTextForFirstLineIfNeeded(data);
+  node.AssociateItemsWithInlines(data);
+  return true;
+}
+
 const NGInlineNodeData& NGInlineNode::EnsureData() {
   PrepareLayoutIfNeeded();
   return Data();
@@ -625,14 +1015,13 @@
 }
 
 void NGInlineNode::ShapeText(NGInlineItemsData* data,
-                             NGInlineItemsData* previous_data) {
+                             const String* previous_text,
+                             const Vector<NGInlineItem>* previous_items) {
   const String& text_content = data->text_content;
   Vector<NGInlineItem>* items = &data->items;
-  const String* previous_text =
-      previous_data ? &previous_data->text_content : nullptr;
 
   // Provide full context of the entire node to the shaper.
-  HarfBuzzShaper shaper(text_content);
+  ReusingTextShaper shaper(data, previous_items);
   ShapeResultSpacing<String> spacing(text_content);
 
   DCHECK(!data->segments ||
@@ -717,43 +1106,35 @@
     }
 
     // Results may only be reused if all items in the range remain valid.
-    bool has_valid_shape_results = true;
-    for (unsigned item_index = index; item_index < end_index; item_index++) {
-      if (NeedsShaping((*items)[item_index])) {
-        has_valid_shape_results = false;
-        break;
+    if (previous_text) {
+      bool has_valid_shape_results = true;
+      for (unsigned item_index = index; item_index < end_index; item_index++) {
+        if (NeedsShaping((*items)[item_index])) {
+          has_valid_shape_results = false;
+          break;
+        }
+      }
+
+      // When shaping across multiple items checking whether the individual
+      // items has valid shape results isn't sufficient as items may have been
+      // re-ordered or removed.
+      // TODO(layout-dev): It would probably be faster to check for removed or
+      // moved items but for now comparing the string itself will do.
+      unsigned text_start = start_item.StartOffset();
+      DCHECK_GE(end_offset, text_start);
+      unsigned text_length = end_offset - text_start;
+      if (has_valid_shape_results && previous_text &&
+          end_offset <= previous_text->length() &&
+          StringView(text_content, text_start, text_length) ==
+              StringView(*previous_text, text_start, text_length)) {
+        index = end_index;
+        continue;
       }
     }
 
-    // When shaping across multiple items checking whether the individual
-    // items has valid shape results isn't sufficient as items may have been
-    // re-ordered or removed.
-    // TODO(layout-dev): It would probably be faster to check for removed or
-    // moved items but for now comparing the string itself will do.
-    unsigned text_start = start_item.StartOffset();
-    DCHECK_GE(end_offset, text_start);
-    unsigned text_length = end_offset - text_start;
-    if (has_valid_shape_results && previous_text &&
-        end_offset <= previous_text->length() &&
-        StringView(text_content, text_start, text_length) ==
-            StringView(*previous_text, text_start, text_length)) {
-      index = end_index;
-      continue;
-    }
-
     // Shape each item with the full context of the entire node.
-    scoped_refptr<ShapeResult> shape_result;
-    if (!data->segments) {
-      RunSegmenter::RunSegmenterRange range =
-          start_item.CreateRunSegmenterRange();
-      range.end = end_offset;
-      shape_result = shaper.Shape(&font, direction, start_item.StartOffset(),
-                                  end_offset, range);
-    } else {
-      shape_result = data->segments->ShapeText(
-          &shaper, &font, direction, start_item.StartOffset(), end_offset,
-          &start_item - items->begin());
-    }
+    scoped_refptr<ShapeResult> shape_result =
+        shaper.Shape(start_item, end_offset);
 
     if (UNLIKELY(spacing.SetSpacing(font.GetFontDescription())))
       shape_result->ApplySpacing(spacing);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
index e9f6f10..5fe5cfb2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -78,6 +78,15 @@
   static void ClearAssociatedFragments(const NGPhysicalFragment& fragment,
                                        const NGBlockBreakToken* break_token);
 
+  // Returns true if we don't need to collect inline items after replacing
+  // |layout_text| after deleting replacing subtext from |offset| to |length|
+  // |new_text| is new text of |layout_text|.
+  // This is optimized version of |PrepareLayout()|.
+  static bool SetTextWithOffset(LayoutText* layout_text,
+                                scoped_refptr<StringImpl> new_text,
+                                unsigned offset,
+                                unsigned length);
+
   // Returns the DOM to text content offset mapping of this block. If it is not
   // computed before, compute and store it in NGInlineNodeData.
   // This funciton must be called with clean layout.
@@ -124,7 +133,8 @@
   void SegmentFontOrientation(NGInlineNodeData*);
   void SegmentBidiRuns(NGInlineNodeData*);
   void ShapeText(NGInlineItemsData*,
-                 NGInlineItemsData* previous_data = nullptr);
+                 const String* previous_text = nullptr,
+                 const Vector<NGInlineItem>* previous_items = nullptr);
   void ShapeTextForFirstLineIfNeeded(NGInlineNodeData*);
   void AssociateItemsWithInlines(NGInlineNodeData*);
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index c0efd50c6..2d316800 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -945,15 +945,6 @@
   EXPECT_TRUE(layout_block_flow_->NeedsCollectInlines());
 }
 
-TEST_F(NGInlineNodeTest, InvalidateSetTextWithOffset) {
-  SetupHtml("t", "<div id=t>before</div>");
-  EXPECT_FALSE(layout_block_flow_->NeedsCollectInlines());
-
-  LayoutText* text = ToLayoutText(layout_block_flow_->FirstChild());
-  text->SetTextWithOffset(String("after").Impl(), 1, 4);
-  EXPECT_TRUE(layout_block_flow_->NeedsCollectInlines());
-}
-
 TEST_F(NGInlineNodeTest, InvalidateAddAbsolute) {
   SetupHtml("t",
             "<style>span { position: absolute; }</style>"
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 22f4eca..90c74f3a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -471,7 +471,10 @@
   // Negative margins can make the position negative, but the inline size is
   // always positive or 0.
   LayoutUnit available_width = AvailableWidth();
-  DCHECK_EQ(position_, line_info->ComputeWidth());
+
+  // Text measurement is done using floats which may introduce small rounding
+  // errors for near-saturated values.
+  DCHECK_EQ(position_.Round(), line_info->ComputeWidth().Round());
 
   line_info->SetWidth(available_width, position_);
   line_info->SetBfcOffset(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
index 2c37e28c..aeaa0c8 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -84,7 +84,7 @@
     PhysicalSize container_physical_size) const {
   WritingMode container_writing_mode = container_style->GetWritingMode();
   TextDirection container_direction = container_style->Direction();
-  PhysicalRect overflow({}, Size());
+  PhysicalRect overflow;
   for (const auto& child : Children()) {
     PhysicalRect child_scroll_overflow =
         child->ScrollableOverflowForPropagation(container);
@@ -116,6 +116,15 @@
     }
     overflow.Unite(child_scroll_overflow);
   }
+
+  // Make sure we include the inline-size of the line-box in the overflow.
+  PhysicalRect rect;
+  if (IsHorizontalWritingMode(container_writing_mode))
+    rect.size.width = Size().width;
+  else
+    rect.size.height = Size().height;
+  overflow.UniteEvenIfEmpty(rect);
+
   return overflow;
 }
 
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index b998529..f96fe9f 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -668,7 +668,18 @@
       params.SetLazyImageAutoReload();
     }
 
-    new_image_content = ImageResourceContent::Fetch(params, document.Fetcher());
+    if (lazy_image_load_state_ == LazyImageLoadState::kDeferred &&
+        was_fully_deferred_) {
+      // TODO(rajendrant): Remove this temporary workaround of creating a 1x1
+      // placeholder to fix an intersection observer issue not firing with
+      // certain styles (https://crbug.com/992765). Instead
+      // NoImageResourceToLoad() should be skipped when the image is deferred.
+      // https://crbug.com/999209
+      new_image_content = ImageResourceContent::CreateLazyImagePlaceholder();
+    } else {
+      new_image_content =
+          ImageResourceContent::Fetch(params, document.Fetcher());
+    }
 
     // If this load is starting while navigating away, treat it as an auditing
     // keepalive request, and don't report its results back to the element.
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
index e03c5fa..89d765f 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -119,6 +119,14 @@
   return content;
 }
 
+ImageResourceContent* ImageResourceContent::CreateLazyImagePlaceholder() {
+  ImageResourceContent* content = MakeGarbageCollected<ImageResourceContent>();
+  content->content_status_ = ResourceStatus::kCached;
+  content->image_ =
+      PlaceholderImage::CreateForLazyImages(content, IntSize(1, 1));
+  return content;
+}
+
 ImageResourceContent* ImageResourceContent::Fetch(FetchParameters& params,
                                                   ResourceFetcher* fetcher) {
   // TODO(hiroshige): Remove direct references to ImageResource by making
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
index 7c91be4..c022783b 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h
+++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -56,6 +56,8 @@
   // Creates ImageResourceContent from an already loaded image.
   static ImageResourceContent* CreateLoaded(scoped_refptr<blink::Image>);
 
+  static ImageResourceContent* CreateLazyImagePlaceholder();
+
   static ImageResourceContent* Fetch(FetchParameters&, ResourceFetcher*);
 
   explicit ImageResourceContent(scoped_refptr<blink::Image> = nullptr);
diff --git a/third_party/blink/renderer/core/page/DEPS b/third_party/blink/renderer/core/page/DEPS
deleted file mode 100644
index a45c5f7..0000000
--- a/third_party/blink/renderer/core/page/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  # For validation_message_overlay_delegate_test.cc
-  "+base/strings/utf_string_conversions.h",
-]
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.cc b/third_party/blink/renderer/core/page/page_widget_delegate.cc
index 69e229f..8ae5bde1 100644
--- a/third_party/blink/renderer/core/page/page_widget_delegate.cc
+++ b/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -40,7 +40,6 @@
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 #include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/validation_message_client.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
@@ -49,11 +48,6 @@
                                  base::TimeTicks monotonic_frame_begin_time) {
   page.GetAutoscrollController().Animate();
   page.Animator().ServiceScriptedAnimations(monotonic_frame_begin_time);
-  // The ValidationMessage overlay manages its own internal Page that isn't
-  // hooked up the normal BeginMainFrame flow, so we manually tick its
-  // animations here.
-  page.GetValidationMessageClient().ServiceScriptedAnimations(
-      monotonic_frame_begin_time);
 }
 
 void PageWidgetDelegate::PostAnimate(Page& page) {
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
index 5b281c7e..6e412fa 100644
--- a/third_party/blink/renderer/core/page/pointer_lock_controller.cc
+++ b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/public/platform/web_mouse_event.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/pointer_lock_options.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -39,7 +40,9 @@
 PointerLockController::PointerLockController(Page* page)
     : page_(page), lock_pending_(false) {}
 
-void PointerLockController::RequestPointerLock(Element* target) {
+void PointerLockController::RequestPointerLock(
+    Element* target,
+    const PointerLockOptions* options) {
   if (!target || !target->isConnected() ||
       document_of_removed_element_while_waiting_for_unlock_) {
     EnqueueEvent(event_type_names::kPointerlockerror, target);
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.h b/third_party/blink/renderer/core/page/pointer_lock_controller.h
index 565ddc8..293d476 100644
--- a/third_party/blink/renderer/core/page/pointer_lock_controller.h
+++ b/third_party/blink/renderer/core/page/pointer_lock_controller.h
@@ -38,6 +38,7 @@
 class Element;
 class Document;
 class Page;
+class PointerLockOptions;
 class WebMouseEvent;
 
 // This class handles mouse pointer lock and unlock, and dispatching mouse
@@ -47,7 +48,8 @@
  public:
   explicit PointerLockController(Page*);
 
-  void RequestPointerLock(Element* target);
+  void RequestPointerLock(Element* target,
+                          const PointerLockOptions* options = nullptr);
   void RequestPointerUnlock();
   void ElementRemoved(Element*);
   void DocumentDetached(Document*);
diff --git a/third_party/blink/renderer/core/page/validation_message_client.h b/third_party/blink/renderer/core/page/validation_message_client.h
index 8e9e1a2..0942526 100644
--- a/third_party/blink/renderer/core/page/validation_message_client.h
+++ b/third_party/blink/renderer/core/page/validation_message_client.h
@@ -62,7 +62,6 @@
 
   virtual void WillBeDestroyed() = 0;
 
-  virtual void ServiceScriptedAnimations(base::TimeTicks) {}
   virtual void LayoutOverlay() {}
   virtual void UpdatePrePaint() {}
   // For CompositeAfterPaint.
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 b914246..7ab6b3b 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
@@ -195,12 +195,6 @@
     HideValidationMessage(*current_anchor_);
 }
 
-void ValidationMessageClientImpl::ServiceScriptedAnimations(
-    base::TimeTicks monotonic_frame_begin_time) {
-  if (overlay_)
-    overlay_->ServiceScriptedAnimations(monotonic_frame_begin_time);
-}
-
 void ValidationMessageClientImpl::LayoutOverlay() {
   if (overlay_)
     CheckAnchorStatus(nullptr);
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.h b/third_party/blink/renderer/core/page/validation_message_client_impl.h
index 4e9cac1..ead9a0d 100644
--- a/third_party/blink/renderer/core/page/validation_message_client_impl.h
+++ b/third_party/blink/renderer/core/page/validation_message_client_impl.h
@@ -26,7 +26,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VALIDATION_MESSAGE_CLIENT_IMPL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VALIDATION_MESSAGE_CLIENT_IMPL_H_
 
-#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/popup_opening_observer.h"
 #include "third_party/blink/renderer/core/page/validation_message_client.h"
@@ -41,7 +40,7 @@
 class FrameOverlay;
 class ValidationMessageOverlayDelegate;
 
-class CORE_EXPORT ValidationMessageClientImpl final
+class ValidationMessageClientImpl final
     : public GarbageCollectedFinalized<ValidationMessageClientImpl>,
       public ValidationMessageClient,
       private PopupOpeningObserver {
@@ -51,18 +50,8 @@
   explicit ValidationMessageClientImpl(Page&);
   ~ValidationMessageClientImpl() override;
 
-  void ShowValidationMessage(const Element& anchor,
-                             const String& message,
-                             TextDirection message_dir,
-                             const String& sub_message,
-                             TextDirection sub_message_dir) override;
-
   void Trace(blink::Visitor*) override;
 
-  ValidationMessageOverlayDelegate* GetDelegateForTesting() const {
-    return overlay_delegate_;
-  }
-
  private:
   void CheckAnchorStatus(TimerBase*);
   LocalFrameView* CurrentView();
@@ -70,12 +59,16 @@
   void Reset(TimerBase*);
   void ValidationMessageVisibilityChanged(const Element& anchor);
 
+  void ShowValidationMessage(const Element& anchor,
+                             const String& message,
+                             TextDirection message_dir,
+                             const String& sub_message,
+                             TextDirection sub_message_dir) override;
   void HideValidationMessage(const Element& anchor) override;
   bool IsValidationMessageVisible(const Element& anchor) override;
   void DocumentDetached(const Document&) override;
   void DidChangeFocusTo(const Element* new_element) override;
   void WillBeDestroyed() override;
-  void ServiceScriptedAnimations(base::TimeTicks) override;
   void LayoutOverlay() override;
   void UpdatePrePaint() override;
   void PaintOverlay(GraphicsContext&) override;
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
index 9aac603..4f35483e 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -114,11 +114,6 @@
   }
 }
 
-void ValidationMessageOverlayDelegate::ServiceScriptedAnimations(
-    base::TimeTicks monotonic_frame_begin_time) {
-  page_->Animator().ServiceScriptedAnimations(monotonic_frame_begin_time);
-}
-
 void ValidationMessageOverlayDelegate::UpdateFrameViewState(
     const FrameOverlay& overlay,
     const IntSize& view_size) {
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
index e3dfbb4..c48cfc1 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VALIDATION_MESSAGE_OVERLAY_DELEGATE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VALIDATION_MESSAGE_OVERLAY_DELEGATE_H_
 
-#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/frame/frame_overlay.h"
 #include "third_party/blink/renderer/platform/text/text_direction.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -24,8 +23,7 @@
 // bubble is shown, and deleted when the bubble is closed.
 //
 // Ownership: A FrameOverlay instance owns a ValidationMessageOverlayDelegate.
-class CORE_EXPORT ValidationMessageOverlayDelegate
-    : public FrameOverlay::Delegate {
+class ValidationMessageOverlayDelegate : public FrameOverlay::Delegate {
  public:
   ValidationMessageOverlayDelegate(Page& main_page,
                                    const Element& anchor,
@@ -36,18 +34,12 @@
   ~ValidationMessageOverlayDelegate() override;
 
   void CreatePage(const FrameOverlay&);
-
-  // FrameOverlay::Delegate implementation.
   void PaintFrameOverlay(const FrameOverlay&,
                          GraphicsContext&,
                          const IntSize& view_size) const override;
-  void ServiceScriptedAnimations(base::TimeTicks) override;
-
   void StartToHide();
   bool IsHiding() const;
 
-  Page* GetPageForTesting() const { return page_; }
-
  private:
   LocalFrameView& FrameView() const;
   void UpdateFrameViewState(const FrameOverlay&, const IntSize& view_size);
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc
deleted file mode 100644
index 9b24609c..0000000
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/page/validation_message_overlay_delegate.h"
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/animation/animation.h"
-#include "third_party/blink/renderer/core/animation/document_timeline.h"
-#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
-#include "third_party/blink/renderer/core/page/validation_message_client.h"
-#include "third_party/blink/renderer/core/page/validation_message_client_impl.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/web_test_support.h"
-
-#if defined(OS_WIN)
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/blink/public/web/win/web_font_rendering.h"
-#endif
-
-namespace blink {
-
-class ValidationMessageOverlayDelegateTest : public PaintTestConfigurations,
-                                             public RenderingTest {
-#if defined(OS_WIN)
- public:
-  void SetUp() override {
-    RenderingTest::SetUp();
-
-    // These tests appear to trigger a requirement for system fonts. On windows,
-    // an extra step is required to ensure that the system font is configured.
-    // See https://crbug.com/969622
-    blink::WebFontRendering::SetMenuFontMetrics(
-        base::ASCIIToUTF16("Arial").c_str(), 12);
-  }
-#endif
-};
-
-INSTANTIATE_PAINT_TEST_SUITE_P(ValidationMessageOverlayDelegateTest);
-
-// Regression test for https://crbug.com/990680, where we accidentally
-// composited the animations created by ValidationMessageOverlayDelegate. Since
-// overlays operate in a Page that has no compositor, the animations broke.
-TEST_P(ValidationMessageOverlayDelegateTest,
-       OverlayAnimationsShouldNotBeComposited) {
-  // When WebTestSupport::IsRunningWebTest is set, the animations in
-  // ValidationMessageOverlayDelegate are disabled. We are specifically testing
-  // animations, so make sure that doesn't happen.
-  bool was_running_web_test = WebTestSupport::IsRunningWebTest();
-  WebTestSupport::SetIsRunningWebTest(false);
-
-  SetBodyInnerHTML("<div id='anchor'></div>");
-  Element* anchor = GetElementById("anchor");
-  ASSERT_TRUE(anchor);
-
-  auto delegate = std::make_unique<ValidationMessageOverlayDelegate>(
-      GetPage(), *anchor, "Test message", TextDirection::kLtr, "Sub-message",
-      TextDirection::kLtr);
-  ValidationMessageOverlayDelegate* delegate_ptr = delegate.get();
-
-  auto overlay =
-      std::make_unique<FrameOverlay>(&GetFrame(), std::move(delegate));
-  delegate_ptr->CreatePage(*overlay);
-  ASSERT_TRUE(
-      GetFrame().View()->UpdateLifecycleToCompositingCleanPlusScrolling());
-
-  // Trigger the overlay animations.
-  auto paint_controller =
-      std::make_unique<PaintController>(PaintController::kTransient);
-  GraphicsContext context(*paint_controller);
-  overlay->Paint(context);
-
-  // Now find the related animations, and make sure they weren't composited.
-  Document* internal_document =
-      To<LocalFrame>(delegate_ptr->GetPageForTesting()->MainFrame())
-          ->GetDocument();
-  HeapVector<Member<Animation>> animations =
-      internal_document->Timeline().getAnimations();
-  ASSERT_FALSE(animations.IsEmpty());
-
-  for (const auto& animation : animations) {
-    EXPECT_FALSE(animation->HasActiveAnimationsOnCompositor());
-  }
-
-  WebTestSupport::SetIsRunningWebTest(was_running_web_test);
-}
-
-// Regression test for https://crbug.com/990680, where we found we were not
-// properly advancing the AnimationClock in the internal Page created by
-// ValidationMessageOverlayDelegate. When combined with the fix for
-// https://crbug.com/785940, this caused Animations to never be updated.
-TEST_P(ValidationMessageOverlayDelegateTest,
-       DelegatesInternalPageShouldHaveAnimationTimesUpdated) {
-  // We use a ValidationMessageClientImpl here to create our delegate since we
-  // need the official path from PageWidgetDelegate::Animate to work.
-  auto* client = MakeGarbageCollected<ValidationMessageClientImpl>(GetPage());
-  ValidationMessageClient* original_client =
-      &GetPage().GetValidationMessageClient();
-  GetPage().SetValidationMessageClientForTesting(client);
-
-  SetBodyInnerHTML(R"HTML(
-    <style>#anchor { width: 100px; height: 100px; }</style>
-    <div id='anchor'></div>
-  )HTML");
-  Element* anchor = GetElementById("anchor");
-  ASSERT_TRUE(anchor);
-
-  client->ShowValidationMessage(*anchor, "Test message", TextDirection::kLtr,
-                                "Sub-message", TextDirection::kLtr);
-  ValidationMessageOverlayDelegate* delegate = client->GetDelegateForTesting();
-  ASSERT_TRUE(delegate);
-
-  // Initially the AnimationClock will be at 0.
-  // TODO(crbug.com/785940): Re-enable this EXPECT_EQ once the AnimationClock no
-  // longer jumps ahead on its own accord.
-  AnimationClock& internal_clock =
-      delegate->GetPageForTesting()->Animator().Clock();
-  // EXPECT_EQ(internal_clock.CurrentTime(), 0);
-
-  // Now update the main Page's clock. This should trickle down and update the
-  // inner Page's clock too.
-  AnimationClock& external_clock = GetPage().Animator().Clock();
-  base::TimeTicks current_time =
-      base::TimeTicks() +
-      base::TimeDelta::FromSecondsD(external_clock.CurrentTime());
-
-  base::TimeTicks new_time = current_time + base::TimeDelta::FromSeconds(1);
-  PageWidgetDelegate::Animate(GetPage(), new_time);
-
-  // TODO(crbug.com/785940): Until this bug is fixed, this comparison could pass
-  // even if the underlying behavior regresses (because calling CurrentTime
-  // could advance the clocks anyway).
-  EXPECT_EQ(external_clock.CurrentTime(), internal_clock.CurrentTime());
-
-  GetPage().SetValidationMessageClientForTesting(original_client);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/block_painter.cc b/third_party/blink/renderer/core/paint/block_painter.cc
index 7ab7779f..1df2298 100644
--- a/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/third_party/blink/renderer/core/paint/block_painter.cc
@@ -270,8 +270,11 @@
   } else if (ShouldPaintDescendantOutlines(paint_info.phase)) {
     ObjectPainter(layout_block_).PaintInlineChildrenOutlines(paint_info);
   } else {
-    LineBoxListPainter(To<LayoutBlockFlow>(layout_block_).LineBoxes())
-        .Paint(layout_block_, paint_info, paint_offset);
+    LineBoxListPainter painter(To<LayoutBlockFlow>(layout_block_).LineBoxes());
+    // Draw a backplate behind all text if forced colors mode is enabled.
+    if (layout_block_.GetFrame()->GetDocument()->InForcedColorsMode())
+      painter.PaintBackplate(layout_block_, paint_info, paint_offset);
+    painter.Paint(layout_block_, paint_info, paint_offset);
   }
 
   // If we don't have any floats to paint, or we're in the wrong paint phase,
diff --git a/third_party/blink/renderer/core/paint/line_box_list_painter.cc b/third_party/blink/renderer/core/paint/line_box_list_painter.cc
index 58aa23f..b849d15 100644
--- a/third_party/blink/renderer/core/paint/line_box_list_painter.cc
+++ b/third_party/blink/renderer/core/paint/line_box_list_painter.cc
@@ -5,17 +5,77 @@
 #include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
 
 #include "third_party/blink/renderer/core/layout/api/line_layout_box_model.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
 #include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
 #include "third_party/blink/renderer/core/layout/line/inline_flow_box.h"
+#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
 #include "third_party/blink/renderer/core/layout/line/line_box_list.h"
 #include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_timing_detector.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 
 namespace blink {
 
+namespace {
+
+// Recursively build up backplates behind inline text boxes, each split at the
+// paragraph level. Store the results in paragraph_backplates.
+void BuildBackplate(const InlineFlowBox* box,
+                    const PhysicalOffset& paint_offset,
+                    PhysicalRect* current_backplate,
+                    int* consecutive_line_breaks,
+                    Vector<PhysicalRect>* paragraph_backplates) {
+  DCHECK(current_backplate && consecutive_line_breaks && paragraph_backplates);
+
+  // The number of consecutive forced breaks that split the backplate by
+  // paragraph.
+  static constexpr int kMaxConsecutiveLineBreaks = 2;
+
+  // Build up and paint backplates of all child inline text boxes. We are not
+  // able to simply use the linebox rect to compute the backplate because the
+  // backplate should only be painted for inline text and not for atomic
+  // inlines.
+  for (InlineBox* child = box->FirstChild(); child;
+       child = child->NextOnLine()) {
+    LineLayoutItem layout_item = child->GetLineLayoutItem();
+    if (layout_item.IsText() || layout_item.IsListMarker()) {
+      if (layout_item.IsText()) {
+        String child_text =
+            ToInlineTextBox(child)->GetLineLayoutItem().GetText();
+        if (ToInlineTextBox(child)->IsLineBreak() ||
+            child_text.StartsWith('\n'))
+          (*consecutive_line_breaks)++;
+      }
+      if (*consecutive_line_breaks >= kMaxConsecutiveLineBreaks) {
+        // This is a paragraph point.
+        paragraph_backplates->push_back(*current_backplate);
+        *current_backplate = PhysicalRect();
+        *consecutive_line_breaks = 0;
+      }
+
+      PhysicalOffset box_origin(PhysicalOffset(child->Location()) +
+                                paint_offset);
+      PhysicalRect box_rect(box_origin, PhysicalSize(child->LogicalWidth(),
+                                                     child->LogicalHeight()));
+      if (*consecutive_line_breaks > 0 && !box_rect.IsEmpty()) {
+        // Text was reached, so reset consecutive_line_breaks.
+        *consecutive_line_breaks = 0;
+      }
+      current_backplate->Unite(box_rect);
+    } else if (child->IsInlineFlowBox()) {
+      // If an inline flow box was reached, continue to recursively build up the
+      // backplate.
+      BuildBackplate(ToInlineFlowBox(child), paint_offset, current_backplate,
+                     consecutive_line_breaks, paragraph_backplates);
+    }
+  }
+}
+
+}  // anonymous namespace
+
 static void AddPDFURLRectsForInlineChildrenRecursively(
     const LayoutObject& layout_object,
     const PaintInfo& paint_info,
@@ -31,9 +91,9 @@
   }
 }
 
-void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
-                               const PaintInfo& paint_info,
-                               const PhysicalOffset& paint_offset) const {
+bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
+                                     const PaintInfo& paint_info,
+                                     const PhysicalOffset& paint_offset) const {
   DCHECK(!ShouldPaintSelfOutline(paint_info.phase) &&
          !ShouldPaintDescendantOutlines(paint_info.phase));
 
@@ -42,7 +102,7 @@
       paint_info.phase != PaintPhase::kSelection &&
       paint_info.phase != PaintPhase::kTextClip &&
       paint_info.phase != PaintPhase::kMask)
-    return;
+    return false;
 
   // The only way an inline could paint like this is if it has a layer.
   DCHECK(layout_object.IsLayoutBlock() ||
@@ -54,11 +114,20 @@
 
   // If we have no lines then we have no work to do.
   if (!line_box_list_.First())
-    return;
+    return false;
 
   if (!line_box_list_.AnyLineIntersectsRect(
           LineLayoutBoxModel(const_cast<LayoutBoxModelObject*>(&layout_object)),
           paint_info.GetCullRect(), paint_offset))
+    return false;
+
+  return true;
+}
+
+void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
+                               const PaintInfo& paint_info,
+                               const PhysicalOffset& paint_offset) const {
+  if (!ShouldPaint(layout_object, paint_info, paint_offset))
     return;
 
   ScopedPaintTimingDetectorBlockPaintHook
@@ -88,4 +157,45 @@
   }
 }
 
+void LineBoxListPainter::PaintBackplate(
+    const LayoutBoxModelObject& layout_object,
+    const PaintInfo& paint_info,
+    const PhysicalOffset& paint_offset) const {
+  if (!ShouldPaint(layout_object, paint_info, paint_offset))
+    return;
+
+  // Only paint backplates behind text when forced-color-adjust is auto.
+  const ComputedStyle& style =
+      line_box_list_.First()->GetLineLayoutItem().StyleRef();
+  if (style.ForcedColorAdjust() == EForcedColorAdjust::kNone)
+    return;
+
+  if (DrawingRecorder::UseCachedDrawingIfPossible(
+          paint_info.context, layout_object,
+          DisplayItem::kForcedColorsModeBackplate))
+    return;
+
+  DrawingRecorder recorder(paint_info.context, layout_object,
+                           DisplayItem::kForcedColorsModeBackplate);
+  Color backplate_color = style.ForcedBackplateColor();
+  const auto& backplates = GetBackplates(paint_offset);
+  for (const auto backplate : backplates)
+    paint_info.context.FillRect(FloatRect(backplate), backplate_color);
+}
+
+Vector<PhysicalRect> LineBoxListPainter::GetBackplates(
+    const PhysicalOffset& paint_offset) const {
+  Vector<PhysicalRect> paragraph_backplates;
+  PhysicalRect current_backplate;
+  int consecutive_line_breaks = 0;
+  for (const InlineFlowBox* line : line_box_list_) {
+    // Recursively build up and paint backplates for line boxes containing text.
+    BuildBackplate(line, paint_offset, &current_backplate,
+                   &consecutive_line_breaks, &paragraph_backplates);
+  }
+  if (!current_backplate.IsEmpty())
+    paragraph_backplates.push_back(current_backplate);
+  return paragraph_backplates;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/line_box_list_painter.h b/third_party/blink/renderer/core/paint/line_box_list_painter.h
index 9377a43..1c33b642 100644
--- a/third_party/blink/renderer/core/paint/line_box_list_painter.h
+++ b/third_party/blink/renderer/core/paint/line_box_list_painter.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
@@ -14,6 +15,7 @@
 class LineBoxList;
 struct PaintInfo;
 struct PhysicalOffset;
+struct PhysicalRect;
 
 class LineBoxListPainter {
   STACK_ALLOCATED();
@@ -25,9 +27,20 @@
   void Paint(const LayoutBoxModelObject&,
              const PaintInfo&,
              const PhysicalOffset& paint_offset) const;
+  void PaintBackplate(const LayoutBoxModelObject& layout_object,
+                      const PaintInfo&,
+                      const PhysicalOffset& paint_offset) const;
 
  private:
   const LineBoxList& line_box_list_;
+
+  bool ShouldPaint(const LayoutBoxModelObject& layout_object,
+                   const PaintInfo& paint_info,
+                   const PhysicalOffset& paint_offset) const;
+
+  // Returns a vector of backplates that surround the paragraphs of text within
+  // line_box_list_.
+  Vector<PhysicalRect> GetBackplates(const PhysicalOffset& paint_offset) const;
 };
 
 }  // namespace blink
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 88934007b..a0856d21 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
@@ -142,6 +142,70 @@
   return fragment.IsBlockFormattingContextRoot();
 }
 
+// Recursively build up backplates behind inline text boxes, each split at the
+// paragraph level. Store the results in paragraph_backplates.
+void BuildBackplate(const NGPaintFragment* line,
+                    const PhysicalOffset& paint_offset,
+                    PhysicalRect* current_backplate,
+                    int* consecutive_line_breaks,
+                    Vector<PhysicalRect>* paragraph_backplates) {
+  DCHECK(current_backplate && consecutive_line_breaks && paragraph_backplates);
+
+  // The number of consecutive forced breaks that split the backplate by
+  // paragraph.
+  static constexpr int kMaxConsecutiveLineBreaks = 2;
+
+  // Build up and paint backplates of all child inline text boxes. We are not
+  // able to simply use the linebox rect to compute the backplate because the
+  // backplate should only be painted for inline text and not for atomic
+  // inlines.
+  for (const NGPaintFragment* child : line->Children()) {
+    const NGPhysicalFragment& child_fragment = child->PhysicalFragment();
+    if (child_fragment.IsHiddenForPaint() || child_fragment.IsFloating())
+      continue;
+    if (auto* text_fragment =
+            DynamicTo<NGPhysicalTextFragment>(child_fragment)) {
+      if (text_fragment->IsLineBreak()) {
+        (*consecutive_line_breaks)++;
+        continue;
+      }
+
+      if (*consecutive_line_breaks >= kMaxConsecutiveLineBreaks) {
+        // This is a paragraph point.
+        paragraph_backplates->push_back(*current_backplate);
+        *current_backplate = PhysicalRect();
+      }
+      *consecutive_line_breaks = 0;
+      PhysicalRect box_rect(child->InlineOffsetToContainerBox() + paint_offset,
+                            child->Size());
+      current_backplate->Unite(box_rect);
+    }
+    if (child_fragment.Type() == NGPhysicalFragment::kFragmentBox) {
+      // If a fragment box was reached, continue to recursively build
+      // up the backplate.
+      BuildBackplate(child, paint_offset, current_backplate,
+                     consecutive_line_breaks, paragraph_backplates);
+    }
+  }
+}
+
+// Returns a vector of backplates that surround the paragraphs of text within
+// line_boxes.
+Vector<PhysicalRect> BuildBackplate(const NGPaintFragment::ChildList line_boxes,
+                                    const PhysicalOffset& paint_offset) {
+  Vector<PhysicalRect> paragraph_backplates;
+  PhysicalRect current_backplate;
+  int consecutive_line_breaks = 0;
+  for (const NGPaintFragment* line : line_boxes) {
+    // Recursively build up and paint backplates for line boxes containing text.
+    BuildBackplate(line, paint_offset, &current_backplate,
+                   &consecutive_line_breaks, &paragraph_backplates);
+  }
+  if (!current_backplate.IsEmpty())
+    paragraph_backplates.push_back(current_backplate);
+  return paragraph_backplates;
+}
+
 }  // anonymous namespace
 
 const NGBorderEdges& NGBoxFragmentPainter::BorderEdges() const {
@@ -878,6 +942,9 @@
     }
   }
 
+  if (layout_block.GetDocument().InForcedColorsMode())
+    PaintBackplate(line_boxes, paint_info, paint_offset);
+
   const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode();
 
   for (const NGPaintFragment* line : line_boxes) {
@@ -928,6 +995,30 @@
   }
 }
 
+void NGBoxFragmentPainter::PaintBackplate(NGPaintFragment::ChildList line_boxes,
+                                          const PaintInfo& paint_info,
+                                          const PhysicalOffset& paint_offset) {
+  if (paint_info.phase != PaintPhase::kForeground)
+    return;
+
+  // Only paint backplates behind text when forced-color-adjust is auto.
+  const ComputedStyle& style = line_boxes.front().Style();
+  if (style.ForcedColorAdjust() == EForcedColorAdjust::kNone)
+    return;
+
+  if (DrawingRecorder::UseCachedDrawingIfPossible(
+          paint_info.context, GetDisplayItemClient(),
+          DisplayItem::kForcedColorsModeBackplate))
+    return;
+
+  DrawingRecorder recorder(paint_info.context, GetDisplayItemClient(),
+                           DisplayItem::kForcedColorsModeBackplate);
+  Color backplate_color = style.ForcedBackplateColor();
+  const auto& backplates = BuildBackplate(line_boxes, paint_offset);
+  for (const auto backplate : backplates)
+    paint_info.context.FillRect(FloatRect(backplate), backplate_color);
+}
+
 void NGBoxFragmentPainter::PaintInlineChildren(
     NGPaintFragment::ChildList inline_children,
     const PaintInfo& paint_info,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index ff6a4c1..af180a1c 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -86,6 +86,9 @@
   void PaintLineBoxChildren(NGPaintFragment::ChildList,
                             const PaintInfo&,
                             const PhysicalOffset& paint_offset);
+  void PaintBackplate(NGPaintFragment::ChildList,
+                      const PaintInfo&,
+                      const PhysicalOffset& paint_offset);
   void PaintInlineChildren(NGPaintFragment::ChildList,
                            const PaintInfo&,
                            const PhysicalOffset& paint_offset);
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index 476685c..332a0ed 100644
--- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -213,6 +213,10 @@
   if (object_.ShouldDoFullPaintInvalidation())
     return object_.FullPaintInvalidationReason();
 
+  if (object_.GetDocument().InForcedColorsMode() &&
+      object_.IsLayoutBlockFlow() && !context_.old_visual_rect.IsEmpty())
+    return PaintInvalidationReason::kBackplate;
+
   if (!(context_.subtree_flags &
         PaintInvalidatorContext::kInvalidateEmptyVisualRect) &&
       context_.old_visual_rect.IsEmpty() &&
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 491bb25..00f9cb6 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2494,6 +2494,11 @@
     return DarkColorScheme() ? WebColorScheme::kDark : WebColorScheme::kLight;
   }
 
+  Color ForcedBackplateColor() const {
+    return LayoutTheme::GetTheme().SystemColor(CSSValueID::kWindow,
+                                               WebColorScheme::kLight);
+  }
+
  private:
   EClear Clear() const { return ClearInternal(); }
   EFloat Floating() const { return FloatingInternal(); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 346f15bf..5fa7d12 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2575,10 +2575,14 @@
   // NOTE: this assumes that any non-image with an anchor is an
   // HTMLAnchorElement
   for (; node; node = node->parentNode()) {
-    if (IsA<HTMLAnchorElement>(*node) ||
-        (node->GetLayoutObject() &&
-         cache.GetOrCreate(node->GetLayoutObject())->IsAnchor()))
+    if (IsA<HTMLAnchorElement>(*node))
       return To<Element>(node);
+
+    if (LayoutObject* layout_object = node->GetLayoutObject()) {
+      AXObject* ax_object = cache.GetOrCreate(layout_object);
+      if (ax_object && ax_object->IsAnchor())
+        return To<Element>(node);
+    }
   }
 
   return nullptr;
diff --git a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
index 59f8c69..c064aa7 100644
--- a/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
+++ b/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
@@ -69,7 +69,7 @@
 
   DOMNodeId canvas_id = DOMNodeIds::IdForNode(&canvas);
   offscreen_canvas->SetPlaceholderCanvasId(canvas_id);
-  canvas.RegisterPlaceholder(static_cast<int>(canvas_id));
+  canvas.RegisterPlaceholderCanvas(static_cast<int>(canvas_id));
 
   SurfaceLayerBridge* bridge = canvas.SurfaceLayerBridge();
   if (bridge) {
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc b/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
index 69830f6..bdeacd0 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
+++ b/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
@@ -72,7 +72,7 @@
   msg_params->client = std::move(session_client);
   msg_params->session_request = std::move(session_request);
 
-  GetSpeechRecognizer().Start(std::move(msg_params));
+  GetSpeechRecognizer()->Start(std::move(msg_params));
 }
 
 void ProvideSpeechRecognitionTo(LocalFrame& frame) {
@@ -80,13 +80,13 @@
       frame, SpeechRecognitionController::Create(frame));
 }
 
-mojom::blink::SpeechRecognizer&
+mojo::Remote<mojom::blink::SpeechRecognizer>&
 SpeechRecognitionController::GetSpeechRecognizer() {
   if (!speech_recognizer_) {
     GetSupplementable()->GetInterfaceProvider().GetInterface(
-        mojo::MakeRequest(&speech_recognizer_));
+        speech_recognizer_.BindNewPipeAndPassReceiver());
   }
-  return *speech_recognizer_;
+  return speech_recognizer_;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/speech/speech_recognition_controller.h b/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
index 8ab8880..0e8cd80 100644
--- a/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
+++ b/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
@@ -28,6 +28,7 @@
 
 #include <memory>
 
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/speech/speech_recognizer.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -61,9 +62,9 @@
   }
 
  private:
-  mojom::blink::SpeechRecognizer& GetSpeechRecognizer();
+  mojo::Remote<mojom::blink::SpeechRecognizer>& GetSpeechRecognizer();
 
-  mojom::blink::SpeechRecognizerPtr speech_recognizer_;
+  mojo::Remote<mojom::blink::SpeechRecognizer> speech_recognizer_;
 };
 
 MODULES_EXPORT void ProvideSpeechRecognitionTo(LocalFrame& frame);
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index acaf8b2..6829acc 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -349,6 +349,10 @@
   RuntimeEnabledFeatures::SetPictureInPictureAPIEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnablePointerLockOptions(bool enable) {
+  RuntimeEnabledFeatures::SetPointerLockOptionsEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnablePortals(bool enable) {
   RuntimeEnabledFeatures::SetPortalsEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
index d42333b..d4b089d2 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -91,9 +91,10 @@
     viz::ResourceId resource_id) {
   DCHECK(IsMainThread());
   OffscreenCanvasPlaceholder* placeholder_canvas =
-      OffscreenCanvasPlaceholder::GetPlaceholderById(placeholder_canvas_id);
+      OffscreenCanvasPlaceholder::GetPlaceholderCanvasById(
+          placeholder_canvas_id);
   if (placeholder_canvas) {
-    placeholder_canvas->SetPlaceholderFrame(
+    placeholder_canvas->SetOffscreenCanvasFrame(
         std::move(canvas_resource), std::move(dispatcher),
         std::move(task_runner), resource_id);
   }
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index b9dd053..ddde5f68 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
 #include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
 
 namespace blink {
 
@@ -220,18 +221,27 @@
 
   // Convert the color type to the requested one if necessary
   if (decoded && target_info.colorType() != dst_info.colorType()) {
-    auto canvas = SkCanvas::MakeRasterDirect(dst_info, pixels, row_bytes);
-    DCHECK(canvas);
-    SkPaint paint;
-    if (dst_info.colorType() == kARGB_4444_SkColorType ||
-        dst_info.colorType() == kRGB_565_SkColorType) {
+    // Convert the color type by readPixels if dithering is not necessary
+    // (readPixels is potentially cheaper than a full-blown drawBitmap).
+    if (SkColorTypeBytesPerPixel(target_info.colorType()) <=
+        SkColorTypeBytesPerPixel(dst_info.colorType())) {
+      decoded = SkPixmap{target_info, memory, adjusted_row_bytes}.readPixels(
+          SkPixmap{dst_info, pixels, row_bytes});
+      DCHECK(decoded);
+    } else {  // Do dithering by drawBitmap() if dithering is necessary
+      auto canvas = SkCanvas::MakeRasterDirect(dst_info, pixels, row_bytes);
+      DCHECK(canvas);
+
+      SkPaint paint;
       paint.setDither(true);
+      paint.setBlendMode(SkBlendMode::kSrc);
+
+      SkBitmap bitmap;
+      decoded = bitmap.installPixels(target_info, memory, adjusted_row_bytes);
+      DCHECK(decoded);
+
+      canvas->drawBitmap(bitmap, 0, 0, &paint);
     }
-    paint.setBlendMode(SkBlendMode::kSrc);
-    SkBitmap bitmap;
-    decoded = bitmap.installPixels(target_info, memory, adjusted_row_bytes);
-    DCHECK(decoded);
-    canvas->drawBitmap(bitmap, 0, 0, &paint);
   }
   return decoded;
 }
diff --git a/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc b/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
index b344e13..84dbe25 100644
--- a/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
+++ b/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
@@ -45,40 +45,17 @@
 namespace blink {
 
 OffscreenCanvasPlaceholder::~OffscreenCanvasPlaceholder() {
-  UnregisterPlaceholder();
+  UnregisterPlaceholderCanvas();
 }
 
-OffscreenCanvasPlaceholder* OffscreenCanvasPlaceholder::GetPlaceholderById(
-    unsigned placeholder_id) {
-  PlaceholderIdMap::iterator it = placeholderRegistry().find(placeholder_id);
-  if (it == placeholderRegistry().end())
-    return nullptr;
-  return it->value;
-}
-
-void OffscreenCanvasPlaceholder::RegisterPlaceholder(unsigned placeholder_id) {
-  DCHECK(!placeholderRegistry().Contains(placeholder_id));
-  DCHECK(!IsPlaceholderRegistered());
-  placeholderRegistry().insert(placeholder_id, this);
-  placeholder_id_ = placeholder_id;
-}
-
-void OffscreenCanvasPlaceholder::UnregisterPlaceholder() {
-  if (!IsPlaceholderRegistered())
-    return;
-  DCHECK(placeholderRegistry().find(placeholder_id_)->value == this);
-  placeholderRegistry().erase(placeholder_id_);
-  placeholder_id_ = kNoPlaceholderId;
-}
-
-void OffscreenCanvasPlaceholder::SetPlaceholderFrame(
+void OffscreenCanvasPlaceholder::SetOffscreenCanvasFrame(
     scoped_refptr<CanvasResource> new_frame,
     base::WeakPtr<CanvasResourceDispatcher> dispatcher,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     viz::ResourceId resource_id) {
-  DCHECK(IsPlaceholderRegistered());
+  DCHECK(IsOffscreenCanvasRegistered());
   DCHECK(new_frame);
-  ReleasePlaceholderFrame();
+  ReleaseOffscreenCanvasFrame();
   placeholder_frame_ = std::move(new_frame);
   frame_dispatcher_ = std::move(dispatcher);
   frame_dispatcher_task_runner_ = std::move(task_runner);
@@ -95,8 +72,8 @@
   }
 }
 
-void OffscreenCanvasPlaceholder::ReleasePlaceholderFrame() {
-  DCHECK(IsPlaceholderRegistered());
+void OffscreenCanvasPlaceholder::ReleaseOffscreenCanvasFrame() {
+  DCHECK(IsOffscreenCanvasRegistered());
   if (placeholder_frame_) {
     DCHECK(frame_dispatcher_task_runner_);
     placeholder_frame_->Transfer();
@@ -144,6 +121,30 @@
   }
 }
 
+OffscreenCanvasPlaceholder*
+OffscreenCanvasPlaceholder::GetPlaceholderCanvasById(unsigned placeholder_id) {
+  PlaceholderIdMap::iterator it = placeholderRegistry().find(placeholder_id);
+  if (it == placeholderRegistry().end())
+    return nullptr;
+  return it->value;
+}
+
+void OffscreenCanvasPlaceholder::RegisterPlaceholderCanvas(
+    unsigned placeholder_id) {
+  DCHECK(!placeholderRegistry().Contains(placeholder_id));
+  DCHECK(!IsOffscreenCanvasRegistered());
+  placeholderRegistry().insert(placeholder_id, this);
+  placeholder_id_ = placeholder_id;
+}
+
+void OffscreenCanvasPlaceholder::UnregisterPlaceholderCanvas() {
+  if (!IsOffscreenCanvasRegistered())
+    return;
+  DCHECK(placeholderRegistry().find(placeholder_id_)->value == this);
+  placeholderRegistry().erase(placeholder_id_);
+  placeholder_id_ = kNoPlaceholderId;
+}
+
 bool OffscreenCanvasPlaceholder::PostSetSuspendAnimationToOffscreenCanvasThread(
     bool suspend) {
   if (!frame_dispatcher_task_runner_)
diff --git a/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h b/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
index de3578a..dc91d6cb 100644
--- a/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
+++ b/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
@@ -24,30 +24,32 @@
  public:
   ~OffscreenCanvasPlaceholder();
 
-  virtual void SetPlaceholderFrame(scoped_refptr<CanvasResource>,
-                                   base::WeakPtr<CanvasResourceDispatcher>,
-                                   scoped_refptr<base::SingleThreadTaskRunner>,
-                                   viz::ResourceId resource_id);
-  void ReleasePlaceholderFrame();
+  virtual void SetOffscreenCanvasFrame(
+      scoped_refptr<CanvasResource>,
+      base::WeakPtr<CanvasResourceDispatcher>,
+      scoped_refptr<base::SingleThreadTaskRunner>,
+      viz::ResourceId resource_id);
+  void ReleaseOffscreenCanvasFrame();
 
   void SetSuspendOffscreenCanvasAnimation(bool);
 
-  static OffscreenCanvasPlaceholder* GetPlaceholderById(
+  static OffscreenCanvasPlaceholder* GetPlaceholderCanvasById(
       unsigned placeholder_id);
 
-  void RegisterPlaceholder(unsigned placeholder_id);
-  void UnregisterPlaceholder();
-  const scoped_refptr<CanvasResource>& PlaceholderFrame() const {
+  void RegisterPlaceholderCanvas(unsigned placeholder_id);
+  void UnregisterPlaceholderCanvas();
+  const scoped_refptr<CanvasResource>& OffscreenCanvasFrame() const {
     return placeholder_frame_;
   }
 
-  bool IsPlaceholderRegistered() const {
+  bool IsOffscreenCanvasRegistered() const {
     return placeholder_id_ != kNoPlaceholderId;
   }
 
  private:
   bool PostSetSuspendAnimationToOffscreenCanvasThread(bool suspend);
 
+  // Information about the Offscreen Canvas:
   scoped_refptr<CanvasResource> placeholder_frame_;
   base::WeakPtr<CanvasResourceDispatcher> frame_dispatcher_;
   scoped_refptr<base::SingleThreadTaskRunner> frame_dispatcher_task_runner_;
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index 6063758d..4a8ff9d 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -80,6 +80,7 @@
     DEBUG_STRING_CASE(DragImage);
     DEBUG_STRING_CASE(DragCaret);
     DEBUG_STRING_CASE(EmptyContentForFilters);
+    DEBUG_STRING_CASE(ForcedColorsModeBackplate);
     DEBUG_STRING_CASE(SVGImage);
     DEBUG_STRING_CASE(LinkHighlight);
     DEBUG_STRING_CASE(ImageAreaFocusRing);
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 9448ce6..ce0e179 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -65,6 +65,7 @@
     kDragImage,
     kDragCaret,
     kEmptyContentForFilters,
+    kForcedColorsModeBackplate,
     kSVGImage,
     kLinkHighlight,
     kImageAreaFocusRing,
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
index 3fcb7a2..b280227a 100644
--- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
+++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
@@ -22,6 +22,8 @@
       return "full";
     case PaintInvalidationReason::kStyle:
       return "style change";
+    case PaintInvalidationReason::kBackplate:
+      return "backplate";
     case PaintInvalidationReason::kGeometry:
       return "geometry";
     case PaintInvalidationReason::kCompositing:
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
index 64d1d7c..5da1ca0d 100644
--- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
+++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
@@ -23,6 +23,7 @@
   kFull,
   kStyle,
   // Layout or visual geometry change.
+  kBackplate,
   kGeometry,
   kCompositing,
   kAppeared,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index a61134d..2cdd4a9 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1272,6 +1272,9 @@
       origin_trial_feature_name: "PNaCl",
     },
     {
+      name: "PointerLockOptions",
+    },
+    {
       name: "PointerRawUpdate",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index eb81b65..62f42192 100644
--- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -31,6 +31,7 @@
 
   PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
 
+  void SetPausedForCooperativeScheduling(Paused) override {}
   void SetFrameVisible(bool) override {}
   bool IsFrameVisible() const override { return true; }
   bool IsPageVisible() const override { return true; }
diff --git a/third_party/blink/renderer/platform/scheduler/common/event_loop.cc b/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
index a9eaba8..abed7cb 100644
--- a/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -22,7 +23,9 @@
   DCHECK(isolate_);
 }
 
-EventLoop::~EventLoop() = default;
+EventLoop::~EventLoop() {
+  DCHECK(schedulers_.IsEmpty());
+}
 
 void EventLoop::EnqueueMicrotask(base::OnceClosure task) {
   pending_microtasks_.push_back(std::move(task));
@@ -46,12 +49,38 @@
 
 void EventLoop::Disable() {
   loop_enabled_ = false;
-  // TODO(tzik): Disable associated Frames.
+
+  for (auto* scheduler : schedulers_) {
+    scheduler->SetPausedForCooperativeScheduling(
+        FrameOrWorkerScheduler::Paused(true));
+  }
+  // TODO(keishi): Disable microtaskqueue too.
 }
 
 void EventLoop::Enable() {
   loop_enabled_ = true;
-  // TODO(tzik): Enable associated Frames.
+
+  for (auto* scheduler : schedulers_) {
+    scheduler->SetPausedForCooperativeScheduling(
+        FrameOrWorkerScheduler::Paused(false));
+  }
+  // TODO(keishi): Enable microtaskqueue too.
+}
+
+void EventLoop::AttachScheduler(FrameOrWorkerScheduler* scheduler) {
+  DCHECK(loop_enabled_);
+  DCHECK(!schedulers_.Contains(scheduler));
+  schedulers_.insert(scheduler);
+}
+
+void EventLoop::DetachScheduler(FrameOrWorkerScheduler* scheduler) {
+  DCHECK(loop_enabled_);
+  DCHECK(schedulers_.Contains(scheduler));
+  schedulers_.erase(scheduler);
+}
+
+bool EventLoop::IsSchedulerAttachedForTest(FrameOrWorkerScheduler* scheduler) {
+  return schedulers_.Contains(scheduler);
 }
 
 // static
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index a364309..e51f0705 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -1207,5 +1207,9 @@
   return QueueTraits().SetShouldUseVirtualTime(false);
 }
 
+void FrameSchedulerImpl::SetPausedForCooperativeScheduling(Paused paused) {
+  // TODO(keishi): Stop all task queues
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index fc7d8be..d2fd2b5e 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -80,6 +80,9 @@
       FrameScheduler::FrameType frame_type);
   ~FrameSchedulerImpl() override;
 
+  // FrameOrWorkerScheduler implementation:
+  void SetPausedForCooperativeScheduling(Paused) override;
+
   // FrameScheduler implementation:
   void SetFrameVisible(bool frame_visible) override;
   bool IsFrameVisible() const override;
diff --git a/third_party/blink/renderer/platform/scheduler/public/event_loop.h b/third_party/blink/renderer/platform/scheduler/public/event_loop.h
index 00190e8..d2ee0896 100644
--- a/third_party/blink/renderer/platform/scheduler/public/event_loop.h
+++ b/third_party/blink/renderer/platform/scheduler/public/event_loop.h
@@ -22,6 +22,7 @@
 namespace blink {
 
 class Agent;
+class FrameOrWorkerScheduler;
 
 namespace scheduler {
 
@@ -72,10 +73,15 @@
   void Disable();
   void Enable();
 
+  void AttachScheduler(FrameOrWorkerScheduler*);
+  void DetachScheduler(FrameOrWorkerScheduler*);
+
   // Returns the MicrotaskQueue instance to be associated to v8::Context. Pass
   // it to v8::Context::New().
   v8::MicrotaskQueue* microtask_queue() const { return microtask_queue_.get(); }
 
+  bool IsSchedulerAttachedForTest(FrameOrWorkerScheduler*);
+
  private:
   friend class WTF::RefCounted<EventLoop>;
   friend blink::Agent;
@@ -90,6 +96,7 @@
   bool loop_enabled_ = true;
   Deque<base::OnceClosure> pending_microtasks_;
   std::unique_ptr<v8::MicrotaskQueue> microtask_queue_;
+  HashSet<FrameOrWorkerScheduler*> schedulers_;
 
   DISALLOW_COPY_AND_ASSIGN(EventLoop);
 };
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
index fb6e1bb..56915ee 100644
--- a/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_FRAME_OR_WORKER_SCHEDULER_H_
 
 #include "base/memory/weak_ptr.h"
+#include "base/util/type_safety/strong_alias.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h"
 #include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
@@ -85,6 +86,10 @@
 
   virtual ~FrameOrWorkerScheduler();
 
+  using Paused = util::StrongAlias<class PausedTag, bool>;
+  // Stops any tasks from running while we yield and run a nested loop.
+  virtual void SetPausedForCooperativeScheduling(Paused) = 0;
+
   // Notifies scheduler that this execution context has started using a feature
   // which impacts scheduling decisions.
   // When the feature stops being used, this handle should be destroyed.
diff --git a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
index 537458f..39922c6 100644
--- a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -67,6 +67,9 @@
   void OnStoppedUsingFeature(SchedulingPolicy::Feature feature,
                              const SchedulingPolicy& policy) override;
 
+  // FrameOrWorkerScheduler implementation:
+  void SetPausedForCooperativeScheduling(Paused) override {}
+
  protected:
   scoped_refptr<NonMainThreadTaskQueue> ThrottleableTaskQueue();
   scoped_refptr<NonMainThreadTaskQueue> UnpausableTaskQueue();
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index 85eaaaf..49aaa6fe 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -336,5 +336,18 @@
 crbug.com/993953 [ Linux ] http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Pass Timeout ]
 crbug.com/993953 [ Linux ] virtual/wasm-site-isolated-code-cache/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/dom/idlharness.any.serviceworker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/css/css-typed-om/idlharness.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/css/cssom-view/idlharness.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/css/cssom/idlharness.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/css/filter-effects/idlharness.any.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/css/filter-effects/idlharness.any.worker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/fetch/api/idlharness.any.worker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/html/dom/idlharness.worker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] external/wpt/mediasession/idlharness.window.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/blink-cors/external/wpt/fetch/api/idlharness.any.serviceworker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/cascade/external/wpt/css/css-typed-om/idlharness.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/idlharness.any.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/idlharness.any.worker.html [ Pass Timeout ]
+
 
 # Note to sheriffs: Timeouts about "idlharness" or "interfaces" are usually crbug.com/856601.
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index ee3106d..7593374a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3251,6 +3251,12 @@
 crbug.com/994214 external/wpt/html/cross-origin-opener-policy/coop-navigated-popup.https.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/css/mediaqueries/aspect-ratio-006.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/mediaqueries/aspect-ratio-006.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/mediaqueries/aspect-ratio-006.html [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/css/mediaqueries/aspect-ratio-005.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/mediaqueries/aspect-ratio-005.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/mediaqueries/aspect-ratio-005.html [ Failure ]
 crbug.com/626703 [ Win10 ] virtual/cascade/external/wpt/css/css-paint-api/color-custom-property-animation.https.html [ Failure ]
 crbug.com/626703 [ Mac10.11 ] virtual/omt-service-worker-startup/external/wpt/shape-detection/shapedetection-cross-origin.sub.https.html [ Timeout ]
 crbug.com/626703 [ Mac10.11 ] virtual/omt-service-worker-startup/external/wpt/shape-detection/detection-security-test.https.html [ Timeout ]
@@ -6530,3 +6536,5 @@
 
 # Pending enabling scroll to text feature
 crbug.com/919204 external/wpt/scroll-to-text-fragment/scroll-to-text-fragment.html [ Skip ]
+
+crbug.com/999209 virtual/lazyload-image/http/tests/lazyload/style-dimension.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 9498c42..f80c725 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -102333,6 +102333,30 @@
      {}
     ]
    ],
+   "css/mediaqueries/aspect-ratio-005.html": [
+    [
+     "css/mediaqueries/aspect-ratio-005.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/mediaqueries/aspect-ratio-006.html": [
+    [
+     "css/mediaqueries/aspect-ratio-006.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/mediaqueries/device-aspect-ratio-001.html": [
     [
      "css/mediaqueries/device-aspect-ratio-001.html",
@@ -164211,7 +164235,7 @@
    "kv-storage/secure-context/README.md": [
     []
    ],
-   "kv-storage/secure-context/import-maps-expected.txt": [
+   "kv-storage/secure-context/import-statement-expected.txt": [
     []
    ],
    "kv-storage/secure-context/resources/dummy-module.js": [
@@ -164220,18 +164244,15 @@
    "kv-storage/secure-context/resources/test-side-effects.js": [
     []
    ],
-   "kv-storage/secure-context/script-element-expected.txt": [
-    []
-   ],
-   "kv-storage/secure-context/side-effects-expected.txt": [
-    []
-   ],
    "largest-contentful-paint/idlharness-expected.txt": [
     []
    ],
    "largest-contentful-paint/resources/iframe-stores-entry.html": [
     []
    ],
+   "largest-contentful-paint/resources/largest-contentful-paint-helpers.js": [
+    []
+   ],
    "layout-instability/resources/slow-image.py": [
     []
    ],
@@ -219489,6 +219510,12 @@
      {}
     ]
    ],
+   "css/cssom-view/getBoundingClientRect-empty-inline.html": [
+    [
+     "css/cssom-view/getBoundingClientRect-empty-inline.html",
+     {}
+    ]
+   ],
    "css/cssom-view/getClientRects-br-htb-ltr.html": [
     [
      "css/cssom-view/getClientRects-br-htb-ltr.html",
@@ -255468,6 +255495,12 @@
      {}
     ]
    ],
+   "largest-contentful-paint/video-poster.html": [
+    [
+     "largest-contentful-paint/video-poster.html",
+     {}
+    ]
+   ],
    "layout-instability/buffer-layout-shift.html": [
     [
      "layout-instability/buffer-layout-shift.html",
@@ -409672,6 +409705,10 @@
    "bf883a1423a150a49fa3170014308a6252365810",
    "testharness"
   ],
+  "css/cssom-view/getBoundingClientRect-empty-inline.html": [
+   "443ded230f465b40d1c327d4837ffcbe7c2a1ada",
+   "testharness"
+  ],
   "css/cssom-view/getClientRects-br-htb-ltr.html": [
    "e952d61b677164c3b5d49799c80063174120307f",
    "testharness"
@@ -412241,7 +412278,7 @@
    "support"
   ],
   "css/mediaqueries/aspect-ratio-001.html": [
-   "0dad9ea792918255a90455419da5e6f52ce249c0",
+   "09878061267683e7c4505a408bd68d0c5ace4ee6",
    "reftest"
   ],
   "css/mediaqueries/aspect-ratio-002.html": [
@@ -412249,13 +412286,21 @@
    "reftest"
   ],
   "css/mediaqueries/aspect-ratio-003.html": [
-   "76bebd70272d4cb5f066b73f80be59898196a887",
+   "14868108ac46d074ab4de0e94e66511907cfd302",
    "reftest"
   ],
   "css/mediaqueries/aspect-ratio-004.html": [
    "b4b2e860d872ae684615dce3c6848e0a4a5c369f",
    "reftest"
   ],
+  "css/mediaqueries/aspect-ratio-005.html": [
+   "2c9d9edcf764802bf0b6a82c0fd2270e158e2679",
+   "reftest"
+  ],
+  "css/mediaqueries/aspect-ratio-006.html": [
+   "188a65b715291b33d93d8a6af88c2a7f6e25858c",
+   "reftest"
+  ],
   "css/mediaqueries/device-aspect-ratio-001.html": [
    "60f49b9b3cfedaf8136dcb568570ef71124cba8b",
    "reftest"
@@ -412393,11 +412438,11 @@
    "support"
   ],
   "css/mediaqueries/test_media_queries-expected.txt": [
-   "00ae68231285ecbf7e7f1c5468bbb54598c85ad5",
+   "cf0e2c2ab45dbbae7404b611c534507290e577c7",
    "support"
   ],
   "css/mediaqueries/test_media_queries.html": [
-   "d08d83c34fd8112e2ecfee0f89893353e84df714",
+   "d368acf8b57da4b98825cb4ddc25ae4c44338745",
    "testharness"
   ],
   "css/mediaqueries/viewport-script-dynamic-ref.html": [
@@ -452156,16 +452201,16 @@
    "38e1bb79c47ecf0886f231f8f40c1aac36d8a063",
    "testharness"
   ],
-  "kv-storage/secure-context/import-maps-expected.txt": [
-   "25267f1b72699393d04d6b7e8507d5fda480b9f8",
-   "support"
-  ],
   "kv-storage/secure-context/import-maps.html": [
-   "64301f03032c0efe047297b21389ccf778949a76",
+   "211b9e43b1f18e9bdab85b890af000e47395c2ff",
    "testharness"
   ],
+  "kv-storage/secure-context/import-statement-expected.txt": [
+   "879a0facba4d00db9e8435b38ff5cd93d281f055",
+   "support"
+  ],
   "kv-storage/secure-context/import-statement.html": [
-   "db01152a4e155e27dcdbc264a4291d0245c115d4",
+   "71e14b04e3144f866ff6cda980998dedaa6a559b",
    "testharness"
   ],
   "kv-storage/secure-context/resources/dummy-module.js": [
@@ -452176,18 +452221,10 @@
    "39780a92fff17fdf64d8b43c025304b59b1fe2b7",
    "support"
   ],
-  "kv-storage/secure-context/script-element-expected.txt": [
-   "05d83405fb23a5995729bde55e69b3e84e630a0a",
-   "support"
-  ],
   "kv-storage/secure-context/script-element.html": [
    "b8170549ab558bbef98a357074b1ec6281a385a7",
    "testharness"
   ],
-  "kv-storage/secure-context/side-effects-expected.txt": [
-   "0d965bf39d42078754e1ce7bd65b224c37f381ca",
-   "support"
-  ],
   "kv-storage/secure-context/side-effects.html": [
    "f4c4b691d30db83342aaa5fc3a181d4dc98b4f1d",
    "testharness"
@@ -452205,11 +452242,11 @@
    "testharness"
   ],
   "largest-contentful-paint/contracted-image.html": [
-   "e099a5e42f6d3fd7982a7e298c53b860258f8c70",
+   "2d4a84bf35cf895f6bc667f2e5c4352d86fd74d0",
    "testharness"
   ],
   "largest-contentful-paint/cross-origin-image.sub.html": [
-   "7669d4647802f54f4d04b7b7a6b0a9ccc19b9f11",
+   "58e636e51b9f2b544b2c8f40324e61c97ee5c795",
    "testharness"
   ],
   "largest-contentful-paint/element-only-when-fully-active.html": [
@@ -452217,11 +452254,11 @@
    "testharness"
   ],
   "largest-contentful-paint/expanded-image.html": [
-   "9f64189eda60bc74b41d2526e577dcd0e0cf88d2",
+   "6f7043dd8e426d6b4b5d4f89d8e64383cf7696e9",
    "testharness"
   ],
   "largest-contentful-paint/first-letter-background.html": [
-   "19544c8edeedb163dc20fa9b2ef654255d050ddf",
+   "44d2a1a968083e8c91f61b33909ec115ea1b3a63",
    "testharness"
   ],
   "largest-contentful-paint/idlharness-expected.txt": [
@@ -452237,11 +452274,11 @@
    "testharness"
   ],
   "largest-contentful-paint/image-TAO.sub.html": [
-   "9409fd8fc05c338dc74a3c7bf8fe94d356679633",
+   "41c8c748619aea00c2afe67dd5983ab7601121b0",
    "testharness"
   ],
   "largest-contentful-paint/image-src-change.html": [
-   "84a49f7ea2220c43c083f91057763ae161035532",
+   "5ec860fa06f3281fd421912298e7b2c93dae19bb",
    "testharness"
   ],
   "largest-contentful-paint/invisible-images.html": [
@@ -452249,7 +452286,7 @@
    "testharness"
   ],
   "largest-contentful-paint/larger-image.html": [
-   "7ff38cf2be10c6e20fc5f2ad3d1578755cfbb903",
+   "094c2096752fa52ee0a249cd26cb97b5376edae1",
    "testharness"
   ],
   "largest-contentful-paint/larger-text.html": [
@@ -452257,15 +452294,15 @@
    "testharness"
   ],
   "largest-contentful-paint/loadTime-after-appendChild.html": [
-   "43ec9f6085d605098faeddce311b5ccbc626b073",
+   "0e40127b57683fa76392827003b15c2bb9c8d558",
    "testharness"
   ],
   "largest-contentful-paint/observe-after-untrusted-scroll.html": [
-   "b551e7632b5ce20e2bbc40758f623fac972b3b73",
+   "1b2cd1d25b5bb9da740e5127526fed41dcebfae7",
    "testharness"
   ],
   "largest-contentful-paint/observe-image.html": [
-   "a9556ebaa60d04c154c8043fe7c48fbd7ec38700",
+   "5856795cac49beea469b05ff06b57a163bc2756a",
    "testharness"
   ],
   "largest-contentful-paint/observe-text.html": [
@@ -452273,13 +452310,17 @@
    "testharness"
   ],
   "largest-contentful-paint/repeated-image.html": [
-   "d25d4735c9747cb27bffdd640e1127f9fb9c075c",
+   "82d662d330ab74ce88773257dadfb75af87451d1",
    "testharness"
   ],
   "largest-contentful-paint/resources/iframe-stores-entry.html": [
    "cd600254805570deab8447ea843657d7f268b7c5",
    "support"
   ],
+  "largest-contentful-paint/resources/largest-contentful-paint-helpers.js": [
+   "0529e227b8094656361a7ab9d5ae81a92f0e8934",
+   "support"
+  ],
   "largest-contentful-paint/supported-lcp-type.html": [
    "25d4eaa0367f45440d286c6c1c14de4458465d7b",
    "testharness"
@@ -452292,6 +452333,10 @@
    "7defcce1b6f9f2b681405988f74d3977fa3f29e8",
    "testharness"
   ],
+  "largest-contentful-paint/video-poster.html": [
+   "9ad9c4cdfd09bfb3c3de4b77c29fff31a2d7089f",
+   "testharness"
+  ],
   "layout-instability/buffer-layout-shift.html": [
    "0cfce2f7124226cf4256284c1238ba1ef024c42b",
    "testharness"
@@ -493245,7 +493290,7 @@
    "testharness"
   ],
   "web-animations/timing-model/timelines/document-timelines.html": [
-   "f45865ac7c0e37abeddee73ad5435dcc8acd6e89",
+   "4023bba55612b689d98a9773c9c6fafe11408e2b",
    "testharness"
   ],
   "web-animations/timing-model/timelines/timelines.html": [
diff --git a/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js b/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js
index 7afa606..6986f84 100644
--- a/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js
+++ b/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js
@@ -100,7 +100,7 @@
   from the outer-most to inner-most environment settings objects.
 
   For example:
-    [{sourceContextType: "srcdoc"}, {sourceContextType: "classic-worker"}]
+    [{sourceContextType: "srcdoc"}, {sourceContextType: "worker-classic"}]
   means that a subresource request is to be sent from
   a classic dedicated worker created from <iframe srcdoc>
   inside the top-level HTML document.
@@ -1059,19 +1059,19 @@
     "iframe": { // <iframe src="same-origin-URL"></iframe>
       invoker: invokeFromIframe,
     },
-    "classic-worker": {
+    "worker-classic": {
       // Classic dedicated worker loaded from same-origin.
       invoker: invokeFromWorker.bind(undefined, false, {}),
     },
-    "classic-data-worker": {
+    "worker-classic-data": {
       // Classic dedicated worker loaded from data: URL.
       invoker: invokeFromWorker.bind(undefined, true, {}),
     },
-    "module-worker": {
+    "worker-module": {
       // Module dedicated worker loaded from same-origin.
       invoker: invokeFromWorker.bind(undefined, false, {type: 'module'}),
     },
-    "module-data-worker": {
+    "worker-module-data": {
       // Module dedicated worker loaded from data: URL.
       invoker: invokeFromWorker.bind(undefined, true, {type: 'module'}),
     },
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block-expected.txt
deleted file mode 100644
index a6bd2954..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-none-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'none' should block rendering in nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block-expected.txt
deleted file mode 100644
index 1ebf8dd3..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-self-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'same' should block render in same-origin nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block-expected.txt
deleted file mode 100644
index c3dad9422..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-cross-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should block or allow rendering in nested frames as appropriate. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block-expected.txt
deleted file mode 100644
index a6bd2954..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-none-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'none' should block rendering in nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block-expected.txt
deleted file mode 100644
index 1ebf8dd3..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-self-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'same' should block render in same-origin nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow-expected.txt
deleted file mode 100644
index 89fc6677..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-star-allow-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value '*' should render in nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow-expected.txt
deleted file mode 100644
index c3dad9422..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-allow-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should block or allow rendering in nested frames as appropriate. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block-expected.txt
deleted file mode 100644
index c3dad9422..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-same-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should block or allow rendering in nested frames as appropriate. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block-expected.txt
deleted file mode 100644
index 93545bf88..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-cross-in-sandboxed-cross-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should compare against each frame's origin rather than URL, so a nested frame with a sandboxed parent frame should be blocked due to the parent having a unique origin. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block-expected.txt
deleted file mode 100644
index a6bd2954..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-none-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'none' should block rendering in nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block-expected.txt
deleted file mode 100644
index 1ebf8dd3..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-self-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'same' should block render in same-origin nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block-expected.txt
deleted file mode 100644
index c3dad9422..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should block or allow rendering in nested frames as appropriate. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block-expected.txt
deleted file mode 100644
index a6bd2954..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-none-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'none' should block rendering in nested frames. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block-expected.txt
deleted file mode 100644
index c3dad9422..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-same-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL value should block or allow rendering in nested frames as appropriate. assert_unreached: Inner IFrame msg: undefined Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-none-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-none-block-expected.txt
deleted file mode 100644
index 0cbda57d..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-none-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'none' should block rendering. assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-self-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-self-block-expected.txt
deleted file mode 100644
index 35eb6ac..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-self-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a value 'self' should block rendering. assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin-expected.txt
deleted file mode 100644
index 62c22f6..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-star-allow-crossorigin-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with '*' should allow rendering. assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-url-block-expected.txt b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-url-block-expected.txt
deleted file mode 100644
index d787651..0000000
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/frame-ancestors-url-block-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL A 'frame-ancestors' CSP directive with a URL which doesn't match this origin should be blocked. assert_unreached: The IFrame should have been blocked (or cross-origin). It wasn't. Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js
index dde04f06..79b761a 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/frame-ancestors/support/frame-ancestors-test.sub.js
@@ -26,7 +26,7 @@
         window.parent.postMessage(e.data, "*");
     else
         if (e.data.type === 'test_result')
-            endTest(e.data.failed, "Inner IFrame msg: " + e.data.msg);
+            endTest(e.data.failed, "Inner IFrame msg: " + e.data.message);
 });
 
 function injectNestedIframe(policy, parent, child, expectation, isSandboxed) {
@@ -67,6 +67,7 @@
         var failed = true;
         var message = "";
         try {
+            ev.target.contentWindow.location.href;
             if (expectBlock) {
                 message = "The IFrame should have been blocked (or cross-origin). It wasn't.";
                 failed = true;
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/scrollable-overflow.tentative.html b/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/scrollable-overflow.tentative.html
new file mode 100644
index 0000000..8835455
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/linebox/scrollable-overflow.tentative.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=996847">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<meta name=assert content="This test checks that bottom half-leading of a line-box doesn't contribute to the scrollable overflow.">
+<p>Test passes if there is a filled green square.</p>
+<div style="overflow-y: auto; width: 100px; height: 100px;">
+  <div style="line-height: 120px; height: 100px; background: green;">
+    <span style="display: inline-block; width: 100px; height: 50px;"></span>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-001.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-001.html
index 0dad9ea7..0987806 100644
--- a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-001.html
@@ -7,7 +7,8 @@
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <meta name="flags" content="">
 <meta name="assert" content="The 'aspect-ratio' property with prefix 'min' set '59/79' means that the minimum of ratio is '59/79',
-only and only if the value of the 'width' to the value of the 'height' is greater than value of 'min-aspect-ratio', the style sheet will be applied.">
+only and only if the value of the 'width' to the value of the 'height' is greater than value of 'min-aspect-ratio', the style sheet will be applied.
+The test runner will run this test in a 800/600 viewport (https://github.com/web-platform-tests/wpt/pull/12695).">
 <style>
   div {
     background-color: red;
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-003.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-003.html
index 76bebd7..1486810 100644
--- a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-003.html
@@ -6,7 +6,9 @@
 <link rel="help" title="4.6. aspect-ratio" href="http://www.w3.org/TR/css3-mediaqueries/#aspect-ratio">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <meta name="flags" content="">
-<meta name="assert" content="The 'aspect-ratio' property with prefix 'max' set '1280/720' means that the maximum of ratio is '1280/720', only and only if the value of the 'width' to the value of the 'height' is lower than value of 'max-aspect-ratio', the style sheet will be applied.">
+<meta name="assert" content="The 'aspect-ratio' property with prefix 'max' set '1280/720' means that the maximum of ratio is '1280/720',
+only and only if the value of the 'width' to the value of the 'height' is lower than value of 'max-aspect-ratio', the style sheet will be applied.
+The test runner will run this test in a 800/600 viewport (https://github.com/web-platform-tests/wpt/pull/12695)">
 <style>
   div {
     background-color: red;
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-005.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-005.html
new file mode 100644
index 0000000..2c9d9ed
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-005.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Media Queries Test: max-aspect-ratio - 1280.1/720.01 ('aspect-ratio' property with prefix 'max')</title>
+<link rel="author" title="Joel Olsson" href="mailto:joel_1st@hotmail.com">
+<link rel="help" title="aspect-ratio" href="https://drafts.csswg.org/mediaqueries-4/#aspect-ratio">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="flags" content="">
+<meta name="assert" content="The 'aspect-ratio' property with prefix 'max' set 1280.1/720.01. Only and only if the value of the 'width'
+to the value of the 'height' is lower than value of 'max-aspect-ratio', the style sheet will be applied.
+The test runner will run this test in a 800/600 viewport (https://github.com/web-platform-tests/wpt/pull/12695)">
+<style>
+  div {
+    background-color: red;
+    height: 100px;
+    width: 100px;
+  }
+  @media screen and (max-aspect-ratio: 1280.1/720.01) {
+    div {
+      background-color: green;
+    }
+  }
+</style>
+<body>
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+  <div></div>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-006.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-006.html
new file mode 100644
index 0000000..188a65b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/aspect-ratio-006.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Media Queries Test: min-aspect-ratio - 0.7 ('aspect-ratio' property with prefix 'min')</title>
+<link rel="author" title="Joel Olsson" href="mailto:joel_1st@hotmail.com">
+<link rel="help" title="aspect-ratio" href="https://drafts.csswg.org/mediaqueries-4/#aspect-ratio">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="flags" content="">
+<meta name="assert" content="The 'aspect-ratio' property with prefix 'min' set '0.7' means that the minimum of ratio is '0.7',
+only and only if the value of the 'width' to the value of the 'height' is greater than value of 'min-aspect-ratio', the style sheet will be applied.
+The test runner will run this test in a 800/600 viewport (https://github.com/web-platform-tests/wpt/pull/12695)">
+<style>
+  div {
+    background-color: red;
+    height: 100px;
+    width: 100px;
+  }
+  @media screen and (min-aspect-ratio: 0.2) {
+    div {
+      background-color: green;
+    }
+  }
+</style>
+<body>
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+  <div></div>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries-expected.txt b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries-expected.txt
index 00ae682..cf0e2c2 100644
--- a/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries-expected.txt
@@ -1,6 +1,6 @@
 This is a testharness.js-based test.
 Harness Error. harness_status.status = 1 , harness_status.message = Uncaught Error: assert_not_equals: overflow-block should be equivalent to not (overflow-block: none) got disallowed value false
-Found 762 tests; 566 PASS, 196 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 772 tests; 576 PASS, 196 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS subtest_1
 FAIL subtest_2 assert_true: expected true got false
 PASS subtest_3
@@ -599,8 +599,6 @@
 PASS subtest_596
 PASS subtest_597
 PASS subtest_598
-PASS monochrome_and_color
-PASS find_depth
 PASS subtest_599
 PASS subtest_600
 PASS subtest_601
@@ -611,6 +609,8 @@
 PASS subtest_606
 PASS subtest_607
 PASS subtest_608
+PASS monochrome_and_color
+PASS find_depth
 PASS subtest_609
 PASS subtest_610
 PASS subtest_611
@@ -684,7 +684,6 @@
 PASS subtest_679
 PASS subtest_680
 PASS subtest_681
-PASS find_resolution
 PASS subtest_682
 PASS subtest_683
 PASS subtest_684
@@ -695,6 +694,7 @@
 PASS subtest_689
 PASS subtest_690
 PASS subtest_691
+PASS find_resolution
 PASS subtest_692
 PASS subtest_693
 PASS subtest_694
@@ -757,11 +757,21 @@
 PASS subtest_751
 PASS subtest_752
 PASS subtest_753
-FAIL subtest_754 assert_true: expected true got false
-FAIL subtest_755 assert_true: expected true got false
-FAIL subtest_756 assert_true: expected true got false
-FAIL subtest_757 assert_true: expected true got false
-FAIL subtest_758 assert_true: expected true got false
+PASS subtest_754
+PASS subtest_755
+PASS subtest_756
+PASS subtest_757
+PASS subtest_758
 PASS subtest_759
+PASS subtest_760
+PASS subtest_761
+PASS subtest_762
+PASS subtest_763
+FAIL subtest_764 assert_true: expected true got false
+FAIL subtest_765 assert_true: expected true got false
+FAIL subtest_766 assert_true: expected true got false
+FAIL subtest_767 assert_true: expected true got false
+FAIL subtest_768 assert_true: expected true got false
+PASS subtest_769
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html
index d08d83c34..d368acf 100644
--- a/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html
+++ b/third_party/blink/web_tests/external/wpt/css/mediaqueries/test_media_queries.html
@@ -318,6 +318,11 @@
       expression_should_not_be_parseable(feature + ": -1/1");
       expression_should_not_be_parseable(feature + ": 1/-1");
       expression_should_not_be_parseable(feature + ": -1/-1");
+      expression_should_not_be_parseable(feature + ": -1/-1");
+      expression_should_not_be_parseable(feature + ": -1/-1");
+      expression_should_not_be_parseable(feature + ": invalid");
+      expression_should_not_be_parseable(feature + ": 1 / invalid");
+      expression_should_not_be_parseable(feature + ": 1 invalid");
     }
 
     var is_monochrome = query_applies("all and (min-monochrome: 1)");
diff --git a/third_party/blink/web_tests/external/wpt/loading/lazyload/original-referrer-policy-applied-tentative.sub-expected.txt b/third_party/blink/web_tests/external/wpt/loading/lazyload/original-referrer-policy-applied-tentative.sub-expected.txt
new file mode 100644
index 0000000..d07bc4b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/loading/lazyload/original-referrer-policy-applied-tentative.sub-expected.txt
@@ -0,0 +1,21 @@
+main frame - DidStartNavigation
+main frame - ReadyToCommitNavigation
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Deferred iframes and images with loading='lazy' use the original referrer-policy specified at the parse time
+frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: 
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - BeginNavigation request to 'http://web-platform.test:8001/xhr/resources/echo-headers.py', http method GET
+frame "<!--framePath //<!--frame0-->-->" - DidStartNavigation
+frame "<!--framePath //<!--frame0-->-->" - ReadyToCommitNavigation
+frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: 
+frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
+frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
+frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
+This is a testharness.js-based test.
+PASS Test that when deferred iframe is loaded, it uses the referrer-policy specified at parse time.
+FAIL Test that when deferred img is loaded, it uses the referrer-policy specified at parse time. assert_unreached: The image load should not fail, by sending the wrong referer header. Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js b/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js
index eb9fc13..ee34c49 100644
--- a/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js
+++ b/third_party/blink/web_tests/external/wpt/mixed-content/generic/mixed-content-test-case.js
@@ -73,7 +73,7 @@
     // We bridge this inconsistency here, and will later pass these information
     // directly from the generated tests and remove this conversion here.
     subresourceType = 'fetch-request';
-    sourceContextList = [{sourceContextType: 'classic-data-worker'}];
+    sourceContextList = [{sourceContextType: 'worker-classic-data'}];
   }
 
   const originTypeConversion = {
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html
index f45865ac..4023bba 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html
+++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html
@@ -9,10 +9,6 @@
 <script>
 'use strict';
 
-function matchUnconditionalClamping(timestamp) {
-  return parseFloat((Math.floor(timestamp / .02) * .02).toPrecision(8), 10);
-}
-
 async_test(t => {
   assert_greater_than_equal(document.timeline.currentTime, 0,
     'The current time is initially is positive or zero');
@@ -32,7 +28,7 @@
   // so we use requestAnimationFrame instead.
   window.requestAnimationFrame(rafTime => {
     t.step(() => {
-      assert_equals(document.timeline.currentTime, matchUnconditionalClamping(rafTime),
+      assert_equals(document.timeline.currentTime, rafTime,
                     'The current time matches requestAnimationFrame time');
     });
     t.done();
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
index 102a7be6..fac7880 100644
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
+++ b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
@@ -8,7 +8,7 @@
       forced colors mode.
     </text>
     <rect x="0" height="60" y="30" width="180" style="fill: red; stroke: blue;"/>
-    <foreignObject x="20" y="30" width="160" height="160">
+    <foreignObject x="20" y="100" width="160" height="160">
       <div xmlns="http://www.w3.org/1999/xhtml" style="color: blue;">
         This text should be WindowText color in forced colors mode.
       </div>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18.html
index 5f7e1235..66ca6a7 100644
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18.html
+++ b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-18.html
@@ -13,7 +13,7 @@
       forced colors mode.
     </text>
     <rect x="0" height="60" y="30" width="180" style="fill: red; stroke: blue;"/>
-    <foreignObject x="20" y="30" width="160" height="160">
+    <foreignObject x="20" y="100" width="160" height="160">
       <div xmlns="http://www.w3.org/1999/xhtml" style="color: blue;">
         This text should be WindowText color in forced colors mode.
       </div>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt
deleted file mode 100644
index 44ff5ffd..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks that background color alpha channels are preserved in forced colors mode. assert_equals: expected "rgba(0, 0, 0, 0.3)" but got "rgba(114, 173, 218, 0.3)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..56bc119a
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic.html
new file mode 100644
index 0000000..bd73c66
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-appearance-basic.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../resources/common.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Date: <input type="date" /></li>
+</ul>
+
+<!-- disabled, readonly -->
+<ul>
+  <li>Date disabled: <input type="date" disabled/></li>
+  <li>Date readonly: <input type="date" readonly/></li>
+</ul>
+
+<!-- RTL -->
+<ul>
+  <li>Date RTL: <input type="date" value="2019-02-14" dir="rtl"/></li>
+</ul>
+
+<!-- font-size, font-weight -->
+<ul>
+  <li>Date font-size, font-weight: <input type="date" value="2019-02-14" style="font-size: 36px; font-weight: bold;"/> </li>
+</ul>
+
+<!-- hover -->
+<ul>
+  <li>Date hover: <input type="date" id="hoverTarget" value="2019-02-14"/></li>
+</ul>
+
+<!-- small width -->
+<ul>
+  <li>Date width: 10px: <input type="date" value="2019-02-14" style="width: 10px;"/> </li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>Date zoom: 1.5: <input type="date" style="zoom: 1.5;"/></li>
+  <li>Date zoom: 3: <input type="date" style="zoom: 3;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+runAfterLayoutAndPaint(function() {
+  var target = document.getElementById('hoverTarget');
+  hoverOverElement(target);
+}, true);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp-expected.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp-expected.html
new file mode 100644
index 0000000..6a0d0350b3
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp-expected.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<head>
+<style>
+#custom-icon::-webkit-calendar-picker-indicator {
+  background-image: none;
+}
+</style>
+</head>
+<body>
+
+<!-- no style for reference -->
+<input type="date" />
+
+<!-- date with custom icon blocked by CSP -->
+<input type="data" id="custom-icon"/>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp.html
new file mode 100644
index 0000000..6cc5b5b9
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/date-with-csp.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<style>
+#custom-icon::-webkit-calendar-picker-indicator {
+  background-image: -webkit-image-set(url(resources/time_icon.svg) 1x);
+}
+</style>
+<link rel="match" href="date-with-csp-expected.html">
+<meta http-equiv="content-security-policy" content="default-src 'none'">
+</head>
+<body>
+
+<!-- no style for reference -->
+<input type="date" />
+
+<!-- date with custom icon blocked by CSP -->
+<input type="data" id="custom-icon"/>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/date/resources/time_icon.svg b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/resources/time_icon.svg
new file mode 100644
index 0000000..464453a
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/date/resources/time_icon.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7 14C6.35417 14 5.73177 13.9167 5.13281 13.75C4.53906 13.5833 3.98177 13.349 3.46094 13.0469C2.94531 12.7396 2.47396 12.375 2.04688 11.9531C1.625 11.526 1.26042 11.0547 0.953125 10.5391C0.651042 10.0182 0.416667 9.46094 0.25 8.86719C0.0833333 8.26823 0 7.64583 0 7C0 6.35417 0.0833333 5.73438 0.25 5.14062C0.416667 4.54167 0.651042 3.98438 0.953125 3.46875C1.26042 2.94792 1.625 2.47656 2.04688 2.05469C2.47396 1.6276 2.94531 1.26302 3.46094 0.960938C3.98177 0.653646 4.53906 0.416667 5.13281 0.25C5.73177 0.0833333 6.35417 0 7 0C7.64583 0 8.26562 0.0833333 8.85938 0.25C9.45833 0.416667 10.0156 0.653646 10.5312 0.960938C11.0521 1.26302 11.5234 1.6276 11.9453 2.05469C12.3724 2.47656 12.737 2.94792 13.0391 3.46875C13.3464 3.98438 13.5833 4.54167 13.75 5.14062C13.9167 5.73438 14 6.35417 14 7C14 7.64583 13.9167 8.26823 13.75 8.86719C13.5833 9.46094 13.3464 10.0182 13.0391 10.5391C12.737 11.0547 12.3724 11.526 11.9453 11.9531C11.5234 12.375 11.0521 12.7396 10.5312 13.0469C10.0156 13.349 9.45833 13.5833 8.85938 13.75C8.26562 13.9167 7.64583 14 7 14ZM7 1C6.17188 1 5.39323 1.15885 4.66406 1.47656C3.9401 1.78906 3.30469 2.21875 2.75781 2.76562C2.21615 3.30729 1.78646 3.94271 1.46875 4.67188C1.15625 5.39583 1 6.17188 1 7C1 7.82812 1.15625 8.60677 1.46875 9.33594C1.78646 10.0599 2.21615 10.6953 2.75781 11.2422C3.30469 11.7839 3.9401 12.2135 4.66406 12.5312C5.39323 12.8438 6.17188 13 7 13C7.82812 13 8.60417 12.8438 9.32812 12.5312C10.0573 12.2135 10.6927 11.7839 11.2344 11.2422C11.7812 10.6953 12.2109 10.0599 12.5234 9.33594C12.8411 8.60677 13 7.82812 13 7C13 6.17188 12.8411 5.39583 12.5234 4.67188C12.2109 3.94271 11.7812 3.30729 11.2344 2.76562C10.6927 2.21875 10.0573 1.78906 9.32812 1.47656C8.60417 1.15885 7.82812 1 7 1ZM7 7V3H6V8H10V7H7Z" fill="#101010"/>
+</svg>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..868d1c7a
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic.html
new file mode 100644
index 0000000..7f8aae7
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../resources/common.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Datetime-local: <input type="datetime-local" /></li>
+</ul>
+
+<!-- disabled, readonly -->
+<ul>
+  <li>Datetime-local disabled: <input type="datetime-local" disabled/></li>
+  <li>Datetime-local readonly: <input type="datetime-local" readonly/></li>
+</ul>
+
+<!-- RTL -->
+<ul>
+  <li>Datetime-local RTL: <input type="datetime-local" value="2019-02-14T13:02" dir="rtl"/></li>
+</ul>
+
+<!-- font-size, font-weight -->
+<ul>
+  <li>Datetime-local font-size, font-weight: <input type="datetime-local" value="2019-02-14T13:02" style="font-size: 36px; font-weight: bold;"/> </li>
+</ul>
+
+<!-- hover -->
+<ul>
+  <li>Datetime-local hover: <input type="datetime-local" id="hoverTarget" value="2019-02-14T13:02"/></li>
+</ul>
+
+<!-- small width -->
+<ul>
+  <li>Datetime-local width: 10px: <input type="datetime-local" style="width: 10px;"/> </li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>Datetime-local zoom: 1.5: <input type="datetime-local" style="zoom: 1.5;"/></li>
+  <li>Datetime-local zoom: 3: <input type="datetime-local" style="zoom: 3;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+runAfterLayoutAndPaint(function() {
+  var target = document.getElementById('hoverTarget');
+  hoverOverElement(target);
+}, true);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..20f99448
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic.html
new file mode 100644
index 0000000..e92c586d
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/month/month-appearance-basic.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../resources/common.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Month: <input type="month" /></li>
+</ul>
+
+<!-- disabled, readonly -->
+<ul>
+  <li>Month disabled: <input type="month" disabled/></li>
+  <li>Month readonly: <input type="month" readonly/></li>
+</ul>
+
+<!-- RTL -->
+<ul>
+  <li>Month RTL: <input type="month" value="2019-02" dir="rtl"/></li>
+</ul>
+
+<!-- font-size, font-weight -->
+<ul>
+  <li>Month font-size, font-weight: <input type="month" value="2019-02" style="font-size: 36px; font-weight: bold;"/> </li>
+</ul>
+
+<!-- hover -->
+<ul>
+  <li>Month hover: <input type="month" id="hoverTarget" value="2019-02"/></li>
+</ul>
+
+<!-- small width -->
+<ul>
+  <li>Month width: 10px: <input type="month" style="width: 10px;"/> </li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>Month zoom: 1.5: <input type="month" style="zoom: 1.5;"/></li>
+  <li>Month zoom: 3: <input type="month" style="zoom: 3;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+runAfterLayoutAndPaint(function() {
+  var target = document.getElementById('hoverTarget');
+  hoverOverElement(target);
+}, true);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..459e1f5
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic.html
new file mode 100644
index 0000000..6c2a166
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/time/time-appearance-basic.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../resources/common.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Time: <input type="time" /></li>
+</ul>
+
+<!-- disabled, readonly -->
+<ul>
+  <li>Time disabled: <input type="time" disabled/></li>
+  <li>Time readonly: <input type="time" readonly/></li>
+</ul>
+
+<!-- RTL -->
+<ul>
+  <li>Time RTL: <input type="time" value="13:00" dir="rtl"/></li>
+</ul>
+
+<!-- font-size, font-weight -->
+<ul>
+  <li>Time font-size, font-weight: <input type="time" value="13:00" style="font-size: 36px; font-weight: bold;"/> </li>
+</ul>
+
+<!-- hover -->
+<ul>
+  <li>Time hover: <input type="time" id="hoverTarget" value="13:00"/></li>
+</ul>
+
+<!-- small width -->
+<ul>
+  <li>Time width: 10px: <input type="time" style="width: 10px;"/> </li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>Time zoom: 1.5: <input type="time" style="zoom: 1.5;"/></li>
+  <li>Time zoom: 3: <input type="time" style="zoom: 3;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+runAfterLayoutAndPaint(function() {
+  var target = document.getElementById('hoverTarget');
+  hoverOverElement(target);
+}, true);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..dd1d768f
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic.html
new file mode 100644
index 0000000..6d475cf
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/week/week-appearance-basic.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../resources/common.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Week: <input type="week" /></li>
+</ul>
+
+<!-- disabled, readonly -->
+<ul>
+  <li>Week disabled: <input type="week" disabled/></li>
+  <li>Week readonly: <input type="week" readonly/></li>
+</ul>
+
+<!-- RTL -->
+<ul>
+  <li>Week RTL: <input type="week" value="2019-W08" dir="rtl"/></li>
+</ul>
+
+<!-- font-size, font-weight -->
+<ul>
+  <li>Week font-size, font-weight: <input type="week" value="2019-W08" style="font-size: 36px; font-weight: bold;"/> </li>
+</ul>
+
+<!-- hover -->
+<ul>
+  <li>Week hover: <input type="week" id="hoverTarget" value="2019-W08"/></li>
+</ul>
+
+<!-- small width -->
+<ul>
+  <li>Week width: 10px: <input type="week" style="width: 10px;"/> </li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>Week zoom: 1.5: <input type="week" style="zoom: 1.5;"/></li>
+  <li>Week zoom: 3: <input type="week" style="zoom: 3;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+runAfterLayoutAndPaint(function() {
+  var target = document.getElementById('hoverTarget');
+  hoverOverElement(target);
+}, true);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding-expected.txt b/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding-expected.txt
new file mode 100644
index 0000000..8cfbce0
--- /dev/null
+++ b/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding-expected.txt
@@ -0,0 +1 @@
+ Should not crash
diff --git a/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding.html b/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding.html
new file mode 100644
index 0000000..db341da
--- /dev/null
+++ b/third_party/blink/web_tests/fast/text/nowrap-with-saturated-padding.html
@@ -0,0 +1,12 @@
+<style>
+label { white-space: nowrap;  }
+meter { padding-right: 99999999px; }
+</style>
+<script>
+if (window.testRunner)
+  testRunner.dumpAsText();
+</script>
+<label>
+<meter></meter>
+</label>
+Should not crash
\ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/worker/worker-console-expected.txt b/third_party/blink/web_tests/inspector-protocol/worker/worker-console-expected.txt
index 0464a35..0518efd 100644
--- a/third_party/blink/web_tests/inspector-protocol/worker/worker-console-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/worker/worker-console-expected.txt
@@ -3,26 +3,26 @@
 === console.log event won't get lost despite worker.terminate. ===
 Starting worker
 -> Posting to worker: message0 (posted after starting worker)
-<- Log from page: message0 (posted after starting worker)
 Terminating worker
+<- Log from page: message0 (posted after starting worker)
 
 === Scenario with autoattach enabled and stopped. ===
 Starting worker
 -> Posting to worker: message1
-<- Log from page: message1
 Starting autoattach
 child session for worker created
 Sending Runtime.enable to worker
 -> Posting to worker: message2 (posted after runtime enabled)
-<-- Console API from worker: message1
-<-- Console API from worker: message2 (posted after runtime enabled)
-<- Log from page: message2 (posted after runtime enabled)
 -> Posting to worker: throw1 (posted after runtime enabled; yields exception in worker)
 Stopping autoattach
-<- Log from page: Uncaught (in promise) throw1 (posted after runtime enabled; yields exception in worker)
 -> Posting to worker: message3 (posted after auto-attach)
-<- Log from page: message3 (posted after auto-attach)
 Terminating worker
+<- Log from page: message1
+<- Log from page: message2 (posted after runtime enabled)
+<- Log from page: Uncaught (in promise) throw1 (posted after runtime enabled; yields exception in worker)
+<- Log from page: message3 (posted after auto-attach)
+<-- Console API from worker: message1
+<-- Console API from worker: message2 (posted after runtime enabled)
 
 === Scenario with autoattach from the get-go. ===
 Starting autoattach
@@ -31,17 +31,17 @@
 -> Posting to worker: message4 (posted before worker's runtime agent enabled)
 Sending Runtime.enable to worker
 -> Posting to worker: message5 (posted after worker's runtime agent enabled)
+Terminating worker
 <- Log from page: message4 (posted before worker's runtime agent enabled)
+<- Log from page: message5 (posted after worker's runtime agent enabled)
 <-- Console API from worker: message4 (posted before worker's runtime agent enabled)
 <-- Console API from worker: message5 (posted after worker's runtime agent enabled)
-<- Log from page: message5 (posted after worker's runtime agent enabled)
-Terminating worker
 
 === New worker, with auto-attach still enabled. ===
 Starting worker
 child session for worker created
 -> Posting to worker: message6 (posted just before worker termination)
 Terminating worker
-<- Log from page: message6 (posted just before worker termination)
 Stopping autoattach
+<- Log from page: message6 (posted just before worker termination)
 
diff --git a/third_party/blink/web_tests/inspector-protocol/worker/worker-console.js b/third_party/blink/web_tests/inspector-protocol/worker/worker-console.js
index a099862..0fb4f0f4 100644
--- a/third_party/blink/web_tests/inspector-protocol/worker/worker-console.js
+++ b/third_party/blink/web_tests/inspector-protocol/worker/worker-console.js
@@ -2,6 +2,16 @@
   var {page, session, dp} = await testRunner.startBlank(
       `Tests how console messages from worker get into page's console once worker is destroyed.`);
 
+  // TODO(johannes): Within this test, it appears that it's necessary to
+  // wait until messages have trickled into the page log
+  // via dp.Log.onEntryAdded or into the console API
+  // via childSession.protocol.Runtime.onConsoleAPICalled, before calling
+  // worker.terminate, or otherwise the messages may be dropped, or even
+  // appear much later, after another worker has been started.
+  // For now, this test is non-flaky primarily by sprinkling several
+  // Promise.all calls around postToWorker. Further investigation /
+  // clarification / research may be needed.
+
   await session.evaluate(`
     let worker;
 
@@ -13,7 +23,7 @@
       return new Promise(resolve => {
         worker = new Worker(
             '${testRunner.url('../resources/worker-console-worker.js')}');
-        worker.onmessage = () => { resolve(); }
+        worker.onmessage = resolve;
       });
     }
 
@@ -26,125 +36,161 @@
     // anyway. This is much of the point of this test.
     function postToWorker(message) {
       return new Promise(resolve => {
-        worker.onmessage = () => { resolve(); };
+        worker.onmessage = resolve;
         worker.postMessage(message);
       });
     }
   `);
 
+  // To avoid flaky test output, we emit messages into these three different
+  // logs, and flush them after each section of the test.
+  const clientLog = [];
+  const pageLog = [];
+  const consoleLog = [];
+  function flushLogs() {
+    for (let line of clientLog) {
+      testRunner.log(line);
+    }
+    clientLog.length = 0;
+    for (let line of pageLog) {
+      testRunner.log('<- Log from page: ' + line);
+    }
+    pageLog.length = 0;
+    for (let line of consoleLog) {
+      testRunner.log('<-- Console API from worker: ' + line);
+    }
+    consoleLog.length = 0;
+  }
+
   await dp.Log.enable();
-  dp.Log.onEntryAdded((event) => {
-    testRunner.log('<- Log from page: ' + event.params.entry.text);
-  });
+  dp.Log.onEntryAdded((event) => { pageLog.push(event.params.entry.text); });
 
   function postToWorker(message) {
-    testRunner.log('-> Posting to worker: ' + message);
+    clientLog.push('-> Posting to worker: ' + message);
     return session.evaluateAsync('postToWorker("' + message + '")');
   }
 
   {
-    testRunner.log(
+    clientLog.push(
         "\n=== console.log event won't get lost despite worker.terminate. ===");
-    testRunner.log('Starting worker');
+    clientLog.push('Starting worker');
     await session.evaluateAsync('startWorker()');
-    await postToWorker('message0 (posted after starting worker)');
-    testRunner.log('Terminating worker');
-    await session.evaluate('worker.terminate()');
+    await Promise.all([
+      postToWorker('message0 (posted after starting worker)'),
+      dp.Log.onceEntryAdded()]);
     // The key part of this test is that its expectation contains
-    // "<- Log from page: message1", even though we terminated the
-    // worker without awaiting the log event (postToWorker only ensures
-    // that the message was echoed back to the page).
+    // "<- Log from page: message0 (posted after starting worker)", even
+    // though we terminated the worker without awaiting the log event
+    // (postToWorker only ensures that the message was echoed back to the page).
+    clientLog.push('Terminating worker');
+    await session.evaluate('worker.terminate()');
+    flushLogs();
   }
 
   {
-    testRunner.log(
+    clientLog.push(
         '\n=== Scenario with autoattach enabled and stopped. ===');
-    testRunner.log('Starting worker');
+    clientLog.push('Starting worker');
     await session.evaluateAsync('startWorker()');
-    await postToWorker('message1');
+    await Promise.all([postToWorker('message1'), dp.Log.onceEntryAdded()]);
 
     // Now we call Target.setAutoAttach, which will immediately generate
     // an event that we're attached; which we receive below to create the
     // childSession instance.
-    testRunner.log('Starting autoattach');
+    clientLog.push('Starting autoattach');
     dp.Target.setAutoAttach({
       autoAttach: true, waitForDebuggerOnStart: false, flatten: true});
     const childSession = session.createChild(
         (await dp.Target.onceAttachedToTarget()).params.sessionId);
     childSession.protocol.Runtime.onConsoleAPICalled((event) => {
-      testRunner.log('<-- Console API from worker: ' +
-                     event.params.args[0].value);
+      consoleLog.push(event.params.args[0].value);
     });
-    testRunner.log('child session for worker created');
+    clientLog.push('child session for worker created');
 
-    testRunner.log('Sending Runtime.enable to worker');
+    clientLog.push('Sending Runtime.enable to worker');
     childSession.protocol.Runtime.enable();
+    await childSession.protocol.Runtime.onceConsoleAPICalled();
 
-    await postToWorker('message2 (posted after runtime enabled)');
-    await postToWorker('throw1 (posted after runtime enabled; ' +
-                       'yields exception in worker)');
+    await Promise.all([
+      postToWorker('message2 (posted after runtime enabled)'),
+      dp.Log.onceEntryAdded(),
+      childSession.protocol.Runtime.onceConsoleAPICalled()]);
+    await Promise.all([
+      postToWorker('throw1 (posted after runtime enabled; ' +
+                   'yields exception in worker)'),
+      dp.Log.onceEntryAdded()]);
 
     // This unregisters the child session, so we stop getting the console API
     // calls, but still receive the log messages for the page.
-    testRunner.log('Stopping autoattach');
+    clientLog.push('Stopping autoattach');
     await dp.Target.setAutoAttach({autoAttach: false,
                                    waitForDebuggerOnStart: false});
-    await postToWorker('message3 (posted after auto-attach)');
-    testRunner.log('Terminating worker');
+    await Promise.all([
+      postToWorker('message3 (posted after auto-attach)'),
+      dp.Log.onceEntryAdded()]);
+    clientLog.push('Terminating worker');
+    flushLogs();
     await session.evaluate('worker.terminate()');
   }
 
   {
-    testRunner.log(
+    clientLog.push(
         '\n=== Scenario with autoattach from the get-go. ===');
     // This time we start the worker only after Target.setAutoAttach, so
     // we may await the autoattach response.
-    testRunner.log('Starting autoattach');
+    clientLog.push('Starting autoattach');
     await dp.Target.setAutoAttach({
       autoAttach: true, waitForDebuggerOnStart: false, flatten: true});
 
-    testRunner.log('Starting worker');
+    clientLog.push('Starting worker');
     session.evaluate('startWorker()');
     const childSession = session.createChild(
         (await dp.Target.onceAttachedToTarget()).params.sessionId);
     childSession.protocol.Runtime.onConsoleAPICalled((event) => {
-      testRunner.log('<-- Console API from worker: ' +
-                     event.params.args[0].value);
+      consoleLog.push(event.params.args[0].value);
     });
-    testRunner.log('child session for worker created');
+    clientLog.push('child session for worker created');
 
     // Here, we test the behavior of posting before / after Runtime.enable.
-    await postToWorker(
-        "message4 (posted before worker's runtime agent enabled)");
-    testRunner.log('Sending Runtime.enable to worker');
+    await Promise.all([
+      postToWorker("message4 (posted before worker's runtime agent enabled)"),
+      dp.Log.onceEntryAdded()]);
+
+    clientLog.push('Sending Runtime.enable to worker');
     childSession.protocol.Runtime.enable();
-    await postToWorker(
-        "message5 (posted after worker's runtime agent enabled)");
-    testRunner.log('Terminating worker');
+    await childSession.protocol.Runtime.onceConsoleAPICalled();
+    await Promise.all([
+      postToWorker("message5 (posted after worker's runtime agent enabled)"),
+      childSession.protocol.Runtime.onceConsoleAPICalled(),
+      dp.Log.onceEntryAdded()]);
+    clientLog.push('Terminating worker');
+    flushLogs();
     await session.evaluate('worker.terminate()');
   }
 
   {
-    testRunner.log(
+    clientLog.push(
         '\n=== New worker, with auto-attach still enabled. ===');
-    testRunner.log('Starting worker');
+    clientLog.push('Starting worker');
     session.evaluate('startWorker()');
     const childSession = session.createChild(
         (await dp.Target.onceAttachedToTarget()).params.sessionId);
     childSession.protocol.Runtime.onConsoleAPICalled((event) => {
-      testRunner.log('<-- Console API from worker: ' +
-                     event.params.args[0].value);
+      consoleLog.push(event.params.args[0].value);
     });
-    testRunner.log('child session for worker created');
+    clientLog.push('child session for worker created');
 
-    await postToWorker('message6 (posted just before worker termination)');
+    await Promise.all([
+      postToWorker('message6 (posted just before worker termination)'),
+      dp.Log.onceEntryAdded()]);
 
-    testRunner.log('Terminating worker');
+    clientLog.push('Terminating worker');
+    clientLog.push('Stopping autoattach');
+    flushLogs();
     await session.evaluate('worker.terminate()');
 
-    testRunner.log('Stopping autoattach');
-    await dp.Target.setAutoAttach({autoAttach: false,
-                                   waitForDebuggerOnStart: false});
+    dp.Target.setAutoAttach({autoAttach: false,
+                             waitForDebuggerOnStart: false});
   }
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..e5e61e4
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..be67064d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..c653f9f8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..1243a7af
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..9ae712fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 7ce5bef..e74ae45 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index f20b199..0a513e5 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index f20b199..0a513e5 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index 4edd1b3..e427f962 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 136c580..25bbe0e 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index 0a49e19..8db9f9b 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index b6bac0a..d2dc229 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..1db676e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..7c59657
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..6d0a5d1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..0408090
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..6696c25
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..e2233d6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..dc83091
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..e0a0242
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..c5cea92
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..8a00981
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 1606abd..34ce0a4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index f733abe..94f4cfe 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index f733abe..94f4cfe 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index b854a9a..a164f0e 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 115ff473..07803f4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index 03a5c4a..b87b1cd 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index e3252da3..3839e97 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..9afb7e3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..68638fc
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..3d9bc5cb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..092a06f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..6d00316
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 1606abd..34ce0a4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index 2d34bb6..f8cb9061 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index 2d34bb6..f8cb9061 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index 384b9f0..abc71f5 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 361c7c2..8363ebb 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index c1ac6850..157f2941 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 39e8bb9..b8b5462 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..0cb7eb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..92acff7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..bbe55c7f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..1d7d3e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..367d7c2d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 1606abd..34ce0a4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index 77307a2..c51739a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index 77307a2..c51739a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index f95854f..d18adf1 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 0aec8266..e8bf26be 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index 8c3a46a0..232b5168 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 74f97842..2ce0952 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..0cb7eb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..92acff7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..bbe55c7f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..1d7d3e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..367d7c2d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 1606abd..34ce0a4 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index 07fe60a..997116bb 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index 07fe60a..997116bb 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index 930ea3ae..feed194e 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 093b0e1..76e4f19 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index df6ebb8..e2495c3 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 5dd0905b..fc04413f 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..0cb7eb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..92acff7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..bbe55c7f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..1d7d3e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..367d7c2d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..18e0024
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..74e7ae5
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..ce8783c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..220c1ca1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..07267ef
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index 1606abd..34ce0a4 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index 07fe60a..997116bb 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index 07fe60a..997116bb 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index 930ea3ae..feed194e 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index 093b0e1..76e4f19 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index df6ebb8..e2495c3 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 5dd0905b..fc04413f 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..0cb7eb6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..92acff7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..bbe55c7f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..1d7d3e9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..367d7c2d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index 77bf3be1..e879b521 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index 77bf3be1..e879b521 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
new file mode 100644
index 0000000..aea6c8e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index aeb000f..6a075ac 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
new file mode 100644
index 0000000..a4d2a93fb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 090ae1c..0a83fb8 100644
--- a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..74ee291
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
index ec0fe7d6..349e0557 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-coarse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
index ec0fe7d6..349e0557 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
index 3f2843dc..8b6f49c5d 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
index e867750..5d2f6cbb 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-step-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
index 34e58dff..6228e35 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-appearance-zoom150-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
index 47d84b90..45d7374d 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-disabled-values-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..a8efab9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png b/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
index f9a4f74f..9a78228 100644
--- a/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
+++ b/third_party/blink/web_tests/virtual/controls-refresh-high-contrast/fast/forms/controls-new-ui-high-contrast/text_number_password_button_submit-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
new file mode 100644
index 0000000..96310a7
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
new file mode 100644
index 0000000..b7d0a055
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
new file mode 100644
index 0000000..78e829e
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
new file mode 100644
index 0000000..d5ad3127
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
new file mode 100644
index 0000000..e3f93ac
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01-expected.html
new file mode 100644
index 0000000..3f8ca2e
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01-expected.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  #a {
+    background-color: Window;
+  }
+</style>
+<body>
+  <div id="a">
+    A backplate should be drawn behind the text
+    <br>
+    in forced colors mode
+    <br>
+    (forced-color-adjust is set to auto.)
+  </div>
+  <br><br><br>
+  <div>
+    There should NOT be a backplate drawn behind the text
+    <br>
+    in forced colors mode
+    <br>
+    (forced-color-adjust is set to none.)
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01.html
new file mode 100644
index 0000000..3d62efa
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-01.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+</title>
+<link rel=match href=forced-colors-mode-backplate-01-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  #a {
+    forced-color-adjust: auto;
+  }
+  #b {
+    forced-color-adjust: none;
+  }
+</style>
+<body>
+  <div id="a">
+    A backplate should be drawn behind the text
+    <br>
+    in forced colors mode
+    <br>
+    (forced-color-adjust is set to auto.)
+  </div>
+  <br><br><br>
+  <div id="b">
+    There should NOT be a backplate drawn behind the text
+    <br>
+    in forced colors mode
+    <br>
+    (forced-color-adjust is set to none.)
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02-expected.html
new file mode 100644
index 0000000..59540e9
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02-expected.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  div {
+    background-color: Window;
+  }
+</style>
+<body>
+  <div>
+   This text <br> should have <br> its own backplate <br> in forced colors mode.
+  </div>
+  <br>
+  <div>
+    This text should have its own backplate in forced colors mode:
+    <br>
+    two br tags indicates a new paragraph.
+    <br>
+    This text should share a backplate with the above text:
+    <br>
+    one br tag used.
+  </div>
+  <br>
+  <br>
+  <br>
+  <div>
+    This text should have its own backplate in forced colors mode:
+    <br>
+    four br tags indicates a new paragraph.
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02.html
new file mode 100644
index 0000000..97902b4
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-02.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests that the backplate feature with a varying number of line breaks.
+</title>
+<link rel=match href=forced-colors-mode-backplate-02-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+</style>
+<body>
+  <span>
+    This text <br> should have <br> its own backplate <br> in forced colors mode.
+  </span>
+  <br>
+  <br>
+  <span>
+    This text should have its own backplate in forced colors mode:
+    <br>
+    two br tags indicates a new paragraph.
+  </span>
+  <br>
+  <span>
+    This text should share a backplate with the above text:
+    <br>
+    one br tag used.
+  </span>
+  <br>
+  <br>
+  <br>
+  <br>
+  <span>
+    This text should have its own backplate in forced colors mode:
+    <br>
+    four br tags indicates a new paragraph.
+  </span>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03-expected.html
new file mode 100644
index 0000000..2967fbb
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03-expected.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    left: 0%;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  li {
+    margin-left: -8px;
+  }
+</style>
+<body>
+  <div>
+    <li style="background-color: Window;">
+      There should be a backplate drawn
+  </div>
+  <br>
+  <div>
+    <li style="background-color: Window;">
+      behind the first three list items
+  </div>
+  <br>
+  <div>
+    <li style="background-color: Window;">
+      in forced colors mode.
+  </div>
+  <br>
+  <div>
+    <li>
+      There should be NO backplate drawn
+  </div>
+  <br>
+  <div>
+    <li>
+      behind the last three list items
+  </div>
+  <br>
+  <div>
+    <li>
+      in forced colors mode.
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03.html
new file mode 100644
index 0000000..3bbf1a67
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-03.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests the backplate feature behind lists.
+</title>
+<link rel=match href=forced-colors-mode-backplate-03-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    left: 0%;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  li {
+    margin-left: -8px;
+  }
+  #a {
+    forced-color-adjust: auto;
+  }
+  #b {
+    forced-color-adjust: none;
+  }
+</style>
+<body>
+  <div id="a">
+    <li>
+      There should be a backplate drawn
+  </div>
+  <br>
+  <div id="a">
+    <li>
+      behind the first three list items
+  </div>
+  <br>
+  <div id="a">
+    <li>
+      in forced colors mode.
+  </div>
+  <br>
+  <div id="b">
+    <li>
+      There should be NO backplate drawn
+  </div>
+  <br>
+  <div id="b">
+    <li>
+      behind the last three list items
+  </div>
+  <br>
+  <div id="b">
+    <li>
+      in forced colors mode.
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04-expected.html
new file mode 100644
index 0000000..ec020289
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04-expected.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  #a {
+    background-color: Window;
+  }
+</style>
+<body>
+  <div id="a">
+    This text should have a backplate drawn
+    <br>
+    in forced colors mode
+    <br>
+    that includes the following link:
+    <br>
+    <a href="https://www.wikipedia.org/">LINK</a>
+  </div>
+  <br><br><br><br>
+  <div>
+    This text should NOT have a backplate drawn
+    <br>
+    in forced colors mode
+    <br>
+    including for the following link:
+    <br>
+    <a href="https://www.wikipedia.org/">LINK</a>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04.html
new file mode 100644
index 0000000..b8af0b3
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-04.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests the backplate feature behind links.
+</title>
+<link rel=match href=forced-colors-mode-backplate-04-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+  #a {
+    forced-color-adjust: auto;
+  }
+  #b {
+    forced-color-adjust: none;
+  }
+</style>
+<body>
+  <div id="a">
+    This text should have a backplate drawn
+    <br>
+    in forced colors mode
+    <br>
+    that includes the following link:
+    <br>
+    <a href="https://www.wikipedia.org/">LINK</a>
+  </div>
+  <br><br><br><br>
+  <div id="b">
+    This text should NOT have a backplate drawn
+    <br>
+    in forced colors mode
+    <br>
+    including for the following link:
+    <br>
+    <a href="https://www.wikipedia.org/">LINK</a>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05-expected.html
new file mode 100644
index 0000000..18907bc65
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05-expected.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    line-height: 10px;
+  }
+  li {
+    display: inline;
+    position: relative;
+  }
+  div {
+    background: Window;
+    text-align: justify;
+    width: 110px;
+  }
+</style>
+<body>
+  <div>
+    <li>The backplate</li>
+    <li>for all of</li>
+    <li>the elements</li>
+    <li>in this list</li>
+    <li>should create</li>
+    <li>one single</li>
+    <li>paragraph</li>
+    <li>in forced</li>
+    <li>colors mode.</li>
+    <li>The backplate</li>
+    <li>should not be</li>
+    <li>painted for</li>
+    <li>each individual</li>
+    <li>list item</li>
+    <li>separately.</li>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05.html
new file mode 100644
index 0000000..312339ef
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-05.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests the backplate feature for display inline/relative position.
+</title>
+<link rel=match href=forced-colors-mode-backplate-05-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    line-height: 10px;
+  }
+  li {
+    display: inline;
+    position: relative;
+  }
+  div {
+    text-align: justify;
+    width: 110px;
+  }
+</style>
+<body>
+  <div>
+    <li>The backplate</li>
+    <li>for all of</li>
+    <li>the elements</li>
+    <li>in this list</li>
+    <li>should create</li>
+    <li>one single</li>
+    <li>paragraph</li>
+    <li>in forced</li>
+    <li>colors mode.</li>
+    <li>The backplate</li>
+    <li>should not be</li>
+    <li>painted for</li>
+    <li>each individual</li>
+    <li>list item</li>
+    <li>separately.</li>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06-expected.html
new file mode 100644
index 0000000..3cfc8332
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06-expected.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+</style>
+<body>
+  <div>
+    This text should not have a backplate in forced colors mode.
+    <br>
+    This text should not have a backplate in forced colors mode.
+  </div>
+  <br>
+  <br>
+  <br>
+  <br>
+  <div style="background: Window;">
+    This text should have a backplate in forced colors mode.
+    <br>
+    This text should have a backplate in forced colors mode.
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06.html
new file mode 100644
index 0000000..263dc36
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-06.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests that inline spans with different forced-color-adjust values from their
+  parent element follow the backplate behavior of that parent in forced colors
+  mode.
+</title>
+<link rel=match href=forced-colors-mode-backplate-06-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    line-height: 10px;
+    text-align: justify;
+    width: 100px;
+  }
+</style>
+<body>
+  <div style="forced-color-adjust: none;">
+    This text should not have a backplate in forced colors mode.
+    <br>
+    <span style="forced-color-adjust: auto">
+      This text should not have a backplate in forced colors mode.
+    </span>
+  </div>
+  <br>
+  <br>
+  <br>
+  <br>
+  <div style="forced-color-adjust: auto;">
+    This text should have a backplate in forced colors mode.
+    <br>
+    <span style="forced-color-adjust: none">
+      This text should have a backplate in forced colors mode.
+    </span>
+  </div>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07-expected.html
new file mode 100644
index 0000000..e832ab6
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07-expected.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+  }
+</style>
+<body>
+  <span style="background-color: Window;">
+    There should be a backplate covering one line of text.
+  </span>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07.html
new file mode 100644
index 0000000..9ae5b95
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-07.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests backplate invalidation.
+</title>
+<link rel=match href=forced-colors-mode-backplate-07-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+  }
+</style>
+<body>
+  <span>
+    There should be a backplate covering one line of text.
+    <br>
+    <span id="text">this second line should be removed</span>
+    <br>
+  </span>
+  <script>
+    if (window.testRunner)
+      testRunner.waitUntilDone();
+    window.onload = function() {
+      requestAnimationFrame(function() {
+        text.innerText = '';
+        if (window.testRunner)
+          testRunner.notifyDone();
+      });
+    }
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08-expected.html
new file mode 100644
index 0000000..2d05e307
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08-expected.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+    forced-color-adjust: none; /* This turns the backplate feature off in
+                                  forced colors mode. The backplate is
+                                  simulated in testing using a Window
+                                  background-color behind the text.
+                                */
+  }
+  span {
+    background-color: Window;
+  }
+</style>
+<body>
+  <span>
+    The text below should have a backplate in forced colors mode.
+  </span>
+  <div>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <span>This text should have a backplate.</span>
+  </div>
+</body>
+
+<script>
+  function scroll() {
+    window.scrollBy(0, 5000);
+  }
+  onload = scroll;
+</script> 
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08.html
new file mode 100644
index 0000000..36abc02
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/backplate/forced-colors-mode-backplate-08.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>
+  Forced colors mode - backplate.
+  Tests backplate is drawn when text is located outside the cull rect.
+</title>
+<link rel=match href=forced-colors-mode-backplate-08-expected.html>
+<style>
+  body {
+    background-image: url("../resources/test-image.jpg");
+    font-family: Ahem;
+    font-size: 10px;
+  }
+</style>
+<body>
+  The text below should have a backplate in forced colors mode.
+  <div>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
+    <span>This text should have a backplate.</span>
+  </div>
+</body>
+
+<script>
+  function scroll() {
+    window.scrollBy(0, 5000);
+  }
+  onload = scroll;
+</script> 
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
index f2f7271..bd38792 100644
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-18-expected.html
@@ -13,7 +13,7 @@
       forced colors mode.
     </text>
     <rect x="0" height="60" y="30" width="180" style="fill: red; stroke: blue;"/>
-    <foreignObject x="20" y="30" width="160" height="160">
+    <foreignObject x="20" y="100" width="160" height="160">
       <div xmlns="http://www.w3.org/1999/xhtml" style="color: WindowText;">
         This text should be WindowText color in forced colors mode.
       </div>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt
deleted file mode 100644
index de145459..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks that background color alpha channels are preserved in forced colors mode.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20.html
similarity index 77%
rename from third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20.html
rename to third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20.html
index 1415397..25b14ec 100644
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-20.html
+++ b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-20.html
@@ -6,8 +6,8 @@
   colors mode.
 </title>
 <link rel="help" href="https://www.w3.org/TR/css-color-adjust-1/#forced-colors-properties">
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../../../resources/testharness.js"></script>
+<script src="../../../../../resources/testharnessreport.js"></script>
 <style>
   div {
     background-color: rgba(114, 173, 218, .3);
@@ -22,7 +22,7 @@
 
 <script>
   var body_color = getComputedStyle(body).backgroundColor;
-  var expected_div_color = body_color.replace('0)', '0.3)').replace('rgb(', 'rgba(');
+  var expected_div_color = body_color.replace(')', ', 0.3)').replace('rgb(', 'rgba(');
   test(function(){
     assert_equals(getComputedStyle(div).backgroundColor, expected_div_color);
   }, "Checks that background color alpha channels are preserved in forced colors mode.");
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/resources/test-image.jpg b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/resources/test-image.jpg
similarity index 100%
rename from third_party/blink/web_tests/fast/css/forced-colors-mode/resources/test-image.jpg
rename to third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/resources/test-image.jpg
Binary files differ
diff --git a/tools/lldb/lldbinit.py b/tools/lldb/lldbinit.py
new file mode 100644
index 0000000..8617b5c
--- /dev/null
+++ b/tools/lldb/lldbinit.py
@@ -0,0 +1,16 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The GN arg `strip_absolute_paths_from_debug_symbols = 1` uses relative paths
+# for debug symbols. This confuses lldb. We explicitly set the source-map to
+# point at the root directory of the chromium checkout.
+import os
+import lldb
+this_dir = os.path.dirname(os.path.abspath(__file__))
+source_dir = os.path.join(os.path.join(this_dir, os.pardir), os.pardir)
+
+lldb.debugger.HandleCommand(
+    'settings set target.source-map ../.. ' + source_dir)
+lldb.debugger.HandleCommand(
+    'settings set target.env-vars CHROMIUM_LLDBINIT_SOURCED=1')
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index e86d3ac..c8f9858 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -6268,6 +6268,9 @@
 </action>
 
 <action name="GridTabSwitcher.Drag.AddToGroupOrCreateGroup">
+  <obsolete>
+    Deprecated as of 8/2019. Replaced with TabGroup.Created.DropToMerge.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <description>
@@ -12416,6 +12419,9 @@
 </action>
 
 <action name="MobileNewTabOpenedTabStrip">
+  <obsolete>
+    Deprecated as of 8/2019. Replaced with MobileNewTabOpened.TabStrip.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <description>
@@ -21577,7 +21583,16 @@
   <description>User drags a tab to reorder it.</description>
 </action>
 
+<action name="TabGridDialog">
+  <owner>yusufo@chromium.org</owner>
+  <owner>wychen@chromium.org</owner>
+  <description>User took an action on the TabGridDialog.</description>
+</action>
+
 <action name="TabGridDialog.Drag.RemoveFromGroup">
+  <obsolete>
+    Deprecated as of 8/2019. Replaced with TabGrid.Drag.RemoveFromGroup.
+  </obsolete>
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <description>
@@ -21604,8 +21619,8 @@
   <owner>yusufo@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <description>
-    Users tapped &quot;^&quot; button on the tab strip, causing tab group bottom
-    sheet to be shown.
+    Users tapped &quot;^&quot; button on the tab strip, causing tab group
+    component to be shown.
   </description>
 </action>
 
@@ -23133,6 +23148,9 @@
 <action-suffix separator="." ordering="suffix">
   <suffix name="DeveloperRequestedNewTab"
       label="Users tapped on a link with a target=_blank"/>
+  <suffix name="DropToMerge"
+      label="Users dragged a single tab and dropped it on another single tab
+             to create a group."/>
   <suffix name="OpenInNewTab"
       label="Users long pressed a link and opened in new tab."/>
   <suffix name="TabMultiSelect"
@@ -23145,6 +23163,10 @@
 <action-suffix separator="." ordering="suffix">
   <suffix name="GridTabSwitcher"
       label="Users switched tabs from the grid layout TabSwitcher."/>
+  <suffix name="TabGridDialogFromStrip"
+      label="Users switched tabs within the tab grid dialog."/>
+  <suffix name="TabGridDialogInSwitcher"
+      label="Users switched tabs between groups using tab grid dialog."/>
   <suffix name="TabGridSheet"
       label="Users switched tabs from the tab group in the bottom sheet
              switcher."/>
@@ -23153,6 +23175,14 @@
 </action-suffix>
 
 <action-suffix separator="." ordering="suffix">
+  <suffix name="TabGridDialogFromStrip"
+      label="Users tapped '+' button on the tab group dialog toolbar, causing
+             a new tab to be created in the group. The dialog is expanded
+             from tab strip"/>
+  <suffix name="TabGridDialogInSwitcher"
+      label="Users tapped '+' button on the tab group dialog toolbar, causing
+             a new tab to be created in the group. The dialog is in tab
+             switcher."/>
   <suffix name="TabGridSheet"
       label="Users tapped '+' button on the tab group bottom sheet toolbar
              causes a new tab to be created in the group."/>
@@ -23196,25 +23226,47 @@
 <action-suffix separator="." ordering="suffix">
   <suffix name="GridTabSwitcher"
       label="Users swipe to close a tab in grid layout TabSwitcher."/>
-  <suffix name="TabGridDialog"
-      label="Users swipe to close a tab in tab grid dialog."/>
+  <suffix name="TabGridDialogFromStrip"
+      label="Users swipe to close a tab in tab grid dialog from tab strip."/>
+  <suffix name="TabGridDialogInSwitcher"
+      label="Users swipe to close a tab in tab grid dialog from grid tab
+             switcher."/>
   <suffix name="TabGridSheet"
       label="Users swipe to close a tab in tab group bottom sheet."/>
   <affected-action name="MobileStackViewSwipeCloseTab"/>
 </action-suffix>
 
 <action-suffix separator="." ordering="suffix">
+  <suffix name="DropToMerge"
+      label="Users use drop-to-merge to combine a single tab and a group or
+             two groups."/>
+  <suffix name="RemoveFromGroup.TabGridDialogFromStrip"
+      label="Users ungroup a tab by dropping it on the ungroup bar in tab
+             grid dialog from tab strip."/>
+  <suffix name="RemoveFromGroup.TabGridDialogInSwitcher"
+      label="Users ungroup a tab by dropping it on the ungroup bar in tab
+             grid dialog from grid tab switcher."/>
   <suffix name="Reordered.GridTabSwitcher"
-      label="Users drag to reorder tabs in grid layout TabSwitcher."/>
-  <suffix name="Reordered.TabGridDialog"
-      label="Users drag to reorder tabs in tab grid dialog."/>
+      label="Users drag to reorder tabs in grid layout TabSwitcher. Recorded
+             at each mini reordering during the gesture."/>
+  <suffix name="Reordered.TabGridDialogFromStrip"
+      label="Users drag to reorder tabs in tab grid dialog from tab strip.
+             Recorded at each mini reordering during the gesture."/>
+  <suffix name="Reordered.TabGridDialogInSwitcher"
+      label="Users drag to reorder tabs in tab grid dialog from grid tab
+             switcher. Recorded at each mini reordering during the gesture."/>
   <suffix name="Reordered.TabGridSheet"
-      label="Users drag to reorder tabs in tab group bottom sheet."/>
+      label="Users drag to reorder tabs in tab group bottom sheet. Recorded
+             at each mini reordering during the gesture."/>
   <suffix name="Start.GridTabSwitcher"
       label="Users long tap on a tab to trigger dragging in grid layout
              TabSwitcher."/>
-  <suffix name="Start.TabGridDialog"
-      label="Users long tap on a tab to trigger dragging in tab grid dialog."/>
+  <suffix name="Start.TabGridDialogFromStrip"
+      label="Users long tap on a tab to trigger dragging in tab grid dialog
+             from tab strip."/>
+  <suffix name="Start.TabGridDialogInSwitcher"
+      label="Users long tap on a tab to trigger dragging in tab grid dialog
+             from grid tab switcher."/>
   <suffix name="Start.TabGridSheet"
       label="Users long tap on a tab to trigger dragging in tab group bottom
              sheet."/>
@@ -23252,4 +23304,24 @@
   <affected-action name="MobileMenuNewIncognitoTab"/>
 </action-suffix>
 
+<action-suffix separator="." ordering="suffix">
+  <suffix name="TabGridDialog"
+      label="Users tapped expand button on the tab strip, causing tab grid
+             dialog to be shown."/>
+  <suffix name="TabGridSheet"
+      label="Users tapped expand button on the tab strip, causing tab grid
+             sheet to be shown."/>
+  <affected-action name="TabGroup.ExpandedFromStrip"/>
+</action-suffix>
+
+<action-suffix separator="." ordering="suffix">
+  <suffix name="Exit"
+      label="Users click the back button or the scrim to exit the tab group
+             dialog."/>
+  <suffix name="ExpandedFromSwitcher"
+      label="Users click a card in TabSwitcher to open a dialog. See also
+             TabGroup.ExpandedFromStrip.TabGridDialog."/>
+  <affected-action name="TabGridDialog"/>
+</action-suffix>
+
 </actions>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index af91f7b..675b1ad 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -18097,6 +18097,14 @@
              or the account id was invalid"/>
 </enum>
 
+<enum name="EnterpriseSystemLogUploadResult">
+  <summary>Result of system log upload attempt.</summary>
+  <int value="0" label="Log upload succeeded"/>
+  <int value="1" label="Zipped log upload succeeded"/>
+  <int value="3" label="Log upload failed"/>
+  <int value="4" label="Zipped log upload failed"/>
+</enum>
+
 <enum name="EnterpriseUploadJobSuccess">
   <summary>
     Number of UploadJob retries as defined in
@@ -35006,6 +35014,7 @@
   <int value="-1304758527" label="SyncSendTabToSelf:disabled"/>
   <int value="-1302904242" label="enable-navigation-tracing"/>
   <int value="-1302859198" label="enable-stylus-virtual-keyboard:disabled"/>
+  <int value="-1297079591" label="EnableRemovingAllThirdPartyCookies:disabled"/>
   <int value="-1294050129" label="ContentFullscreen:disabled"/>
   <int value="-1292615467"
       label="OmniboxSuggestionTransparencyOptions:disabled"/>
@@ -35749,6 +35758,7 @@
   <int value="-297716805"
       label="CrossOriginMediaPlaybackRequiresUserGesture:disabled"/>
   <int value="-296179618" label="CookiesWithoutSameSiteMustBeSecure:enabled"/>
+  <int value="-295237704" label="EnableRemovingAllThirdPartyCookies:enabled"/>
   <int value="-290672626" label="enable-asm-wasm"/>
   <int value="-290329565" label="CrosVmCupsProxy:disabled"/>
   <int value="-288316828" label="enable-delegated-renderer"/>
@@ -43503,6 +43513,12 @@
   <int value="5" label="Chrome process launch failed"/>
 </enum>
 
+<enum name="NotificationSchedulerActionButtonEvent">
+  <int value="0" label="Shown"/>
+  <int value="1" label="Helpful"/>
+  <int value="2" label="Unhelpful"/>
+</enum>
+
 <enum name="NotificationSchedulerBackgroundTaskEvent">
   <int value="0" label="Start"/>
   <int value="1" label="Finish"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e27d8ee03..859b07c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -35640,6 +35640,12 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.SystemLogUploadResult"
+    enum="EnterpriseSystemLogUploadResult" expires_after="2020-06-01">
+  <owner>poromov@chromium.org</owner>
+  <summary>Result of a single attempt to upload system logs.</summary>
+</histogram>
+
 <histogram name="Enterprise.TiclInvalidationService.DevicePolicyInvalidations"
     enum="EnterprisePolicyInvalidations" expires_after="2020-01-01">
   <owner>askaraitzhan@google.com</owner>
@@ -87122,6 +87128,18 @@
   </summary>
 </histogram>
 
+<histogram name="Notifications.Scheduler.IhnrActionButtonEvent"
+    enum="NotificationSchedulerActionButtonEvent" expires_after="2020-08-01">
+<!-- Name completed by histogram_suffixes name="NotificationSchedulerClientType" -->
+
+  <owner>xingliu@chromium.org</owner>
+  <owner>hesen@chromium.org</owner>
+  <summary>
+    Records events for inline helpful/unhelpful action buttons on the
+    notification when the buttons are shown or clicked.
+  </summary>
+</histogram>
+
 <histogram name="Notifications.Scheduler.Impression.Count" units="records"
     expires_after="2020-08-01">
 <!-- Name completed by histogram_suffixes name="NotificationSchedulerClientType" -->
@@ -167436,6 +167454,7 @@
   <suffix name="__Test__"/>
   <suffix name="Unknown"/>
   <suffix name="WebUI"/>
+  <affected-histogram name="Notifications.Scheduler.IhnrActionButtonEvent"/>
   <affected-histogram name="Notifications.Scheduler.Impression.Count"/>
   <affected-histogram name="Notifications.Scheduler.UserAction"/>
 </histogram_suffixes>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index 75971f75..3051e55 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -110,7 +110,8 @@
 _WIN_10_BENCHMARK_NAMES = _OFFICIAL_EXCEPT_DISPLAY_LOCKING
 _WIN_10_LOW_END_HP_CANDIDATE_BENCHMARK_NAMES = frozenset([
     'v8.browsing_desktop'])
-_WIN_7_BENCHMARK_NAMES = _OFFICIAL_EXCEPT_DISPLAY_LOCKING_JETSTREAM2
+_WIN_7_BENCHMARK_NAMES = (_OFFICIAL_EXCEPT_DISPLAY_LOCKING_JETSTREAM2 -
+                          frozenset(['rendering.desktop']))
 _WIN_7_GPU_BENCHMARK_NAMES = _OFFICIAL_EXCEPT_DISPLAY_LOCKING_JETSTREAM2
 _ANDROID_GO_BENCHMARK_NAMES = frozenset([
     'system_health.memory_mobile',
diff --git a/tools/perf/core/shard_maps/win_7_perf_map.json b/tools/perf/core/shard_maps/win_7_perf_map.json
index 6b22f02e..6ee5905c 100644
--- a/tools/perf/core/shard_maps/win_7_perf_map.json
+++ b/tools/perf/core/shard_maps/win_7_perf_map.json
@@ -85,9 +85,6 @@
             "rasterize_and_record_micro.top_25": {
                 "abridged": false
             },
-            "rendering.desktop": {
-                "abridged": false
-            },
             "speedometer": {
                 "abridged": false
             },
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 578a283..42ab4928 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -1167,7 +1167,6 @@
       Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager();
   params.pipes.compositor_frame_sink_info = std::move(sink_info);
   params.pipes.client_request = std::move(client_request);
-  params.enable_surface_synchronization = true;
   params.client_name = kExo;
   bool root_accepts_events =
       (event_targeting_policy_ == EventTargetingPolicy::kTargetOnly) ||
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index bef361b..6934dac 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -28,6 +28,10 @@
 const base::Feature kInputMethodSettingsUiUpdate = {
     "InputMethodSettingsUiUpdate", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Allows requesting unadjusted movement when entering pointerlock.
+const base::Feature kPointerLockOptions = {"PointerLockOptions",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Allows system caption style for WebVTT Captions.
 const base::Feature kSystemCaptionStyle{"SystemCaptionStyle",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index 5c4bf65b..e8e2f96 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -23,6 +23,8 @@
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kInputMethodSettingsUiUpdate;
 COMPONENT_EXPORT(UI_BASE_FEATURES)
+extern const base::Feature kPointerLockOptions;
+COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kSystemCaptionStyle;
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kSystemKeyboardLock;
diff --git a/ui/compositor/host/host_context_factory_private.cc b/ui/compositor/host/host_context_factory_private.cc
index 747d018..d32c154 100644
--- a/ui/compositor/host/host_context_factory_private.cc
+++ b/ui/compositor/host/host_context_factory_private.cc
@@ -145,7 +145,6 @@
       compositor->context_factory()->GetGpuMemoryBufferManager();
   params.pipes.compositor_frame_sink_associated_info = std::move(sink_info);
   params.pipes.client_request = std::move(client_request);
-  params.enable_surface_synchronization = true;
   if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
     params.hit_test_data_provider =
         std::make_unique<viz::HitTestDataProviderDrawQuad>(
diff --git a/ui/file_manager/file_manager/foreground/images/filetype/2x/filetype_tini.png b/ui/file_manager/file_manager/foreground/images/filetype/2x/filetype_tini.png
index 020c786..17fda9b 100644
--- a/ui/file_manager/file_manager/foreground/images/filetype/2x/filetype_tini.png
+++ b/ui/file_manager/file_manager/foreground/images/filetype/2x/filetype_tini.png
Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/filetype/filetype_tini.png b/ui/file_manager/file_manager/foreground/images/filetype/filetype_tini.png
index c4a76e8..eb979a1b 100644
--- a/ui/file_manager/file_manager/foreground/images/filetype/filetype_tini.png
+++ b/ui/file_manager/file_manager/foreground/images/filetype/filetype_tini.png
Binary files differ
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn
index 494634a3..1fe934fc 100644
--- a/ui/ozone/platform/x11/BUILD.gn
+++ b/ui/ozone/platform/x11/BUILD.gn
@@ -20,8 +20,8 @@
     "gl_surface_glx_ozone.h",
     "ozone_platform_x11.cc",
     "ozone_platform_x11.h",
-    "x11_clipboard.cc",
-    "x11_clipboard.h",
+    "x11_clipboard_ozone.cc",
+    "x11_clipboard_ozone.h",
     "x11_cursor_factory_ozone.cc",
     "x11_cursor_factory_ozone.h",
     "x11_cursor_ozone.cc",
@@ -41,6 +41,7 @@
     "//gpu/vulkan:buildflags",
     "//skia",
     "//ui/base",
+    "//ui/base/clipboard:clipboard_types",
     "//ui/base/ime",
     "//ui/base/x",
     "//ui/display/fake",
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index cdec41e..470673d 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -15,7 +15,7 @@
 #include "ui/events/platform/x11/x11_event_source_default.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
-#include "ui/ozone/platform/x11/x11_clipboard.h"
+#include "ui/ozone/platform/x11/x11_clipboard_ozone.h"
 #include "ui/ozone/platform/x11/x11_cursor_factory_ozone.h"
 #include "ui/ozone/platform/x11/x11_screen_ozone.h"
 #include "ui/ozone/platform/x11/x11_surface_factory.h"
@@ -126,7 +126,7 @@
     window_manager_ = std::make_unique<X11WindowManagerOzone>();
     overlay_manager_ = std::make_unique<StubOverlayManager>();
     input_controller_ = CreateStubInputController();
-    clipboard_ = std::make_unique<X11Clipboard>();
+    clipboard_ = std::make_unique<X11ClipboardOzone>();
     cursor_factory_ozone_ = std::make_unique<X11CursorFactoryOzone>();
     gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
 
@@ -179,7 +179,7 @@
   std::unique_ptr<X11WindowManagerOzone> window_manager_;
   std::unique_ptr<OverlayManagerOzone> overlay_manager_;
   std::unique_ptr<InputController> input_controller_;
-  std::unique_ptr<X11Clipboard> clipboard_;
+  std::unique_ptr<X11ClipboardOzone> clipboard_;
   std::unique_ptr<X11CursorFactoryOzone> cursor_factory_ozone_;
   std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
 
diff --git a/ui/ozone/platform/x11/x11_clipboard.cc b/ui/ozone/platform/x11/x11_clipboard.cc
deleted file mode 100644
index b512b16..0000000
--- a/ui/ozone/platform/x11/x11_clipboard.cc
+++ /dev/null
@@ -1,56 +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 <utility>
-
-#include "ui/ozone/platform/x11/x11_clipboard.h"
-
-namespace ui {
-
-X11Clipboard::X11Clipboard() = default;
-X11Clipboard::~X11Clipboard() = default;
-
-void X11Clipboard::OfferClipboardData(
-    const PlatformClipboard::DataMap& data_map,
-    PlatformClipboard::OfferDataClosure callback) {
-  // TODO(crbug.com/973295): Implement X11Clipboard
-  NOTIMPLEMENTED_LOG_ONCE();
-  std::move(callback).Run();
-}
-
-void X11Clipboard::RequestClipboardData(
-    const std::string& mime_type,
-    PlatformClipboard::DataMap* data_map,
-    PlatformClipboard::RequestDataClosure callback) {
-  // TODO(crbug.com/973295): Implement X11Clipboard
-  NOTIMPLEMENTED_LOG_ONCE();
-  std::move(callback).Run({});
-}
-
-void X11Clipboard::GetAvailableMimeTypes(
-    PlatformClipboard::GetMimeTypesClosure callback) {
-  // TODO(crbug.com/973295): Implement X11Clipboard
-  NOTIMPLEMENTED_LOG_ONCE();
-  std::move(callback).Run({});
-}
-
-bool X11Clipboard::IsSelectionOwner() {
-  // TODO(crbug.com/973295): Implement X11Clipboard
-  NOTIMPLEMENTED_LOG_ONCE();
-  return false;
-}
-
-void X11Clipboard::SetSequenceNumberUpdateCb(
-    PlatformClipboard::SequenceNumberUpdateCb cb) {
-  DCHECK(update_sequence_cb_.is_null())
-      << " The callback can be installed only once.";
-  update_sequence_cb_ = std::move(cb);
-}
-
-void X11Clipboard::UpdateSequenceNumber() {
-  if (!update_sequence_cb_.is_null())
-    update_sequence_cb_.Run();
-}
-
-}  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_clipboard.h b/ui/ozone/platform/x11/x11_clipboard.h
deleted file mode 100644
index 120210cd6..0000000
--- a/ui/ozone/platform/x11/x11_clipboard.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_H_
-#define UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "ui/ozone/public/platform_clipboard.h"
-
-namespace ui {
-
-// Handles clipboard operations for X11 Platform
-class X11Clipboard : public PlatformClipboard {
- public:
-  X11Clipboard();
-  ~X11Clipboard() override;
-
-  // PlatformClipboard.
-  void OfferClipboardData(
-      const PlatformClipboard::DataMap& data_map,
-      PlatformClipboard::OfferDataClosure callback) override;
-  void RequestClipboardData(
-      const std::string& mime_type,
-      PlatformClipboard::DataMap* data_map,
-      PlatformClipboard::RequestDataClosure callback) override;
-  void GetAvailableMimeTypes(
-      PlatformClipboard::GetMimeTypesClosure callback) override;
-  bool IsSelectionOwner() override;
-  void SetSequenceNumberUpdateCb(
-      PlatformClipboard::SequenceNumberUpdateCb cb) override;
-
- private:
-  void UpdateSequenceNumber();
-
-  // Notifies whenever clipboard sequence number is changed.
-  PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(X11Clipboard);
-};
-
-}  // namespace ui
-
-#endif  // UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_H_
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
new file mode 100644
index 0000000..7797f50
--- /dev/null
+++ b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
@@ -0,0 +1,357 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/x11_clipboard_ozone.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/containers/span.h"
+#include "base/stl_util.h"
+#include "ui/base/clipboard/clipboard_constants.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/x11_types.h"
+
+using base::Contains;
+
+namespace ui {
+
+namespace {
+
+const char kChromeSelection[] = "CHROME_SELECTION";
+const char kClipboard[] = "CLIPBOARD";
+const char kMimeTypeUtf8[] = "text/plain;charset=utf-8";
+const char kString[] = "STRING";
+const char kTargets[] = "TARGETS";
+const char kTimestamp[] = "TIMESTAMP";
+const char kUtf8String[] = "UTF8_STRING";
+
+// Helps to allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING.
+void ExpandTypes(std::vector<std::string>* list) {
+  bool has_mime_type_text = Contains(*list, ui::kMimeTypeText);
+  bool has_string = Contains(*list, kString);
+  bool has_mime_type_utf8 = Contains(*list, kMimeTypeUtf8);
+  bool has_utf8_string = Contains(*list, kUtf8String);
+  if (has_mime_type_text && !has_string)
+    list->push_back(kString);
+  if (has_string && !has_mime_type_text)
+    list->push_back(ui::kMimeTypeText);
+  if (has_mime_type_utf8 && !has_utf8_string)
+    list->push_back(kUtf8String);
+  if (has_utf8_string && !has_mime_type_utf8)
+    list->push_back(kMimeTypeUtf8);
+}
+
+XID FindXEventTarget(const XEvent& xev) {
+  XID target = xev.xany.window;
+  if (xev.type == GenericEvent)
+    target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event;
+  return target;
+}
+
+}  // namespace
+
+X11ClipboardOzone::X11ClipboardOzone()
+    : atom_clipboard_(gfx::GetAtom(kClipboard)),
+      atom_targets_(gfx::GetAtom(kTargets)),
+      atom_timestamp_(gfx::GetAtom(kTimestamp)),
+      x_property_(gfx::GetAtom(kChromeSelection)),
+      x_display_(gfx::GetXDisplay()),
+      x_window_(XCreateSimpleWindow(x_display_,
+                                    DefaultRootWindow(x_display_),
+                                    /*x=*/-100,
+                                    /*y=*/-100,
+                                    /*width=*/10,
+                                    /*height=*/10,
+                                    /*border_width=*/0,
+                                    /*border=*/0,
+                                    /*background=*/0)) {
+  int ignored;  // xfixes_error_base.
+  if (!XFixesQueryExtension(x_display_, &xfixes_event_base_, &ignored)) {
+    LOG(ERROR) << "X server does not support XFixes.";
+    return;
+  }
+  using_xfixes_ = true;
+
+  // Register to receive standard X11 events.
+  X11EventSource::GetInstance()->AddXEventDispatcher(this);
+
+  // Register to receive XFixes notification when selection owner changes.
+  XFixesSelectSelectionInput(x_display_, x_window_, atom_clipboard_,
+                             XFixesSetSelectionOwnerNotifyMask);
+
+  // Prefetch the current remote clipboard contents.
+  QueryTargets();
+}
+
+X11ClipboardOzone::~X11ClipboardOzone() {
+  X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
+}
+
+bool X11ClipboardOzone::DispatchXEvent(XEvent* xev) {
+  if (FindXEventTarget(*xev) != x_window_)
+    return false;
+
+  switch (xev->type) {
+    case SelectionRequest:
+      return OnSelectionRequest(xev);
+    case SelectionNotify:
+      return OnSelectionNotify(xev);
+  }
+
+  if (using_xfixes_ &&
+      xev->type == xfixes_event_base_ + XFixesSetSelectionOwnerNotify) {
+    return OnSetSelectionOwnerNotify(xev);
+  }
+
+  return false;
+}
+
+// We are the clipboard owner, and a remote peer has requested either:
+// TARGETS: List of mime types that we support for the clipboard.
+// TIMESTAMP: Time when we took ownership of the clipboard.
+// <mime-type>: Mime type to receive clipboard as.
+bool X11ClipboardOzone::OnSelectionRequest(XEvent* xev) {
+  // We only support selection=CLIPBOARD, and property must be set.
+  if (xev->xselectionrequest.selection != atom_clipboard_ ||
+      xev->xselectionrequest.property == x11::None) {
+    return false;
+  }
+
+  XSelectionEvent selection_event;
+  selection_event.type = SelectionNotify;
+  selection_event.display = xev->xselectionrequest.display;
+  selection_event.requestor = xev->xselectionrequest.requestor;
+  selection_event.selection = xev->xselectionrequest.selection;
+  selection_event.target = xev->xselectionrequest.target;
+  selection_event.property = xev->xselectionrequest.property;
+  selection_event.time = xev->xselectionrequest.time;
+
+  selection_event.property = xev->xselectionrequest.property;
+
+  // target=TARGETS.
+  if (selection_event.target == atom_targets_) {
+    std::vector<std::string> targets;
+    // Add TIMESTAMP.
+    targets.push_back(kTimestamp);
+    for (auto& entry : offer_data_map_) {
+      targets.push_back(entry.first);
+    }
+    // Expand types, then convert from string to atom.
+    ExpandTypes(&targets);
+    std::vector<XAtom> atoms;
+    for (auto& entry : targets) {
+      atoms.push_back(gfx::GetAtom(entry.c_str()));
+    }
+    XChangeProperty(
+        x_display_, selection_event.requestor, selection_event.property,
+        XA_ATOM, /*format=*/32, PropModeReplace,
+        reinterpret_cast<unsigned char*>(atoms.data()), atoms.size());
+
+  } else if (selection_event.target == atom_timestamp_) {
+    // target=TIMESTAMP.
+    XChangeProperty(
+        x_display_, selection_event.requestor, selection_event.property,
+        XA_INTEGER, /*format=*/32, PropModeReplace,
+        reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1);
+
+  } else {
+    // Send clipboard data.
+    char* target_name = XGetAtomName(x_display_, selection_event.target);
+
+    std::string key = target_name;
+    // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING.
+    if (key == kUtf8String && !Contains(offer_data_map_, kUtf8String)) {
+      key = kMimeTypeUtf8;
+    } else if (key == kString && !Contains(offer_data_map_, kString)) {
+      key = kMimeTypeText;
+    }
+    auto it = offer_data_map_.find(key);
+    if (it != offer_data_map_.end()) {
+      XChangeProperty(
+          x_display_, selection_event.requestor, selection_event.property,
+          selection_event.target, /*format=*/8, PropModeReplace,
+          const_cast<unsigned char*>(it->second.data()), it->second.size());
+    }
+    XFree(target_name);
+  }
+
+  // Notify remote peer that clipboard has been sent.
+  XSendEvent(x_display_, selection_event.requestor, /*propagate=*/x11::False,
+             /*event_mask=*/0, reinterpret_cast<XEvent*>(&selection_event));
+  return true;
+}
+
+// A remote peer owns the clipboard.  This event is received in response to
+// our request for TARGETS (GetAvailableMimeTypes), or a specific mime type
+// (RequestClipboardData).
+bool X11ClipboardOzone::OnSelectionNotify(XEvent* xev) {
+  // GetAvailableMimeTypes.
+  if (xev->xselection.target == atom_targets_) {
+    XAtom type;
+    int format;
+    unsigned long item_count, after;
+    unsigned char* data = nullptr;
+
+    if (XGetWindowProperty(x_display_, x_window_, x_property_,
+                           /*long_offset=*/0,
+                           /*long_length=*/256 * sizeof(XAtom),
+                           /*delete=*/x11::False, XA_ATOM, &type, &format,
+                           &item_count, &after, &data) != x11::Success) {
+      return false;
+    }
+
+    mime_types_.clear();
+    base::span<XAtom> targets(reinterpret_cast<XAtom*>(data), item_count);
+    for (auto target : targets) {
+      char* atom_name = XGetAtomName(x_display_, target);
+      if (atom_name) {
+        mime_types_.push_back(atom_name);
+        XFree(atom_name);
+      }
+    }
+    XFree(data);
+
+    // If we have a saved callback, invoke it now with expanded types, otherwise
+    // guess that we will want 'text/plain' and fetch it now.
+    if (get_available_mime_types_callback_) {
+      std::vector<std::string> result(mime_types_);
+      ExpandTypes(&result);
+      std::move(get_available_mime_types_callback_).Run(std::move(result));
+    } else {
+      data_mime_type_ = kMimeTypeText;
+      ReadRemoteClipboard();
+    }
+
+    return true;
+  }
+
+  // RequestClipboardData.
+  if (xev->xselection.property == x_property_) {
+    XAtom type;
+    int format;
+    unsigned long item_count, after;
+    unsigned char* data;
+    XGetWindowProperty(x_display_, x_window_, x_property_,
+                       /*long_offset=*/0, /*long_length=*/~0L,
+                       /*delete=*/x11::True, AnyPropertyType, &type, &format,
+                       &item_count, &after, &data);
+    if (type != x11::None && format == 8) {
+      std::vector<unsigned char> tmp(data, data + item_count);
+      data_ = tmp;
+    }
+    XFree(data);
+
+    // If we have a saved callback, invoke it now, otherwise this was a prefetch
+    // and we have already saved |data_| for the next call to
+    // |RequestClipboardData|.
+    if (request_clipboard_data_callback_) {
+      request_data_map_->emplace(data_mime_type_, data_);
+      std::move(request_clipboard_data_callback_).Run(data_);
+    }
+    return true;
+  }
+
+  return false;
+}
+
+bool X11ClipboardOzone::OnSetSelectionOwnerNotify(XEvent* xev) {
+  // Reset state and fetch remote clipboard if there is a new remote owner.
+  if (!IsSelectionOwner()) {
+    mime_types_.clear();
+    data_mime_type_.clear();
+    data_.clear();
+    QueryTargets();
+  }
+  return true;
+}
+
+void X11ClipboardOzone::QueryTargets() {
+  mime_types_.clear();
+  XConvertSelection(x_display_, atom_clipboard_, atom_targets_, x_property_,
+                    x_window_, x11::CurrentTime);
+}
+
+void X11ClipboardOzone::ReadRemoteClipboard() {
+  data_.clear();
+  // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING.
+  std::string target = data_mime_type_;
+  if (!Contains(mime_types_, target)) {
+    if (target == kMimeTypeText) {
+      target = kString;
+    } else if (target == kMimeTypeUtf8) {
+      target = kUtf8String;
+    }
+  }
+
+  XConvertSelection(x_display_, atom_clipboard_, gfx::GetAtom(target.c_str()),
+                    x_property_, x_window_, x11::CurrentTime);
+}
+
+void X11ClipboardOzone::OfferClipboardData(
+    const PlatformClipboard::DataMap& data_map,
+    PlatformClipboard::OfferDataClosure callback) {
+  acquired_selection_timestamp_ = X11EventSource::GetInstance()->GetTimestamp();
+  offer_data_map_ = data_map;
+  // Only take ownership if we are using xfixes.
+  // TODO(joelhockey): Make clipboard work without xfixes.
+  if (using_xfixes_) {
+    XSetSelectionOwner(x_display_, atom_clipboard_, x_window_,
+                       acquired_selection_timestamp_);
+  }
+  std::move(callback).Run();
+}
+
+void X11ClipboardOzone::RequestClipboardData(
+    const std::string& mime_type,
+    PlatformClipboard::DataMap* data_map,
+    PlatformClipboard::RequestDataClosure callback) {
+  // If we are not using xfixes, return empty data.
+  // TODO(joelhockey): Make clipboard work without xfixes.
+  // If we have already prefetched the clipboard for the correct mime type,
+  // then send it right away, otherwise save the callback and attempt to get the
+  // requested mime type from the remote clipboard.
+  if (!using_xfixes_ || (data_mime_type_ == mime_type && !data_.empty())) {
+    data_map->emplace(mime_type, data_);
+    std::move(callback).Run(data_);
+    return;
+  }
+  data_mime_type_ = mime_type;
+  request_data_map_ = data_map;
+  DCHECK(request_clipboard_data_callback_.is_null());
+  request_clipboard_data_callback_ = std::move(callback);
+  ReadRemoteClipboard();
+}
+
+void X11ClipboardOzone::GetAvailableMimeTypes(
+    PlatformClipboard::GetMimeTypesClosure callback) {
+  // If we are not using xfixes, return empty data.
+  // TODO(joelhockey): Make clipboard work without xfixes.
+  // If we already have the list of supported mime types, send the expanded list
+  // of types right away, otherwise save the callback and get the list of
+  // TARGETS from the remote clipboard.
+  if (!using_xfixes_ || !mime_types_.empty()) {
+    std::vector<std::string> result(mime_types_);
+    ExpandTypes(&result);
+    std::move(callback).Run(std::move(result));
+    return;
+  }
+  DCHECK(get_available_mime_types_callback_.is_null());
+  get_available_mime_types_callback_ = std::move(callback);
+  QueryTargets();
+}
+
+bool X11ClipboardOzone::IsSelectionOwner() {
+  // If we are not using xfixes, then we are always the owner.
+  // TODO(joelhockey): Make clipboard work without xfixes.
+  return !using_xfixes_ ||
+         XGetSelectionOwner(x_display_, atom_clipboard_) == x_window_;
+}
+
+void X11ClipboardOzone::SetSequenceNumberUpdateCb(
+    PlatformClipboard::SequenceNumberUpdateCb cb) {
+  update_sequence_cb_ = std::move(cb);
+}
+
+}  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.h b/ui/ozone/platform/x11/x11_clipboard_ozone.h
new file mode 100644
index 0000000..eb0424f9b
--- /dev/null
+++ b/ui/ozone/platform/x11/x11_clipboard_ozone.h
@@ -0,0 +1,121 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_OZONE_H_
+#define UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_OZONE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/x/x11.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/ozone/public/platform_clipboard.h"
+
+namespace ui {
+
+// Handles clipboard operations for X11.
+// Registers to receive standard X11 events, as well as
+// XFixesSetSelectionOwnerNotify.  When the remote owner changes, TARGETS and
+// text/plain are preemptively fetched.  They can then be provided immediately
+// to GetAvailableMimeTypes, and RequestClipboardData when mime_type is
+// text/plain.  Otherwise GetAvailableMimeTypes and RequestClipboardData call
+// the appropriate X11 functions and invoke callbacks when the associated events
+// are received.
+class X11ClipboardOzone : public PlatformClipboard, public XEventDispatcher {
+ public:
+  X11ClipboardOzone();
+  ~X11ClipboardOzone() override;
+
+  // PlatformClipboard:
+  void OfferClipboardData(
+      const PlatformClipboard::DataMap& data_map,
+      PlatformClipboard::OfferDataClosure callback) override;
+  void RequestClipboardData(
+      const std::string& mime_type,
+      PlatformClipboard::DataMap* data_map,
+      PlatformClipboard::RequestDataClosure callback) override;
+  void GetAvailableMimeTypes(
+      PlatformClipboard::GetMimeTypesClosure callback) override;
+  bool IsSelectionOwner() override;
+  void SetSequenceNumberUpdateCb(
+      PlatformClipboard::SequenceNumberUpdateCb cb) override;
+
+ private:
+  // XEventDispatcher:
+  bool DispatchXEvent(XEvent* xev) override;
+
+  bool OnSelectionRequest(XEvent* xev);
+  bool OnSelectionNotify(XEvent* xev);
+  bool OnSetSelectionOwnerNotify(XEvent* xev);
+
+  // Queries the current clipboard owner for what mime types are available by
+  // sending XConvertSelection with target=TARGETS.  After sending this, we
+  // will receive a SelectionNotify event with xselection.target=TARGETS which
+  // is processed in |OnSelectionNotify|.
+  void QueryTargets();
+
+  // Reads the contents of the remote clipboard by sending XConvertSelection
+  // with target=<mime-type>.  After sending this, we will receive a
+  // SelectionNotify event with xselection.target=<mime-type> which is processed
+  // in |OnSelectionNotify|.
+  void ReadRemoteClipboard();
+
+  // Notifies whenever clipboard sequence number is changed.
+  PlatformClipboard::SequenceNumberUpdateCb update_sequence_cb_;
+
+  // DataMap we keep from |OfferClipboardData| to service remote requests for
+  // the clipboard.
+  PlatformClipboard::DataMap offer_data_map_;
+
+  // DataMap from |RequestClipboardData| that we write remote clipboard contents
+  // to before calling the completion callback.
+  PlatformClipboard::DataMap* request_data_map_ = nullptr;
+
+  // Mime types supported by remote clipboard.
+  std::vector<std::string> mime_types_;
+
+  // Data most recently read from remote clipboard.
+  std::vector<unsigned char> data_;
+
+  // Mime type of most recently read data from remote clipboard.
+  std::string data_mime_type_;
+
+  // If XFixes is unavailable, this clipboard window will not register to
+  // receive events and no processing will take place.
+  // TODO(joelhockey): Make clipboard work without xfixes.
+  bool using_xfixes_ = false;
+
+  // The event base returned by XFixesQueryExtension().
+  int xfixes_event_base_;
+
+  // Callbacks are stored when we haven't already prefetched the remote
+  // clipboard.
+  PlatformClipboard::GetMimeTypesClosure get_available_mime_types_callback_;
+  PlatformClipboard::RequestDataClosure request_clipboard_data_callback_;
+
+  // Local cache of atoms.
+  const XAtom atom_clipboard_;
+  const XAtom atom_targets_;
+  const XAtom atom_timestamp_;
+
+  // The property on |x_window_| which will receive remote clipboard contents.
+  const XAtom x_property_;
+
+  // Our X11 state.
+  Display* const x_display_;
+
+  // Input-only window used as a selection owner.
+  const XID x_window_;
+
+  // The time that this instance took ownership of the clipboard.
+  Time acquired_selection_timestamp_;
+
+  DISALLOW_COPY_AND_ASSIGN(X11ClipboardOzone);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_PLATFORM_X11_X11_CLIPBOARD_OZONE_H_
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
index bb29536..dadfd89 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -47,6 +47,11 @@
 js_library("provisioning_page") {
   deps = [
     ":base_page",
+    ":webview_post_util",
+  ]
+  externs_list = [
+    "$externs_path/chrome_extensions.js",
+    "$externs_path/webview_tag.js",
   ]
 }
 
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
index e2be730..4e36caa 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html
@@ -23,7 +23,11 @@
         selected="[[selectedPageName_]]"
         selected-item="{{selectedPage_}}">
       <sim-detect-page show-error="[[showError_]]"></sim-detect-page>
-      <provisioning-page show-error="[[showError_]]"></provisioning-page>
+      <provisioning-page show-error="{{showError_}}"
+          cellular-metadata="[[cellularMetadata_]]"
+          on-carrier-portal-loaded="onCarrierPortalLoaded_"
+          on-carrier-portal-result="onCarrierPortalResult_">
+      </provisioning-page>
       <final-page show-error="[[showError_]]"></final-page>
     </iron-pages>
     <button-bar show-try-again-button="[[showTryAgainButton_]]"
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
index a48b31ec..52f19ab 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js
@@ -40,7 +40,7 @@
 
     // The portal is a website served by the mobile carrier.
     if (state === State.WAITING_FOR_PORTAL_TO_LOAD) {
-      return 5000;  // 5 seconds.
+      return 10000;  // 10 seconds.
     }
 
     // Finishing activation only requires sending a D-Bus message to Shill.
@@ -100,6 +100,16 @@
     showError_: {type: Boolean, value: false},
 
     /**
+     * Cellular metadata received via the onActivationStarted() callback. If
+     * that callback has not occurred, this field is null.
+     * @private {?chromeos.cellularSetup.mojom.CellularMetadata}
+     */
+    cellularMetadata_: {
+      type: Object,
+      value: null,
+    },
+
+    /**
      * Whether try again should be shown in the button bar.
      * @private {boolean}
      */
@@ -150,13 +160,6 @@
   currentTimeoutId_: null,
 
   /**
-   * Cellular metadata received via the onActivationStarted() callback. If that
-   * callback has not occurred, this field is null.
-   * @private {?chromeos.cellularSetup.mojom.CellularMetadata}
-   */
-  cellularMetadata_: null,
-
-  /**
    * Handler used to communicate state updates back to the CellularSetup
    * service.
    * @private {?chromeos.cellularSetup.mojom.CarrierPortalHandlerRemote}
@@ -320,6 +323,7 @@
     this.activationDelegateReceiver_.$.close();
     this.activationDelegateReceiver_ = null;
     this.carrierPortalHandler_ = null;
+    this.cellularMetadata_ = null;
   },
 
   /** @private */
@@ -331,6 +335,24 @@
   },
 
   /** @private */
+  onCarrierPortalLoaded_: function() {
+    this.state_ = cellularSetup.State.WAITING_FOR_USER_PAYMENT;
+    this.carrierPortalHandler_.onCarrierPortalStatusChange(
+        chromeos.cellularSetup.mojom.CarrierPortalStatus
+            .kPortalLoadedWithoutPaidUser);
+  },
+
+  /**
+   * @param {!CustomEvent<boolean>} event
+   * @private
+   */
+  onCarrierPortalResult_: function(event) {
+    const success = event.detail;
+    this.state_ = success ? cellularSetup.State.ACTIVATION_SUCCESS :
+                            cellularSetup.State.ACTIVATION_FAILURE;
+  },
+
+  /** @private */
   onBackwardNavRequested_: function() {
     // TODO(azeemarshad): Add back navigation.
   },
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
index c3852a9c..43e2dcb 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.html
@@ -2,13 +2,47 @@
 
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/base_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/webview_post_util.html">
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
 
 <dom-module id="provisioning-page">
   <template>
-    <base-page title="[[i18n('provisioningPageTitle')]]">
-      <div slot="page-body">
-        <!-- TODO(azeemarshad): Add webview and error screen -->
-        [[i18n('provisioningPageTitle')]]
+    <style include="iron-flex cr-hidden-style">
+      paper-spinner-lite {
+        height: 200px;
+        width: 200px;
+      }
+
+      #portalContainer {
+        height: 100%;
+        width: 100%;
+      }
+
+      #error-icon-container {
+        background-image: -webkit-image-set(
+            url(error_1x.png) 1x,
+            url(error_2x.png) 2x);
+        background-position: center center;
+        background-repeat: no-repeat;
+        height: 100%;
+        width: 100%;
+      }
+    </style>
+    <base-page title="[[getPageTitle_(
+                            showError, carrierName_, hasCarrierPortalLoaded_)]]"
+        message="[[getPageMessage_(showError)]]">
+      <div slot="page-body" class="layout horizontal center-center">
+        <paper-spinner-lite active
+            hidden$="[[!shouldShowSpinner_(
+                           showError, hasCarrierPortalLoaded_)]]">
+        </paper-spinner-lite>
+        <div id="portalContainer"
+            hidden$="[[!shouldShowPortal_(
+                           showError, hasCarrierPortalLoaded_)]]">
+        </div>
+        <div id="error-icon-container" hidden$="[[!showError]]"></div>
       </div>
     </base-page>
   </template>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.js
index 8c89b909..c389d04 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.js
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/provisioning_page.js
@@ -21,6 +21,189 @@
     showError: {
       type: Boolean,
       value: false,
+      notify: true,
     },
+
+    /**
+     * Metadata used to open carrier provisioning portal. Expected to start as
+     * null, then change to a valid object.
+     * @type {?chromeos.cellularSetup.mojom.CellularMetadata}
+     */
+    cellularMetadata: {
+      type: Object,
+      value: null,
+      observer: 'onCellularMetadataChanged_',
+    },
+
+    /**
+     * Whether the carrier portal has completed being loaded.
+     * @private {boolean}
+     */
+    hasCarrierPortalLoaded_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * The last carrier name provided via |cellularMetadata|.
+     * @private {string}
+     */
+    carrierName_: {
+      type: String,
+      value: '',
+    },
+  },
+
+  /**
+   * @return {string}
+   * @private
+   */
+  getPageTitle_: function() {
+    if (this.showError) {
+      return this.i18n('provisioningPageErrorTitle', this.carrierName_);
+    }
+    if (this.hasCarrierPortalLoaded_) {
+      return this.i18n('provisioningPageActiveTitle');
+    }
+    return this.i18n('provisioningPageLoadingTitle', this.carrierName_);
+  },
+
+  /**
+   * @return {string}
+   * @private
+   */
+  getPageMessage_: function() {
+    if (this.showError) {
+      return this.i18n('provisioningPageErrorMessage', this.carrierName_);
+    }
+    return '';
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowSpinner_: function() {
+    return !this.showError && !this.hasCarrierPortalLoaded_;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowPortal_: function() {
+    return !this.showError && this.hasCarrierPortalLoaded_;
+  },
+
+  /**
+   * @return {?WebView}
+   * @private
+   */
+  getPortalWebview: function() {
+    return /** @type {?WebView} */ (this.$$('webview'));
+  },
+
+  /** @private */
+  onCellularMetadataChanged_: function() {
+    // Once |cellularMetadata| has been set, load the carrier provisioning page.
+    if (this.cellularMetadata) {
+      this.carrierName_ = this.cellularMetadata.carrier;
+      this.loadPortal_();
+      return;
+    }
+
+    // If |cellularMetadata| is now null, the page should be reset so that a new
+    // attempt can begin.
+    this.resetPage_();
+  },
+
+  /** @private */
+  loadPortal_: function() {
+    assert(!!this.cellularMetadata);
+    assert(!this.getPortalWebview());
+
+    const portalWebview =
+        /** @type {!WebView} */ (document.createElement('webview'));
+    this.$.portalContainer.appendChild(portalWebview);
+
+    portalWebview.addEventListener(
+        'loadabort', this.onPortalLoadAbort_.bind(this));
+    portalWebview.addEventListener(
+        'loadstop', this.onPortalLoadStop_.bind(this));
+    window.addEventListener('message', this.onMessageReceived_.bind(this));
+
+    // Setting a <webview>'s "src" attribute triggers a GET request, but some
+    // carrier portals require a POST request instead. If data is provided for a
+    // POST request body, use a utility function to load the webview.
+    if (this.cellularMetadata.paymentPostData) {
+      webviewPost.util.postDeviceDataToWebview(
+          portalWebview, this.cellularMetadata.paymentUrl.url,
+          this.cellularMetadata.paymentPostData);
+      return;
+    }
+
+    // Otherwise, use a normal GET request by specifying the "src".
+    portalWebview.src = this.cellularMetadata.paymentUrl.url;
+  },
+
+  /** @private */
+  resetPage_: function() {
+    this.hasCarrierPortalLoaded_ = false;
+
+    // Remove the portal from the DOM if it exists.
+    const portalWebview = this.getPortalWebview();
+    if (portalWebview) {
+      portalWebview.remove();
+    }
+  },
+
+  /** @private */
+  onPortalLoadAbort_: function(event) {
+    this.showError = true;
+  },
+
+  /** @private */
+  onPortalLoadStop_: function() {
+    if (this.hasCarrierPortalLoaded_) {
+      return;
+    }
+
+    this.hasCarrierPortalLoaded_ = true;
+    this.fire('carrier-portal-loaded');
+
+    // When the portal loads, it expects to receive a message from this frame
+    // alerting it that loading has completed successfully.
+    this.getPortalWebview().contentWindow.postMessage(
+        {msg: 'loadedInWebview'}, this.cellularMetadata.paymentUrl.url);
+  },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onMessageReceived_: function(event) {
+    const messageType = /** @type {string} */ (event.data.type);
+    const status = /** @type {string} */ (event.data.status);
+
+    // The <webview> requested information about this device. Reply by posting a
+    // message back to it.
+    if (messageType == 'requestDeviceInfoMsg') {
+      this.getPortalWebview().contentWindow.postMessage(
+          {
+            carrier: this.cellularMetadata.carrier,
+            MEID: this.cellularMetadata.meid,
+            IMEI: this.cellularMetadata.imei,
+            MDN: this.cellularMetadata.mdn
+          },
+          this.cellularMetadata.paymentUrl.url);
+      return;
+    }
+
+    // The <webview> provided an update on the status of the activation attempt.
+    if (messageType == 'reportTransactionStatusMsg') {
+      const success = status == 'ok';
+      this.fire('on-carrier-portal-result', success);
+      return;
+    }
   },
 });
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.html b/ui/webui/resources/cr_components/chromeos/network/network_config.html
index 83bb186..f46eb34dd 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.html
@@ -34,7 +34,9 @@
       <!-- SSID (WiFi) -->
       <template is="dom-if" if="[[isType_(NetworkType_.WI_FI, type)]]" restamp>
         <network-config-input id="ssid" label="[[i18n('OncWiFi-SSID')]]"
-            value="{{configProperties_.WiFi.SSID}}" readonly="[[hasGuid_(guid)]]">
+            value="{{configProperties_.WiFi.SSID}}"
+            readonly="[[hasGuid_(guid)]]"
+            on-enter="onEnterPressedInInput_">
         </network-config-input>
       </template>
 
@@ -54,7 +56,7 @@
           restamp>
         <network-password-input label="[[i18n('OncWiFi-Passphrase')]]"
             value="{{configProperties_.WiFi.Passphrase}}"
-            on-enter="onEnterPressedInPasswordInput_"
+            on-enter="onEnterPressedInInput_"
             property="[[managedProperties.WiFi.Passphrase]]">
         </network-password-input>
       </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.js b/ui/webui/resources/cr_components/chromeos/network/network_config.js
index ade9cad..dc238fe1 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -476,7 +476,7 @@
   },
 
   /** @private */
-  onEnterPressedInPasswordInput_: function() {
+  onEnterPressedInInput_: function() {
     if (!this.isConfigured_) {
       return;
     }
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
index 5f66677b..fe7fafb 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
@@ -28,7 +28,8 @@
     <div id="container">
       <cr-input label="[[label]]" value="{{value}}"
           hidden="[[hidden]]" readonly="[[readonly]]"
-          disabled="[[getDisabled_(disabled, property)]]">
+          disabled="[[getDisabled_(disabled, property)]]"
+          on-keypress="onKeypress_">
       </cr-input>
       <cr-policy-network-indicator
           property="[[property]]" tooltip-position="left">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.js b/ui/webui/resources/cr_components/chromeos/network/network_config_input.js
index e5281f2..295fb7d 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_input.js
@@ -32,4 +32,16 @@
   focus: function() {
     this.$$('cr-input').focus();
   },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onKeypress_: function(event) {
+    if (event.key != 'Enter') {
+      return;
+    }
+    event.stopPropagation();
+    this.fire('enter');
+  },
 });
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 80f3d4e8..6ae9a93 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -33,6 +33,7 @@
     "cr_checkbox:closure_compile_module",
     "cr_icon_button:closure_compile_module",
     "cr_input:closure_compile_module",
+    "cr_radio_button:closure_compile_module",
     "cr_toast:closure_compile_module",
     "cr_toggle:closure_compile_module",
     "cr_view_manager:closure_compile_module",
@@ -119,6 +120,9 @@
     "cr_icon_button:cr_icon_button_module",
     "cr_input:cr_input_module",
     "cr_input:cr_input_style_css_module",
+    "cr_radio_button:cr_radio_button_module",
+    "cr_radio_button:cr_radio_button_style_css_module",
+    "cr_radio_button:modulize",
     "cr_toast:cr_toast_module",
     "cr_toggle:cr_toggle_module",
     "cr_view_manager:cr_view_manager_module",
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
index 0e7c4668..50c62df1 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../../tools/js_modulizer.gni")
 
 js_type_check("closure_compile") {
   deps = [
@@ -21,3 +23,55 @@
     "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
   ]
 }
+
+# Targets for auto-generating and typechecking Polymer 3 JS modules
+
+js_modulizer("modulize") {
+  input_files = [ "cr_radio_button_behavior.js" ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
+  ]
+  namespace_rewrites = [ "Polymer.PaperRippleBehavior|PaperRippleBehavior" ]
+}
+
+polymer_modulizer("cr_radio_button") {
+  js_file = "cr_radio_button.js"
+  html_file = "cr_radio_button.html"
+  html_type = "dom-module"
+  auto_imports = [ "ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html|CrRadioButtonBehavior" ]
+}
+
+polymer_modulizer("cr_radio_button_style_css") {
+  js_file = "cr_radio_button_style_css.m.js"
+  html_file = "cr_radio_button_style_css.html"
+  html_type = "style-module"
+}
+
+js_type_check("closure_compile_module") {
+  is_polymer3 = true
+  deps = [
+    ":cr_radio_button.m",
+    ":cr_radio_button_behavior.m",
+  ]
+}
+
+js_library("cr_radio_button.m") {
+  sources = [
+    "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.m.js",
+  ]
+  deps = [
+    ":cr_radio_button_behavior.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+  extra_deps = [ ":cr_radio_button_module" ]
+}
+
+js_library("cr_radio_button_behavior.m") {
+  sources = [
+    "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js",
+  ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
+  ]
+  extra_deps = [ ":modulize" ]
+}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js
index 8ccc382..9cb515f4 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js
+++ b/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.js
@@ -6,6 +6,10 @@
  * @fileoverview Behavior for cr-radio-button-like elements.
  */
 
+// clang-format off
+// #import {PaperRippleBehavior} from 'chrome://resources/polymer/v3_0/paper-behaviors/paper-ripple-behavior.js'
+// clang-format on
+
 /** @polymerBehavior */
 const CrRadioButtonBehaviorImpl = {
   properties: {
@@ -89,7 +93,7 @@
 
 
 /** @polymerBehavior */
-const CrRadioButtonBehavior = [
+/* #export */ const CrRadioButtonBehavior = [
   Polymer.PaperRippleBehavior,
   CrRadioButtonBehaviorImpl,
 ];
diff --git a/ui/webui/resources/cr_elements_resources_v3.grdp b/ui/webui/resources/cr_elements_resources_v3.grdp
index ef96084..0c58094 100644
--- a/ui/webui/resources/cr_elements_resources_v3.grdp
+++ b/ui/webui/resources/cr_elements_resources_v3.grdp
@@ -31,6 +31,21 @@
          use_base_dir="false"
          type="BINDATA"
          compress="gzip" />
+  <include name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_M_JS"
+         file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.m.js"
+         use_base_dir="false"
+         type="BINDATA"
+         compress="gzip" />
+  <include name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_BEHAVIOR_M_JS"
+         file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js"
+         use_base_dir="false"
+         type="BINDATA"
+         compress="gzip" />
+  <include name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_STYLE_CSS_M_JS"
+         file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_style_css.m.js"
+         use_base_dir="false"
+         type="BINDATA"
+         compress="gzip" />
   <include name="IDR_CR_ELEMENTS_CR_SHARED_STYLE_CSS_M_JS"
          file="${root_gen_dir}/ui/webui/resources/cr_elements/shared_style_css.m.js"
          use_base_dir="false"