diff --git a/.gn b/.gn
index 70856f6..3a7b224f 100644
--- a/.gn
+++ b/.gn
@@ -386,7 +386,6 @@
   # "//third_party/crashpad/*", 20ish errors
   "//third_party/crc32c/*",
   "//third_party/cros_system_api/*",
-  "//third_party/custom_tabs_client/*",
   "//third_party/cython/*",
   "//third_party/d3/*",
   "//third_party/dawn/*",
diff --git a/DEPS b/DEPS
index de97104..01dac9e 100644
--- a/DEPS
+++ b/DEPS
@@ -145,11 +145,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': '87cef069cab4d8a4742d35a1bb1fb31644213045',
+  'skia_revision': '593290ed75fd3fbf060d94021925cdf76c62c38e',
   # 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': 'f94fe17b50a5c62280c5ea7bfee8caa9f091203e',
+  'v8_revision': 'c760764140d5b95cf53a6b39e4c151c7578e3a59',
   # 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.
@@ -157,7 +157,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': '415bb0cdb057f60f684b3c01731a4f0e93e3630d',
+  'angle_revision': '483ee3fa2315298aba6cbaf6f62d515f7214c0f7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -280,7 +280,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '38ee172a228dd28550aa7b7c4c6ff1532ad4d35b',
+  'dawn_revision': '1cd83ffbdd5d5f870f57398768555d3d97068177',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -404,7 +404,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/autofill/captured_sites',
-        'version': 'x-MlaiKZT7T-YaM3_ZEyIqsILkx9IvGpvrZHmXq0EiEC',
+        'version': '27xauHcZofjRobU1o1UZrUuYaK_No7r2SSaMT6gzwd0C',
       }
     ],
     'condition': 'checkout_chromium_autofill_test_dependencies',
@@ -415,7 +415,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/password/captured_sites',
-        'version': 'fh4O86nUCfRN5a1Piw48cbufqayIfZQjCDbFDKXnRwEC',
+        'version': '484POXsN4YniZtOU5CH6WWuVHJK82SmGIjbpxvEHaR0C',
       }
     ],
     'condition': 'checkout_chromium_password_manager_test_dependencies',
@@ -664,6 +664,11 @@
       'dep_type': 'cipd',
   },
 
+  'src/third_party/android_sdk/androidx_browser/src': {
+      'url': Var('chromium_git') + '/external/gob/android/platform/frameworks/support/browser.git' + '@' + 'aeeea8bd0a6703bc4a148e9bcd6998553def74ab',
+      'condition': 'checkout_android',
+  },
+
   'src/third_party/android_sdk/public': {
       'packages': [
           {
@@ -824,7 +829,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'c59652b94a7e9157193b5d631f3f061ccd282553',
+      'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'c267899484bac0f024a10b32452d4cee6ffa6068',
       'condition': 'checkout_linux',
   },
 
@@ -1207,7 +1212,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cb5dd5c30dd6b780ab4b012147f915c934c131a4',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '887948c03303365c7466f047e93e634bd1ca6ae2',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1375,7 +1380,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '1e49ab2d40eba7a3a15d00db998f3f5a6703a167',
+    Var('webrtc_git') + '/src.git' + '@' + 'b6685420c42a6b0903e2d4e9e5a270261d30a52d',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1416,7 +1421,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@43dbb476f6af5174d90e971d3a3d812385af9e7b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@97c6c359d43f7b1c926208166ae4a4029d8b3bd8',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index f6afcd0..09b52ea3 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1240,6 +1240,8 @@
 _GENERIC_PYDEPS_FILES = [
     'chrome/test/chromedriver/test/run_py_tests.pydeps',
     'chrome/test/chromedriver/log_replay/client_replay_unittest.pydeps',
+    'third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps',
+    'third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps',
     'tools/binary_size/sizes.pydeps',
     'tools/binary_size/supersize.pydeps',
 ]
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index 5bbd04f..cc12b05 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -24,6 +24,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
@@ -363,8 +364,9 @@
   const GURL& new_host = MaybeFixUpSchemeForSecureCookie(host, value);
 
   net::CanonicalCookie::CookieInclusionStatus status;
-  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-      new_host, value, base::Time::Now(), options, &status));
+  std::unique_ptr<net::CanonicalCookie> cc(
+      net::CanonicalCookie::Create(new_host, value, base::Time::Now(),
+                                   base::nullopt /* server_time */, &status));
 
   if (!cc) {
     MaybeRunCookieCallback(std::move(callback), false);
diff --git a/android_webview/browser/gfx/BUILD.gn b/android_webview/browser/gfx/BUILD.gn
index a84f09e..25534221 100644
--- a/android_webview/browser/gfx/BUILD.gn
+++ b/android_webview/browser/gfx/BUILD.gn
@@ -34,6 +34,8 @@
     "gpu_service_web_view.h",
     "hardware_renderer.cc",
     "hardware_renderer.h",
+    "hardware_renderer_single_thread.cc",
+    "hardware_renderer_single_thread.h",
     "java_browser_view_renderer_helper.cc",
     "java_browser_view_renderer_helper.h",
     "parent_compositor_draw_constraints.cc",
diff --git a/android_webview/browser/gfx/aw_draw_fn_impl.h b/android_webview/browser/gfx/aw_draw_fn_impl.h
index aa54c39c..6df9e6b 100644
--- a/android_webview/browser/gfx/aw_draw_fn_impl.h
+++ b/android_webview/browser/gfx/aw_draw_fn_impl.h
@@ -13,6 +13,7 @@
 #include "android_webview/public/browser/draw_fn.h"
 #include "base/android/jni_weak_ref.h"
 #include "base/containers/queue.h"
+#include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
diff --git a/android_webview/browser/gfx/hardware_renderer.cc b/android_webview/browser/gfx/hardware_renderer.cc
index ab08d974..f9bfa23 100644
--- a/android_webview/browser/gfx/hardware_renderer.cc
+++ b/android_webview/browser/gfx/hardware_renderer.cc
@@ -9,55 +9,27 @@
 #include <memory>
 #include <utility>
 
-#include "android_webview/browser/gfx/aw_gl_surface.h"
-#include "android_webview/browser/gfx/aw_render_thread_context_provider.h"
 #include "android_webview/browser/gfx/parent_compositor_draw_constraints.h"
 #include "android_webview/browser/gfx/render_thread_manager.h"
-#include "android_webview/browser/gfx/surfaces_instance.h"
-#include "android_webview/common/aw_switches.h"
-#include "base/command_line.h"
 #include "base/logging.h"
-#include "base/macros.h"
 #include "base/trace_event/trace_event.h"
+#include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
-#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "ui/gfx/transform.h"
 #include "ui/gl/gl_bindings.h"
 
 namespace android_webview {
 
 HardwareRenderer::HardwareRenderer(RenderThreadManager* state)
     : render_thread_manager_(state),
-      surfaces_(SurfacesInstance::GetOrCreateInstance()),
-      last_egl_context_(surfaces_->is_using_vulkan() ? nullptr
-                                                     : eglGetCurrentContext()),
-      frame_sink_id_(surfaces_->AllocateFrameSinkId()),
-      parent_local_surface_id_allocator_(
-          std::make_unique<viz::ParentLocalSurfaceIdAllocator>()),
-      last_committed_layer_tree_frame_sink_id_(0u),
-      last_submitted_layer_tree_frame_sink_id_(0u) {
-  DCHECK(surfaces_->is_using_vulkan() || last_egl_context_);
-  surfaces_->GetFrameSinkManager()->RegisterFrameSinkId(
-      frame_sink_id_, true /* report_activation */);
-  surfaces_->GetFrameSinkManager()->SetFrameSinkDebugLabel(frame_sink_id_,
-                                                           "HardwareRenderer");
-  CreateNewCompositorFrameSinkSupport();
-}
+      last_egl_context_(eglGetCurrentContext()) {}
 
 HardwareRenderer::~HardwareRenderer() {
-  // Must reset everything before |surface_factory_| to ensure all
-  // resources are returned before resetting.
-  if (child_id_.is_valid())
-    DestroySurface();
-  support_.reset();
-  surfaces_->GetFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
-
   // Reset draw constraints.
-  render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
-      ParentCompositorDrawConstraints(), compositor_id_,
-      viz::FrameTimingDetailsMap(), 0u);
+  if (child_frame_) {
+    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
+        ParentCompositorDrawConstraints(), child_frame_->compositor_id,
+        viz::FrameTimingDetailsMap(), 0u);
+  }
   for (auto& child_frame : child_frame_queue_) {
     child_frame->WaitOnFutureIfNeeded();
     ReturnChildFrame(std::move(child_frame));
@@ -85,8 +57,7 @@
 }
 
 void HardwareRenderer::Draw(HardwareRendererDrawParams* params) {
-  TRACE_EVENT1("android_webview", "HardwareRenderer::Draw", "vulkan",
-               surfaces_->is_using_vulkan());
+  TRACE_EVENT0("android_webview", "HardwareRenderer::Draw");
 
   for (auto& pruned_frame : WaitAndPruneFrameQueue(&child_frame_queue_))
     ReturnChildFrame(std::move(pruned_frame));
@@ -100,7 +71,7 @@
         child_frame_->layer_tree_frame_sink_id;
   }
 
-  if (!surfaces_->is_using_vulkan()) {
+  if (last_egl_context_) {
     // We need to watch if the current Android context has changed and enforce a
     // clean-up in the compositor.
     EGLContext current_context = eglGetCurrentContext();
@@ -111,126 +82,34 @@
       DLOG(WARNING) << "EGLContextChanged";
   }
 
-  bool submitted_new_frame = false;
-  uint32_t frame_token = 0u;
-  // SurfaceFactory::SubmitCompositorFrame might call glFlush. So calling it
-  // during "kModeSync" stage (which does not allow GL) might result in extra
-  // kModeProcess. Instead, submit the frame in "kModeDraw" stage to avoid
-  // unnecessary kModeProcess.
-  if (child_frame_.get() && child_frame_->frame.get()) {
-    if (!compositor_id_.Equals(child_frame_->compositor_id) ||
-        last_submitted_layer_tree_frame_sink_id_ !=
-            child_frame_->layer_tree_frame_sink_id) {
-      if (child_id_.is_valid())
-        DestroySurface();
+  DrawAndSwap(params);
+}
 
-      CreateNewCompositorFrameSinkSupport();
-      compositor_id_ = child_frame_->compositor_id;
-      last_submitted_layer_tree_frame_sink_id_ =
-          child_frame_->layer_tree_frame_sink_id;
-    }
-
-    std::unique_ptr<viz::CompositorFrame> child_compositor_frame =
-        std::move(child_frame_->frame);
-
-    float device_scale_factor = child_compositor_frame->device_scale_factor();
-    gfx::Size frame_size = child_compositor_frame->size_in_pixels();
-    if (!child_id_.is_valid() || surface_size_ != frame_size ||
-        device_scale_factor_ != device_scale_factor) {
-      if (child_id_.is_valid())
-        DestroySurface();
-      AllocateSurface();
-      surface_size_ = frame_size;
-      device_scale_factor_ = device_scale_factor;
-    }
-
-    frame_token = child_compositor_frame->metadata.frame_token;
-    support_->SubmitCompositorFrame(child_id_,
-                                    std::move(*child_compositor_frame));
-    submitted_new_frame = true;
-  }
-
-  gfx::Transform transform(gfx::Transform::kSkipInitialization);
-  transform.matrix().setColMajorf(params->transform);
-  transform.Translate(scroll_offset_.x(), scroll_offset_.y());
-
-  gfx::Size viewport(params->width, params->height);
-  // Need to post the new transform matrix back to child compositor
-  // because there is no onDraw during a Render Thread animation, and child
-  // compositor might not have the tiles rasterized as the animation goes on.
-  ParentCompositorDrawConstraints draw_constraints(viewport, transform);
-  bool need_to_update_draw_constraints =
-      !child_frame_.get() || draw_constraints.NeedUpdate(*child_frame_);
-
-  // Post data after draw if submitted_new_frame, since we may have
-  // presentation feedback to return as well.
-  if (need_to_update_draw_constraints && !submitted_new_frame) {
-    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
-        draw_constraints, compositor_id_, viz::FrameTimingDetailsMap(), 0u);
-  }
-
-  if (!child_id_.is_valid())
+void HardwareRenderer::ReturnChildFrame(
+    std::unique_ptr<ChildFrame> child_frame) {
+  if (!child_frame || !child_frame->frame)
     return;
 
-  CopyOutputRequestQueue requests;
-  requests.swap(child_frame_->copy_requests);
-  for (auto& copy_request : requests) {
-    support_->RequestCopyOfOutput(child_id_, std::move(copy_request));
-  }
+  std::vector<viz::ReturnedResource> resources_to_return =
+      viz::TransferableResource::ReturnResources(
+          child_frame->frame->resource_list);
 
-  gfx::Rect clip(params->clip_left, params->clip_top,
-                 params->clip_right - params->clip_left,
-                 params->clip_bottom - params->clip_top);
-  surfaces_->DrawAndSwap(viewport, clip, transform, surface_size_,
-                         viz::SurfaceId(frame_sink_id_, child_id_),
-                         device_scale_factor_, params->color_space);
-  viz::FrameTimingDetailsMap timing_details =
-      support_->TakeFrameTimingDetailsMap();
-  if (submitted_new_frame) {
-    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
-        draw_constraints, compositor_id_, std::move(timing_details),
-        frame_token);
-  }
+  // The child frame's compositor id is not necessarily same as
+  // compositor_id_.
+  ReturnResourcesToCompositor(resources_to_return, child_frame->compositor_id,
+                              child_frame->layer_tree_frame_sink_id);
 }
 
-void HardwareRenderer::AllocateSurface() {
-  DCHECK(!child_id_.is_valid());
-  parent_local_surface_id_allocator_->GenerateId();
-  child_id_ =
-      parent_local_surface_id_allocator_->GetCurrentLocalSurfaceIdAllocation()
-          .local_surface_id();
-  surfaces_->AddChildId(viz::SurfaceId(frame_sink_id_, child_id_));
+void HardwareRenderer::ReturnResourcesToCompositor(
+    const std::vector<viz::ReturnedResource>& resources,
+    const CompositorID& compositor_id,
+    uint32_t layer_tree_frame_sink_id) {
+  if (layer_tree_frame_sink_id != last_committed_layer_tree_frame_sink_id_)
+    return;
+  render_thread_manager_->InsertReturnedResourcesOnRT(resources, compositor_id,
+                                                      layer_tree_frame_sink_id);
 }
 
-void HardwareRenderer::DestroySurface() {
-  DCHECK(child_id_.is_valid());
-
-  surfaces_->RemoveChildId(viz::SurfaceId(frame_sink_id_, child_id_));
-  support_->EvictSurface(child_id_);
-  child_id_ = viz::LocalSurfaceId();
-  surfaces_->GetFrameSinkManager()->surface_manager()->GarbageCollectSurfaces();
-}
-
-void HardwareRenderer::DidReceiveCompositorFrameAck(
-    const std::vector<viz::ReturnedResource>& resources) {
-  ReturnResourcesToCompositor(resources, compositor_id_,
-                              last_submitted_layer_tree_frame_sink_id_);
-}
-
-void HardwareRenderer::OnBeginFrame(
-    const viz::BeginFrameArgs& args,
-    const viz::FrameTimingDetailsMap& timing_details) {
-  NOTREACHED();
-}
-
-void HardwareRenderer::ReclaimResources(
-    const std::vector<viz::ReturnedResource>& resources) {
-  ReturnResourcesToCompositor(resources, compositor_id_,
-                              last_submitted_layer_tree_frame_sink_id_);
-}
-
-void HardwareRenderer::OnBeginFramePausedChanged(bool paused) {}
-
 namespace {
 
 void MoveCopyRequests(CopyOutputRequestQueue* from,
@@ -284,38 +163,4 @@
   return pruned_frames;
 }
 
-void HardwareRenderer::ReturnChildFrame(
-    std::unique_ptr<ChildFrame> child_frame) {
-  if (!child_frame || !child_frame->frame)
-    return;
-
-  std::vector<viz::ReturnedResource> resources_to_return =
-      viz::TransferableResource::ReturnResources(
-          child_frame->frame->resource_list);
-
-  // The child frame's compositor id is not necessarily same as
-  // compositor_id_.
-  ReturnResourcesToCompositor(resources_to_return, child_frame->compositor_id,
-                              child_frame->layer_tree_frame_sink_id);
-}
-
-void HardwareRenderer::ReturnResourcesToCompositor(
-    const std::vector<viz::ReturnedResource>& resources,
-    const CompositorID& compositor_id,
-    uint32_t layer_tree_frame_sink_id) {
-  if (layer_tree_frame_sink_id != last_committed_layer_tree_frame_sink_id_)
-    return;
-  render_thread_manager_->InsertReturnedResourcesOnRT(resources, compositor_id,
-                                                      layer_tree_frame_sink_id);
-}
-
-void HardwareRenderer::CreateNewCompositorFrameSinkSupport() {
-  constexpr bool is_root = false;
-  constexpr bool needs_sync_points = true;
-  support_.reset();
-  support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
-      this, surfaces_->GetFrameSinkManager(), frame_sink_id_, is_root,
-      needs_sync_points);
-}
-
 }  // namespace android_webview
diff --git a/android_webview/browser/gfx/hardware_renderer.h b/android_webview/browser/gfx/hardware_renderer.h
index 38a1b29..d41ce4a 100644
--- a/android_webview/browser/gfx/hardware_renderer.h
+++ b/android_webview/browser/gfx/hardware_renderer.h
@@ -8,24 +8,12 @@
 #include <memory>
 
 #include "android_webview/browser/gfx/child_frame.h"
-#include "android_webview/browser/gfx/compositor_id.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "components/viz/common/frame_timing_details_map.h"
-#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
 #include "ui/gfx/color_space.h"
 
-namespace viz {
-class CompositorFrameSinkSupport;
-class ParentLocalSurfaceIdAllocator;
-}
-
 namespace android_webview {
 
-class ChildFrame;
 class RenderThreadManager;
-class SurfacesInstance;
 
 struct HardwareRendererDrawParams {
   int clip_left;
@@ -38,7 +26,7 @@
   gfx::ColorSpace color_space;
 };
 
-class HardwareRenderer : public viz::mojom::CompositorFrameSinkClient {
+class HardwareRenderer {
  public:
   // Two rules:
   // 1) Never wait on |new_frame| on the UI thread, or in kModeSync. Otherwise
@@ -54,21 +42,13 @@
   // * Append new frame without waiting on it.
   static ChildFrameQueue WaitAndPruneFrameQueue(ChildFrameQueue* child_frames);
 
-  explicit HardwareRenderer(RenderThreadManager* state);
-  ~HardwareRenderer() override;
+  virtual ~HardwareRenderer();
 
   void Draw(HardwareRendererDrawParams* params);
   void CommitFrame();
 
- private:
-  // viz::mojom::CompositorFrameSinkClient implementation.
-  void DidReceiveCompositorFrameAck(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFrame(const viz::BeginFrameArgs& args,
-                    const viz::FrameTimingDetailsMap& timing_details) override;
-  void ReclaimResources(
-      const std::vector<viz::ReturnedResource>& resources) override;
-  void OnBeginFramePausedChanged(bool paused) override;
+ protected:
+  explicit HardwareRenderer(RenderThreadManager* state);
 
   void ReturnChildFrame(std::unique_ptr<ChildFrame> child_frame);
   void ReturnResourcesToCompositor(
@@ -76,25 +56,13 @@
       const CompositorID& compositor_id,
       uint32_t layer_tree_frame_sink_id);
 
-  void AllocateSurface();
-  void DestroySurface();
-
-  void CreateNewCompositorFrameSinkSupport();
+  virtual void DrawAndSwap(HardwareRendererDrawParams* params) = 0;
 
   RenderThreadManager* const render_thread_manager_;
 
-  const scoped_refptr<SurfacesInstance> surfaces_;
-
   typedef void* EGLContext;
   EGLContext last_egl_context_;
 
-  // Information about last delegated frame.
-  gfx::Size surface_size_;
-  float device_scale_factor_ = 0;
-
-  // Infromation from UI on last commit.
-  gfx::Vector2d scroll_offset_;
-
   ChildFrameQueue child_frame_queue_;
 
   // This holds the last ChildFrame received. Contains the frame info of the
@@ -102,17 +70,13 @@
   // been submitted.
   std::unique_ptr<ChildFrame> child_frame_;
 
-  viz::FrameSinkId frame_sink_id_;
-  const std::unique_ptr<viz::ParentLocalSurfaceIdAllocator>
-      parent_local_surface_id_allocator_;
-  std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
-  viz::LocalSurfaceId child_id_;
-  CompositorID compositor_id_;
-  // HardwareRenderer guarantees resources are returned in the order of
-  // layer_tree_frame_sink_id, and resources for old output surfaces are
+  // Information from UI on last commit.
+  gfx::Vector2d scroll_offset_;
+
+  // HardwareRendererSingleThread guarantees resources are returned in the order
+  // of layer_tree_frame_sink_id, and resources for old output surfaces are
   // dropped.
-  uint32_t last_committed_layer_tree_frame_sink_id_;
-  uint32_t last_submitted_layer_tree_frame_sink_id_;
+  uint32_t last_committed_layer_tree_frame_sink_id_ = 0u;
 
   DISALLOW_COPY_AND_ASSIGN(HardwareRenderer);
 };
diff --git a/android_webview/browser/gfx/hardware_renderer_single_thread.cc b/android_webview/browser/gfx/hardware_renderer_single_thread.cc
new file mode 100644
index 0000000..f97f90cf
--- /dev/null
+++ b/android_webview/browser/gfx/hardware_renderer_single_thread.cc
@@ -0,0 +1,185 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/gfx/hardware_renderer_single_thread.h"
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+#include "android_webview/browser/gfx/parent_compositor_draw_constraints.h"
+#include "android_webview/browser/gfx/render_thread_manager.h"
+#include "android_webview/browser/gfx/surfaces_instance.h"
+#include "android_webview/common/aw_switches.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
+#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "ui/gfx/transform.h"
+
+namespace android_webview {
+
+HardwareRendererSingleThread::HardwareRendererSingleThread(
+    RenderThreadManager* state)
+    : HardwareRenderer(state),
+      surfaces_(SurfacesInstance::GetOrCreateInstance()),
+      frame_sink_id_(surfaces_->AllocateFrameSinkId()),
+      parent_local_surface_id_allocator_(
+          std::make_unique<viz::ParentLocalSurfaceIdAllocator>()),
+      last_submitted_layer_tree_frame_sink_id_(0u) {
+  surfaces_->GetFrameSinkManager()->RegisterFrameSinkId(
+      frame_sink_id_, true /* report_activation */);
+  surfaces_->GetFrameSinkManager()->SetFrameSinkDebugLabel(
+      frame_sink_id_, "HardwareRendererSingleThread");
+  CreateNewCompositorFrameSinkSupport();
+}
+
+HardwareRendererSingleThread::~HardwareRendererSingleThread() {
+  // Must reset everything before |surface_factory_| to ensure all
+  // resources are returned before resetting.
+  if (child_id_.is_valid())
+    DestroySurface();
+  support_.reset();
+  surfaces_->GetFrameSinkManager()->InvalidateFrameSinkId(frame_sink_id_);
+}
+
+void HardwareRendererSingleThread::DrawAndSwap(
+    HardwareRendererDrawParams* params) {
+  TRACE_EVENT1("android_webview", "HardwareRendererSingleThread::DrawAndSwap",
+               "vulkan", surfaces_->is_using_vulkan());
+
+  bool submitted_new_frame = false;
+  uint32_t frame_token = 0u;
+  // SurfaceFactory::SubmitCompositorFrame might call glFlush. So calling it
+  // during "kModeSync" stage (which does not allow GL) might result in extra
+  // kModeProcess. Instead, submit the frame in "kModeDraw" stage to avoid
+  // unnecessary kModeProcess.
+  if (child_frame_.get() && child_frame_->frame.get()) {
+    if (!compositor_id_.Equals(child_frame_->compositor_id) ||
+        last_submitted_layer_tree_frame_sink_id_ !=
+            child_frame_->layer_tree_frame_sink_id) {
+      if (child_id_.is_valid())
+        DestroySurface();
+
+      CreateNewCompositorFrameSinkSupport();
+      compositor_id_ = child_frame_->compositor_id;
+      last_submitted_layer_tree_frame_sink_id_ =
+          child_frame_->layer_tree_frame_sink_id;
+    }
+
+    std::unique_ptr<viz::CompositorFrame> child_compositor_frame =
+        std::move(child_frame_->frame);
+
+    float device_scale_factor = child_compositor_frame->device_scale_factor();
+    gfx::Size frame_size = child_compositor_frame->size_in_pixels();
+    if (!child_id_.is_valid() || surface_size_ != frame_size ||
+        device_scale_factor_ != device_scale_factor) {
+      if (child_id_.is_valid())
+        DestroySurface();
+      AllocateSurface();
+      surface_size_ = frame_size;
+      device_scale_factor_ = device_scale_factor;
+    }
+
+    frame_token = child_compositor_frame->metadata.frame_token;
+    support_->SubmitCompositorFrame(child_id_,
+                                    std::move(*child_compositor_frame));
+    submitted_new_frame = true;
+  }
+
+  gfx::Transform transform(gfx::Transform::kSkipInitialization);
+  transform.matrix().setColMajorf(params->transform);
+  transform.Translate(scroll_offset_.x(), scroll_offset_.y());
+
+  gfx::Size viewport(params->width, params->height);
+  // Need to post the new transform matrix back to child compositor
+  // because there is no onDraw during a Render Thread animation, and child
+  // compositor might not have the tiles rasterized as the animation goes on.
+  ParentCompositorDrawConstraints draw_constraints(viewport, transform);
+  bool need_to_update_draw_constraints =
+      !child_frame_.get() || draw_constraints.NeedUpdate(*child_frame_);
+
+  // Post data after draw if submitted_new_frame, since we may have
+  // presentation feedback to return as well.
+  if (need_to_update_draw_constraints && !submitted_new_frame) {
+    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
+        draw_constraints, compositor_id_, viz::FrameTimingDetailsMap(), 0u);
+  }
+
+  if (!child_id_.is_valid())
+    return;
+
+  CopyOutputRequestQueue requests;
+  requests.swap(child_frame_->copy_requests);
+  for (auto& copy_request : requests) {
+    support_->RequestCopyOfOutput(child_id_, std::move(copy_request));
+  }
+
+  gfx::Rect clip(params->clip_left, params->clip_top,
+                 params->clip_right - params->clip_left,
+                 params->clip_bottom - params->clip_top);
+  surfaces_->DrawAndSwap(viewport, clip, transform, surface_size_,
+                         viz::SurfaceId(frame_sink_id_, child_id_),
+                         device_scale_factor_, params->color_space);
+  viz::FrameTimingDetailsMap timing_details =
+      support_->TakeFrameTimingDetailsMap();
+  if (submitted_new_frame) {
+    render_thread_manager_->PostParentDrawDataToChildCompositorOnRT(
+        draw_constraints, compositor_id_, std::move(timing_details),
+        frame_token);
+  }
+}
+
+void HardwareRendererSingleThread::AllocateSurface() {
+  DCHECK(!child_id_.is_valid());
+  parent_local_surface_id_allocator_->GenerateId();
+  child_id_ =
+      parent_local_surface_id_allocator_->GetCurrentLocalSurfaceIdAllocation()
+          .local_surface_id();
+  surfaces_->AddChildId(viz::SurfaceId(frame_sink_id_, child_id_));
+}
+
+void HardwareRendererSingleThread::DestroySurface() {
+  DCHECK(child_id_.is_valid());
+
+  surfaces_->RemoveChildId(viz::SurfaceId(frame_sink_id_, child_id_));
+  support_->EvictSurface(child_id_);
+  child_id_ = viz::LocalSurfaceId();
+  surfaces_->GetFrameSinkManager()->surface_manager()->GarbageCollectSurfaces();
+}
+
+void HardwareRendererSingleThread::DidReceiveCompositorFrameAck(
+    const std::vector<viz::ReturnedResource>& resources) {
+  ReturnResourcesToCompositor(resources, compositor_id_,
+                              last_submitted_layer_tree_frame_sink_id_);
+}
+
+void HardwareRendererSingleThread::OnBeginFrame(
+    const viz::BeginFrameArgs& args,
+    const viz::FrameTimingDetailsMap& timing_details) {
+  NOTREACHED();
+}
+
+void HardwareRendererSingleThread::ReclaimResources(
+    const std::vector<viz::ReturnedResource>& resources) {
+  ReturnResourcesToCompositor(resources, compositor_id_,
+                              last_submitted_layer_tree_frame_sink_id_);
+}
+
+void HardwareRendererSingleThread::OnBeginFramePausedChanged(bool paused) {}
+
+void HardwareRendererSingleThread::CreateNewCompositorFrameSinkSupport() {
+  constexpr bool is_root = false;
+  constexpr bool needs_sync_points = true;
+  support_.reset();
+  support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
+      this, surfaces_->GetFrameSinkManager(), frame_sink_id_, is_root,
+      needs_sync_points);
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/gfx/hardware_renderer_single_thread.h b/android_webview/browser/gfx/hardware_renderer_single_thread.h
new file mode 100644
index 0000000..b0cd098
--- /dev/null
+++ b/android_webview/browser/gfx/hardware_renderer_single_thread.h
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_GFX_HARDWARE_RENDERER_SINGLE_THREAD_H_
+#define ANDROID_WEBVIEW_BROWSER_GFX_HARDWARE_RENDERER_SINGLE_THREAD_H_
+
+#include <memory>
+
+#include "android_webview/browser/gfx/compositor_id.h"
+#include "android_webview/browser/gfx/hardware_renderer.h"
+#include "base/memory/ref_counted.h"
+#include "components/viz/common/frame_timing_details_map.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
+
+namespace viz {
+class CompositorFrameSinkSupport;
+class ParentLocalSurfaceIdAllocator;
+}  // namespace viz
+
+namespace android_webview {
+
+class SurfacesInstance;
+
+class HardwareRendererSingleThread
+    : public HardwareRenderer,
+      public viz::mojom::CompositorFrameSinkClient {
+ public:
+  explicit HardwareRendererSingleThread(RenderThreadManager* state);
+  ~HardwareRendererSingleThread() override;
+
+ private:
+  // HardwareRenderer implementation.
+  void DrawAndSwap(HardwareRendererDrawParams* params) override;
+
+  // viz::mojom::CompositorFrameSinkClient implementation.
+  void DidReceiveCompositorFrameAck(
+      const std::vector<viz::ReturnedResource>& resources) override;
+  void OnBeginFrame(const viz::BeginFrameArgs& args,
+                    const viz::FrameTimingDetailsMap& timing_details) override;
+  void ReclaimResources(
+      const std::vector<viz::ReturnedResource>& resources) override;
+  void OnBeginFramePausedChanged(bool paused) override;
+
+  void AllocateSurface();
+  void DestroySurface();
+
+  void CreateNewCompositorFrameSinkSupport();
+
+  const scoped_refptr<SurfacesInstance> surfaces_;
+
+  // Information about last delegated frame.
+  gfx::Size surface_size_;
+  float device_scale_factor_ = 0;
+
+  viz::FrameSinkId frame_sink_id_;
+  const std::unique_ptr<viz::ParentLocalSurfaceIdAllocator>
+      parent_local_surface_id_allocator_;
+  std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
+  viz::LocalSurfaceId child_id_;
+  CompositorID compositor_id_;
+  uint32_t last_submitted_layer_tree_frame_sink_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(HardwareRendererSingleThread);
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_GFX_HARDWARE_RENDERER_SINGLE_THREAD_H_
diff --git a/android_webview/browser/gfx/render_thread_manager.cc b/android_webview/browser/gfx/render_thread_manager.cc
index 64e884f4..62cced8c 100644
--- a/android_webview/browser/gfx/render_thread_manager.cc
+++ b/android_webview/browser/gfx/render_thread_manager.cc
@@ -192,7 +192,7 @@
   ScopedAllowGL allow_gl;
   if (!hardware_renderer_ && !IsInsideHardwareRelease() &&
       HasFrameForHardwareRendererOnRT()) {
-    hardware_renderer_.reset(new HardwareRenderer(this));
+    hardware_renderer_.reset(new HardwareRendererSingleThread(this));
     hardware_renderer_->CommitFrame();
   }
 
diff --git a/android_webview/browser/gfx/render_thread_manager.h b/android_webview/browser/gfx/render_thread_manager.h
index c1d69d10..d74d835 100644
--- a/android_webview/browser/gfx/render_thread_manager.h
+++ b/android_webview/browser/gfx/render_thread_manager.h
@@ -8,7 +8,7 @@
 #include <map>
 
 #include "android_webview/browser/gfx/compositor_frame_consumer.h"
-#include "android_webview/browser/gfx/hardware_renderer.h"
+#include "android_webview/browser/gfx/hardware_renderer_single_thread.h"
 #include "android_webview/browser/gfx/parent_compositor_draw_constraints.h"
 #include "base/logging.h"
 #include "base/macros.h"
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager_unittest.cc b/android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager_unittest.cc
index fc14f73..e391e9ba 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager_unittest.cc
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -29,7 +30,8 @@
 
   void SetWhitelist(std::vector<std::string>&& whitelist, bool expected);
 
-  base::MessageLoopForIO loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_{
+      base::test::ScopedTaskEnvironment::MainThreadType::IO};
   std::unique_ptr<AwSafeBrowsingWhitelistManager> wm_;
 };
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 46e30b6..2ea4f75 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -217,8 +217,6 @@
     "cancel_mode.h",
     "custom_tab/arc_custom_tab_view.cc",
     "custom_tab/arc_custom_tab_view.h",
-    "dbus/ash_dbus_helper.cc",
-    "dbus/ash_dbus_helper.h",
     "dbus/ash_dbus_services.cc",
     "dbus/ash_dbus_services.h",
     "dbus/display_service_provider.cc",
diff --git a/ash/dbus/ash_dbus_helper.cc b/ash/dbus/ash_dbus_helper.cc
deleted file mode 100644
index ba27720..0000000
--- a/ash/dbus/ash_dbus_helper.cc
+++ /dev/null
@@ -1,67 +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 "ash/dbus/ash_dbus_helper.h"
-
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_pump_type.h"
-#include "base/system/sys_info.h"
-#include "base/threading/thread.h"
-#include "chromeos/dbus/constants/dbus_switches.h"
-#include "dbus/bus.h"
-#include "dbus/dbus_statistics.h"
-
-namespace ash {
-
-// static
-std::unique_ptr<AshDBusHelper> AshDBusHelper::CreateWithExistingBus(
-    scoped_refptr<dbus::Bus> bus) {
-  bool use_real_clients = bus != nullptr;
-  // Use WrapUnique so that the constructor can be made private.
-  std::unique_ptr<AshDBusHelper> helper =
-      base::WrapUnique(new AshDBusHelper(use_real_clients));
-  helper->bus_ = bus;
-  return helper;
-}
-
-// static
-std::unique_ptr<AshDBusHelper> AshDBusHelper::Create() {
-  bool use_real_clients = base::SysInfo::IsRunningOnChromeOS() &&
-                          !base::CommandLine::ForCurrentProcess()->HasSwitch(
-                              chromeos::switches::kDbusStub);
-  // Use WrapUnique so that the constructor can be made private.
-  std::unique_ptr<AshDBusHelper> helper =
-      base::WrapUnique(new AshDBusHelper(use_real_clients));
-  helper->InitializeDBus();
-  return helper;
-}
-
-AshDBusHelper::AshDBusHelper(bool use_real_clients)
-    : use_real_clients_(use_real_clients) {}
-
-void AshDBusHelper::InitializeDBus() {
-  dbus::statistics::Initialize();
-  if (!use_real_clients_)
-    return;
-
-  // Create the D-Bus thread.
-  base::Thread::Options thread_options;
-  thread_options.message_pump_type = base::MessagePumpType::IO;
-  dbus_thread_ = std::make_unique<base::Thread>("D-Bus thread");
-  dbus_thread_->StartWithOptions(thread_options);
-
-  // Create the connection to the system bus.
-  dbus::Bus::Options bus_options;
-  bus_options.bus_type = dbus::Bus::SYSTEM;
-  bus_options.connection_type = dbus::Bus::PRIVATE;
-  bus_options.dbus_task_runner = dbus_thread_->task_runner();
-  bus_ = base::MakeRefCounted<dbus::Bus>(bus_options);
-}
-
-AshDBusHelper::~AshDBusHelper() {
-  dbus::statistics::Shutdown();
-}
-
-}  // namespace ash
diff --git a/ash/dbus/ash_dbus_helper.h b/ash/dbus/ash_dbus_helper.h
deleted file mode 100644
index c16e6ce6..0000000
--- a/ash/dbus/ash_dbus_helper.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_DBUS_ASH_DBUS_HELPER_H_
-#define ASH_DBUS_ASH_DBUS_HELPER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-
-namespace base {
-class Thread;
-}
-
-namespace dbus {
-class Bus;
-}
-
-namespace ash {
-
-// In Classic/SingleProcessMash, owns the dbus::Bus* provided by Chrome.
-// In MultiProcessMash, creates and owns the dbus::Bus instance.
-class AshDBusHelper {
- public:
-  // Creates the helper with an existing dbus::Bus instance in single process
-  // mode. If |bus| is null, fake dbus clients are being used and
-  // |use_real_clients_| will be set to false.
-  static std::unique_ptr<AshDBusHelper> CreateWithExistingBus(
-      scoped_refptr<dbus::Bus> bus);
-
-  // Creates the helper in multi process mode.
-  static std::unique_ptr<AshDBusHelper> Create();
-
-  ~AshDBusHelper();
-
-  dbus::Bus* bus() { return bus_.get(); }
-  bool use_real_clients() const { return use_real_clients_; }
-
- protected:
-  explicit AshDBusHelper(bool use_real_clients);
-  void InitializeDBus();
-
- private:
-  // Set to false if fake dbus clients are being used (|bus_| will be null).
-  const bool use_real_clients_;
-
-  // The dbus::Bus instance provided or created (see comments above).
-  scoped_refptr<dbus::Bus> bus_;
-
-  // Thread required when a dbus::Bus instance is created.
-  std::unique_ptr<base::Thread> dbus_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(AshDBusHelper);
-};
-
-}  // namespace ash
-
-#endif  // ASH_DBUS_ASH_DBUS_HELPER_H_
diff --git a/ash/shell.cc b/ash/shell.cc
index bfd323b..c2413a8a 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -23,7 +23,6 @@
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller.h"
 #include "ash/autoclick/autoclick_controller.h"
-#include "ash/dbus/ash_dbus_helper.h"
 #include "ash/dbus/ash_dbus_services.h"
 #include "ash/detachable_base/detachable_base_handler.h"
 #include "ash/detachable_base/detachable_base_notification_controller.h"
@@ -1177,7 +1176,7 @@
   user_metrics_recorder_->OnShellInitialized();
 
   // Initialize the D-Bus bus and services for ash.
-  ash_dbus_helper_ = AshDBusHelper::CreateWithExistingBus(dbus_bus);
+  dbus_bus_ = dbus_bus;
   ash_dbus_services_ = std::make_unique<AshDBusServices>(dbus_bus.get());
 
   // By this point ash shell should have initialized its D-Bus signal
diff --git a/ash/shell.h b/ash/shell.h
index 2e006ac..cf48892 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -91,7 +91,6 @@
 class AccessibilityDelegate;
 class AccessibilityFocusRingControllerImpl;
 class AmbientController;
-class AshDBusHelper;
 class AshDBusServices;
 class AshFocusRules;
 class AppListControllerImpl;
@@ -641,7 +640,8 @@
       accessibility_focus_ring_controller_;
   std::unique_ptr<AmbientController> ambient_controller_;
   std::unique_ptr<AppListControllerImpl> app_list_controller_;
-  std::unique_ptr<AshDBusHelper> ash_dbus_helper_;
+  // May be null in tests or when running on linux-chromeos.
+  scoped_refptr<dbus::Bus> dbus_bus_;
   std::unique_ptr<AshDBusServices> ash_dbus_services_;
   std::unique_ptr<AssistantController> assistant_controller_;
   std::unique_ptr<BacklightsForcedOffSetter> backlights_forced_off_setter_;
diff --git a/ash/system/network/network_icon_unittest.cc b/ash/system/network/network_icon_unittest.cc
index 37b318d..e3f5dec 100644
--- a/ash/system/network/network_icon_unittest.cc
+++ b/ash/system/network/network_icon_unittest.cc
@@ -177,12 +177,6 @@
       CreateStandaloneNetworkProperties("cellular", NetworkType::kCellular,
                                         ConnectionStateType::kNotConnected, 50);
 
-  NetworkStatePropertiesPtr wimax_network = CreateStandaloneNetworkProperties(
-      "wimax", NetworkType::kWiMAX, ConnectionStateType::kNotConnected, 50);
-
-  EXPECT_TRUE(gfx::test::AreImagesEqual(ImageForNetwork(wifi_network.get()),
-                                        ImageForNetwork(wimax_network.get())));
-
   NetworkStatePropertiesPtr tether_network = CreateStandaloneNetworkProperties(
       "tether", NetworkType::kTether, ConnectionStateType::kNotConnected, 50);
 
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc
index b393caf0..81db1d3 100644
--- a/ash/system/network/network_state_list_detailed_view.cc
+++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -65,7 +65,6 @@
   switch (type) {
     case NetworkType::kVPN:
     case NetworkType::kWiFi:
-    case NetworkType::kWiMAX:
       return true;
     case NetworkType::kAll:
     case NetworkType::kCellular:
diff --git a/base/BUILD.gn b/base/BUILD.gn
index c99fad58..604fd0f4b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -625,6 +625,8 @@
     "profiler/register_context.h",
     "profiler/sample_metadata.cc",
     "profiler/sample_metadata.h",
+    "profiler/stack_buffer.cc",
+    "profiler/stack_buffer.h",
     "profiler/stack_sampler.cc",
     "profiler/stack_sampler.h",
     "profiler/stack_sampler_android.cc",
diff --git a/base/profiler/stack_buffer.cc b/base/profiler/stack_buffer.cc
new file mode 100644
index 0000000..c8527147
--- /dev/null
+++ b/base/profiler/stack_buffer.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/stack_buffer.h"
+
+namespace base {
+
+constexpr size_t StackBuffer::kPlatformStackAlignment;
+
+StackBuffer::StackBuffer(size_t buffer_size)
+    : buffer_(new uint8_t[buffer_size + kPlatformStackAlignment - 1]),
+      size_(buffer_size) {}
+
+StackBuffer::~StackBuffer() = default;
+
+}  // namespace base
diff --git a/base/profiler/stack_buffer.h b/base/profiler/stack_buffer.h
new file mode 100644
index 0000000..e678aa2
--- /dev/null
+++ b/base/profiler/stack_buffer.h
@@ -0,0 +1,58 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PROFILER_STACK_BUFFER_H_
+#define BASE_PROFILER_STACK_BUFFER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <memory>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+
+// This class contains a buffer for stack copies that can be shared across
+// multiple instances of StackSampler.
+class BASE_EXPORT StackBuffer {
+ public:
+  // The expected alignment of the stack on the current platform. Windows and
+  // System V AMD64 ABIs on x86, x64, and ARM require the stack to be aligned
+  // to twice the pointer size. Excepted from this requirement is code setting
+  // up the stack during function calls (between pushing the return address
+  // and the end of the function prologue). The profiler will sometimes
+  // encounter this exceptional case for leaf frames.
+  static constexpr size_t kPlatformStackAlignment = 2 * sizeof(uintptr_t);
+
+  StackBuffer(size_t buffer_size);
+  ~StackBuffer();
+
+  // Returns a kPlatformStackAlignment-aligned pointer to the stack buffer.
+  uintptr_t* buffer() const {
+    // Return the first address in the buffer aligned to
+    // kPlatformStackAlignment. The buffer is guaranteed to have enough space
+    // for size() bytes beyond this value.
+    return reinterpret_cast<uintptr_t*>(
+        (reinterpret_cast<uintptr_t>(buffer_.get()) + kPlatformStackAlignment -
+         1) &
+        ~(kPlatformStackAlignment - 1));
+  }
+
+  size_t size() const { return size_; }
+
+ private:
+  // The buffer to store the stack.
+  const std::unique_ptr<uint8_t[]> buffer_;
+
+  // The size of the requested buffer allocation. The actual allocation is
+  // larger to accommodate alignment requirements.
+  const size_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(StackBuffer);
+};
+
+}  // namespace base
+
+#endif  // BASE_PROFILER_STACK_BUFFER_H_
diff --git a/base/profiler/stack_sampler.cc b/base/profiler/stack_sampler.cc
index c191e59..e0704e8 100644
--- a/base/profiler/stack_sampler.cc
+++ b/base/profiler/stack_sampler.cc
@@ -5,22 +5,15 @@
 #include "base/profiler/stack_sampler.h"
 
 #include "base/memory/ptr_util.h"
+#include "base/profiler/stack_buffer.h"
 
 namespace base {
 
-constexpr size_t StackSampler::StackBuffer::kPlatformStackAlignment;
-
-StackSampler::StackBuffer::StackBuffer(size_t buffer_size)
-    : buffer_(new uint8_t[buffer_size + kPlatformStackAlignment - 1]),
-      size_(buffer_size) {}
-
-StackSampler::StackBuffer::~StackBuffer() = default;
-
 StackSampler::StackSampler() = default;
 
 StackSampler::~StackSampler() = default;
 
-std::unique_ptr<StackSampler::StackBuffer> StackSampler::CreateStackBuffer() {
+std::unique_ptr<StackBuffer> StackSampler::CreateStackBuffer() {
   size_t size = GetStackBufferSize();
   if (size == 0)
     return nullptr;
diff --git a/base/profiler/stack_sampler.h b/base/profiler/stack_sampler.h
index f4d7824c..42e14efd 100644
--- a/base/profiler/stack_sampler.h
+++ b/base/profiler/stack_sampler.h
@@ -16,6 +16,7 @@
 class Unwinder;
 class ModuleCache;
 class ProfileBuilder;
+class StackBuffer;
 class StackSamplerTestDelegate;
 
 // StackSampler is an implementation detail of StackSamplingProfiler. It
@@ -23,45 +24,6 @@
 // for a given thread.
 class BASE_EXPORT StackSampler {
  public:
-  // This class contains a buffer for stack copies that can be shared across
-  // multiple instances of StackSampler.
-  class BASE_EXPORT StackBuffer {
-   public:
-    // The expected alignment of the stack on the current platform. Windows and
-    // System V AMD64 ABIs on x86, x64, and ARM require the stack to be aligned
-    // to twice the pointer size. Excepted from this requirement is code setting
-    // up the stack during function calls (between pushing the return address
-    // and the end of the function prologue). The profiler will sometimes
-    // encounter this exceptional case for leaf frames.
-    static constexpr size_t kPlatformStackAlignment = 2 * sizeof(uintptr_t);
-
-    StackBuffer(size_t buffer_size);
-    ~StackBuffer();
-
-    // Returns a kPlatformStackAlignment-aligned pointer to the stack buffer.
-    uintptr_t* buffer() const {
-      // Return the first address in the buffer aligned to
-      // kPlatformStackAlignment. The buffer is guaranteed to have enough space
-      // for size() bytes beyond this value.
-      return reinterpret_cast<uintptr_t*>(
-          (reinterpret_cast<uintptr_t>(buffer_.get()) +
-           kPlatformStackAlignment - 1) &
-          ~(kPlatformStackAlignment - 1));
-    }
-
-    size_t size() const { return size_; }
-
-   private:
-    // The buffer to store the stack.
-    const std::unique_ptr<uint8_t[]> buffer_;
-
-    // The size of the requested buffer allocation. The actual allocation is
-    // larger to accommodate alignment requirements.
-    const size_t size_;
-
-    DISALLOW_COPY_AND_ASSIGN(StackBuffer);
-  };
-
   virtual ~StackSampler();
 
   // Creates a stack sampler that records samples for thread with |thread_id|.
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc
index 6993664..2dbfb7e3 100644
--- a/base/profiler/stack_sampler_impl.cc
+++ b/base/profiler/stack_sampler_impl.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/profiler/profile_builder.h"
 #include "base/profiler/sample_metadata.h"
+#include "base/profiler/stack_buffer.h"
 #include "base/profiler/thread_delegate.h"
 #include "base/profiler/unwinder.h"
 
@@ -237,10 +238,9 @@
   // alignment between values in the original stack and the copy. This uses the
   // platform stack alignment rather than pointer alignment so that the stack
   // copy is aligned to platform expectations.
-  uint8_t* stack_copy_bottom =
-      reinterpret_cast<uint8_t*>(stack_buffer_bottom) +
-      (reinterpret_cast<uintptr_t>(byte_src) &
-       (StackSampler::StackBuffer::kPlatformStackAlignment - 1));
+  uint8_t* stack_copy_bottom = reinterpret_cast<uint8_t*>(stack_buffer_bottom) +
+                               (reinterpret_cast<uintptr_t>(byte_src) &
+                                (StackBuffer::kPlatformStackAlignment - 1));
   uint8_t* byte_dst = stack_copy_bottom;
 
   // Copy bytes verbatim up to the first aligned address.
diff --git a/base/profiler/stack_sampler_impl_unittest.cc b/base/profiler/stack_sampler_impl_unittest.cc
index f86d433..2b373bde 100644
--- a/base/profiler/stack_sampler_impl_unittest.cc
+++ b/base/profiler/stack_sampler_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/profiler/profile_builder.h"
+#include "base/profiler/stack_buffer.h"
 #include "base/profiler/stack_sampler_impl.h"
 #include "base/profiler/thread_delegate.h"
 #include "base/profiler/unwinder.h"
@@ -229,8 +230,7 @@
 
 static constexpr size_t kTestStackBufferSize = sizeof(uintptr_t) * 4;
 
-union alignas(StackSampler::StackBuffer::kPlatformStackAlignment)
-    TestStackBuffer {
+union alignas(StackBuffer::kPlatformStackAlignment) TestStackBuffer {
   uintptr_t as_uintptr[kTestStackBufferSize / sizeof(uintptr_t)];
   uint16_t as_uint16[kTestStackBufferSize / sizeof(uint16_t)];
   uint8_t as_uint8[kTestStackBufferSize / sizeof(uint8_t)];
@@ -301,7 +301,7 @@
 
   // Leave extra space within the stack buffer beyond the end of the stack, but
   // preserve the platform alignment.
-  const size_t extra_space = StackSampler::StackBuffer::kPlatformStackAlignment;
+  const size_t extra_space = StackBuffer::kPlatformStackAlignment;
   uintptr_t* stack_top =
       &stack_buffer.as_uintptr[size(stack_buffer.as_uintptr) -
                                extra_space / sizeof(uintptr_t)];
@@ -439,9 +439,8 @@
       std::make_unique<TestThreadDelegate>(stack),
       std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache);
 
-  std::unique_ptr<StackSampler::StackBuffer> stack_buffer =
-      std::make_unique<StackSampler::StackBuffer>(stack.size() *
-                                                  sizeof(uintptr_t));
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   TestProfileBuilder profile_builder(&module_cache);
   stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder);
 
@@ -457,9 +456,8 @@
       std::make_unique<TestThreadDelegate>(stack),
       std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache);
 
-  std::unique_ptr<StackSampler::StackBuffer> stack_buffer =
-      std::make_unique<StackSampler::StackBuffer>((stack.size() - 1) *
-                                                  sizeof(uintptr_t));
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>((stack.size() - 1) * sizeof(uintptr_t));
   // Make the buffer different than the input stack.
   stack_buffer->buffer()[0] = 100;
   TestProfileBuilder profile_builder(&module_cache);
@@ -486,9 +484,8 @@
                                      &stack_copy_bottom),
       &module_cache);
 
-  std::unique_ptr<StackSampler::StackBuffer> stack_buffer =
-      std::make_unique<StackSampler::StackBuffer>(stack.size() *
-                                                  sizeof(uintptr_t));
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   TestProfileBuilder profile_builder(&module_cache);
 
   stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder);
@@ -510,9 +507,8 @@
       std::make_unique<TestUnwinder>(stack.size(), nullptr, &stack_copy_bottom),
       &module_cache);
 
-  std::unique_ptr<StackSampler::StackBuffer> stack_buffer =
-      std::make_unique<StackSampler::StackBuffer>(stack.size() *
-                                                  sizeof(uintptr_t));
+  std::unique_ptr<StackBuffer> stack_buffer =
+      std::make_unique<StackBuffer>(stack.size() * sizeof(uintptr_t));
   TestProfileBuilder profile_builder(&module_cache);
   stack_sampler_impl.RecordStackFrames(stack_buffer.get(), &profile_builder);
 
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index 482a04c..a5f5e4b 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
+#include "base/profiler/stack_buffer.h"
 #include "base/profiler/stack_sampler.h"
 #include "base/profiler/unwinder.h"
 #include "base/synchronization/lock.h"
@@ -191,7 +192,7 @@
   // A stack-buffer used by the sampler for its work. This buffer is re-used
   // across multiple sampler objects since their execution is serialized on the
   // sampling thread.
-  std::unique_ptr<StackSampler::StackBuffer> stack_buffer_;
+  std::unique_ptr<StackBuffer> stack_buffer_;
 
   // A map of collection ids to collection contexts. Because this class is a
   // singleton that is never destroyed, context objects will never be destructed
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc
index c560af32..b7e4bcd1d 100644
--- a/base/task/sequence_manager/sequence_manager_impl.cc
+++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -847,14 +847,12 @@
   controller_->SetTimerSlack(timer_slack);
 }
 
-void SequenceManagerImpl::AddTaskObserver(
-    MessageLoop::TaskObserver* task_observer) {
+void SequenceManagerImpl::AddTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   main_thread_only().task_observers.AddObserver(task_observer);
 }
 
-void SequenceManagerImpl::RemoveTaskObserver(
-    MessageLoop::TaskObserver* task_observer) {
+void SequenceManagerImpl::RemoveTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   main_thread_only().task_observers.RemoveObserver(task_observer);
 }
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h
index 983968b..a8c1659 100644
--- a/base/task/sequence_manager/sequence_manager_impl.h
+++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -21,7 +21,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
 #include "base/message_loop/message_pump_type.h"
 #include "base/pending_task.h"
 #include "base/run_loop.h"
@@ -41,6 +41,8 @@
 
 namespace base {
 
+class TaskObserver;
+
 namespace trace_event {
 class ConvertableToTraceFormat;
 }  // namespace trace_event
@@ -132,8 +134,8 @@
   bool HasPendingHighResolutionTasks() override;
   bool OnSystemIdle() override;
 
-  void AddTaskObserver(MessageLoop::TaskObserver* task_observer);
-  void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer);
+  void AddTaskObserver(TaskObserver* task_observer);
+  void RemoveTaskObserver(TaskObserver* task_observer);
   void AddDestructionObserver(
       MessageLoopCurrent::DestructionObserver* destruction_observer);
   void RemoveDestructionObserver(
@@ -272,7 +274,7 @@
     std::uniform_real_distribution<double> uniform_distribution;
 
     internal::TaskQueueSelector selector;
-    ObserverList<MessageLoop::TaskObserver>::Unchecked task_observers;
+    ObserverList<TaskObserver>::Unchecked task_observers;
     ObserverList<TaskTimeObserver>::Unchecked task_time_observers;
     std::set<TimeDomain*> time_domains;
     std::unique_ptr<internal::RealTimeDomain> real_time_domain;
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index 84ba2595..d1ec830 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -1578,7 +1578,7 @@
   EXPECT_THAT(run_order, ElementsAre(0u, 1u, 2u, 3u));
 }
 
-class MockTaskObserver : public MessageLoop::TaskObserver {
+class MockTaskObserver : public TaskObserver {
  public:
   MOCK_METHOD1(DidProcessTask, void(const PendingTask& task));
   MOCK_METHOD1(WillProcessTask, void(const PendingTask& task));
@@ -1615,8 +1615,7 @@
   RunLoop().RunUntilIdle();
 }
 
-void RemoveObserverTask(SequenceManagerImpl* manager,
-                        MessageLoop::TaskObserver* observer) {
+void RemoveObserverTask(SequenceManagerImpl* manager, TaskObserver* observer) {
   manager->RemoveTaskObserver(observer);
 }
 
@@ -1669,7 +1668,7 @@
 }
 
 void RemoveQueueObserverTask(scoped_refptr<TestTaskQueue> queue,
-                             MessageLoop::TaskObserver* observer) {
+                             TaskObserver* observer) {
   queue->RemoveTaskObserver(observer);
 }
 
@@ -1963,9 +1962,9 @@
   EXPECT_FALSE(was_nested);
 }
 
-class SequenceNumberCapturingTaskObserver : public MessageLoop::TaskObserver {
+class SequenceNumberCapturingTaskObserver : public TaskObserver {
  public:
-  // MessageLoop::TaskObserver overrides.
+  // TaskObserver overrides.
   void WillProcessTask(const PendingTask& pending_task) override {}
   void DidProcessTask(const PendingTask& pending_task) override {
     sequence_numbers_.push_back(pending_task.sequence_num);
@@ -4162,7 +4161,7 @@
 // TODO(altimin): Add a test that posts an infinite number of other tasks
 // from its destructor.
 
-class QueueTimeTaskObserver : public MessageLoop::TaskObserver {
+class QueueTimeTaskObserver : public TaskObserver {
  public:
   void WillProcessTask(const PendingTask& pending_task) override {
     queue_time_ = pending_task.queue_time;
diff --git a/base/task/sequence_manager/task_queue.cc b/base/task/sequence_manager/task_queue.cc
index 3945d59..a7a0c13 100644
--- a/base/task/sequence_manager/task_queue.cc
+++ b/base/task/sequence_manager/task_queue.cc
@@ -253,14 +253,14 @@
   return impl_->GetQueuePriority();
 }
 
-void TaskQueue::AddTaskObserver(MessageLoop::TaskObserver* task_observer) {
+void TaskQueue::AddTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   if (!impl_)
     return;
   impl_->AddTaskObserver(task_observer);
 }
 
-void TaskQueue::RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) {
+void TaskQueue::RemoveTaskObserver(TaskObserver* task_observer) {
   DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
   if (!impl_)
     return;
diff --git a/base/task/sequence_manager/task_queue.h b/base/task/sequence_manager/task_queue.h
index a62613eb..6c358f06 100644
--- a/base/task/sequence_manager/task_queue.h
+++ b/base/task/sequence_manager/task_queue.h
@@ -21,6 +21,8 @@
 
 namespace base {
 
+class TaskObserver;
+
 namespace trace_event {
 class BlameContext;
 }
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index 8dddc849..f7ce193 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -12,6 +12,7 @@
 #include "base/task/sequence_manager/sequence_manager_impl.h"
 #include "base/task/sequence_manager/time_domain.h"
 #include "base/task/sequence_manager/work_queue.h"
+#include "base/task/task_observer.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/trace_event/blame_context.h"
@@ -697,12 +698,11 @@
   state->EndDictionary();
 }
 
-void TaskQueueImpl::AddTaskObserver(MessageLoop::TaskObserver* task_observer) {
+void TaskQueueImpl::AddTaskObserver(TaskObserver* task_observer) {
   main_thread_only().task_observers.AddObserver(task_observer);
 }
 
-void TaskQueueImpl::RemoveTaskObserver(
-    MessageLoop::TaskObserver* task_observer) {
+void TaskQueueImpl::RemoveTaskObserver(TaskObserver* task_observer) {
   main_thread_only().task_observers.RemoveObserver(task_observer);
 }
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index d1430ab..99bd67e 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8905823319988905248
\ No newline at end of file
+8905797561571658672
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index e8d7d924..017dfd3 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8905833153311204368
\ No newline at end of file
+8905797565613988256
\ No newline at end of file
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index b3145e8..9a52a23 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -369,6 +369,7 @@
     "//third_party/android_deps:javax_inject_javax_inject_java",
     "//third_party/android_media:android_media_java",
     "//third_party/android_sdk:android_gcm_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/android_swipe_refresh:android_swipe_refresh_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
@@ -376,7 +377,6 @@
     "//third_party/cacheinvalidation:cacheinvalidation_javalib",
     "//third_party/cacheinvalidation:cacheinvalidation_proto_java",
     "//third_party/cct_dynamic_module:cct_dynamic_module_java",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
     "//third_party/feed:feed_lib_proto_java",
     "//third_party/gif_player:gif_player_java",
     "//third_party/google_android_play_core:com_google_android_play_core_java",
@@ -710,10 +710,10 @@
     "//third_party/android_deps:com_android_support_mediarouter_v7_java",
     "//third_party/android_deps:com_android_support_recyclerview_v7_java",
     "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//third_party/cacheinvalidation:cacheinvalidation_javalib",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
     "//third_party/hamcrest:hamcrest_java",
     "//ui/android:ui_java",
     "//url/mojom:url_mojom_gurl_java",
@@ -755,7 +755,7 @@
     "//third_party/android_deps:android_support_v4_java",
     "//third_party/android_media:android_media_resources",
     "//third_party/android_support_test_runner:runner_java",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/espresso:espresso_all_java",
     "//third_party/junit:junit",
   ]
@@ -862,13 +862,13 @@
     "//third_party/android_sdk:android_test_runner_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//third_party/blink/public/mojom:mojom_mhtml_load_result_java",
     "//third_party/blink/public/mojom:mojom_platform_java",
     "//third_party/cacheinvalidation:cacheinvalidation_javalib",
     "//third_party/cct_dynamic_module:cct_dynamic_module_java",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
     "//third_party/espresso:espresso_all_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/jsr-305:jsr_305_javalib",
@@ -950,13 +950,13 @@
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
-    "//third_party/android_support_test_runner:rules_java",
-    "//third_party/android_support_test_runner:runner_java",
     "//third_party/android_deps:android_arch_lifecycle_common_java",
-    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
     "//third_party/android_deps:com_android_support_recyclerview_v7_java",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_support_test_runner:rules_java",
+    "//third_party/android_support_test_runner:runner_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/junit",
     "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 6ad1fc1..0d41b49 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -401,11 +401,13 @@
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskCustomTabActivity9.java",
   "java/src/org/chromium/chrome/browser/customtabs/SeparateTaskManagedCustomTabActivity.java",
   "java/src/org/chromium/chrome/browser/customtabs/TranslucentCustomTabActivity.java",
-  "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityInitialPageLoader.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabFactory.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java",
+  "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandler.java",
+  "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java",
+  "java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/TabCreationMode.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
index 201a2be0..a3a24d1 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
@@ -7,10 +7,8 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import android.util.Base64;
 
 import org.chromium.base.Callback;
-import org.chromium.base.Log;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
@@ -24,8 +22,6 @@
  * A handler that provides Autofill Assistant actions for a specific activity.
  */
 class AutofillAssistantActionHandlerImpl implements AutofillAssistantActionHandler {
-    private static final String TAG = "AutofillAssistant";
-
     private final Context mContext;
     private final BottomSheetController mBottomSheetController;
     private final ScrimView mScrimView;
@@ -40,8 +36,8 @@
     }
 
     @Override
-    public void listActions(String userName, String experimentIds, String scriptBundle,
-            Bundle arguments, Callback<Set<String>> callback) {
+    public void listActions(String userName, String experimentIds, Bundle arguments,
+            Callback<Set<String>> callback) {
         if (!AutofillAssistantPreferencesUtil.isAutofillOnboardingAccepted()) {
             callback.onResult(Collections.emptySet());
             return;
@@ -51,16 +47,8 @@
             callback.onResult(Collections.emptySet());
             return;
         }
-        byte[] scriptBundleBytes = null;
-        if (!scriptBundle.isEmpty()) {
-            try {
-                scriptBundleBytes = Base64.decode(scriptBundle, Base64.DEFAULT);
-            } catch (IllegalArgumentException e) {
-                Log.v(TAG, "Invalid script_bundle parameter value: base64 decoding failed.");
-            }
-        }
-        client.listDirectActions(
-                userName, experimentIds, scriptBundleBytes, toArgumentMap(arguments), callback);
+
+        client.listDirectActions(userName, experimentIds, toArgumentMap(arguments), callback);
     }
 
     @Override
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
index 627fdaa9e..7e631ac75 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
@@ -135,8 +135,7 @@
 
     /** Lists available direct actions. */
     public void listDirectActions(String userName, String experimentIds,
-            @Nullable byte[] scriptBundle, Map<String, String> arguments,
-            Callback<Set<String>> callback) {
+            Map<String, String> arguments, Callback<Set<String>> callback) {
         if (mNativeClientAndroid == 0) {
             callback.onResult(Collections.emptySet());
             return;
@@ -146,7 +145,7 @@
 
         // The native side calls sendDirectActionList() on the callback once the controller has
         // results.
-        nativeListDirectActions(mNativeClientAndroid, experimentIds, scriptBundle,
+        nativeListDirectActions(mNativeClientAndroid, experimentIds,
                 arguments.keySet().toArray(new String[arguments.size()]),
                 arguments.values().toArray(new String[arguments.size()]), callback);
     }
@@ -335,8 +334,7 @@
     private native void nativeDestroyUI(long nativeClientAndroid);
     private native void nativeTransferUITo(long nativeClientAndroid, Object otherWebContents);
     private native void nativeListDirectActions(long nativeClientAndroid, String experimentIds,
-            @Nullable byte[] scriptBundle, String[] argumentNames, String[] argumentValues,
-            Object callback);
+            String[] argumentNames, String[] argumentValues, Object callback);
     private native boolean nativePerformDirectAction(long nativeClientAndroid, String actionId,
             String experimentId, String[] argumentNames, String[] argumentValues,
             @Nullable AssistantOnboardingCoordinator onboardingCoordinator);
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java
index 5dfc796..9d61ac4c 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java
@@ -35,6 +35,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -87,12 +88,14 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testAcceptOnboarding() throws Exception {
         testOnboarding(R.id.button_init_ok, true);
     }
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testRejectOnboarding() throws Exception {
         testOnboarding(R.id.button_init_not_ok, false);
     }
@@ -115,6 +118,7 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testOnboardingWithNoTabs() throws Exception {
         AssistantOnboardingCoordinator coordinator = createCoordinator(/* tab= */ null);
         showOnboardingAndWait(coordinator, mCallback);
@@ -126,6 +130,7 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testTransfertControls() throws Exception {
         AssistantOnboardingCoordinator coordinator = createCoordinator(mTab);
 
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
index 785e6ad..7c0b190 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
@@ -32,6 +32,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -91,16 +92,13 @@
 
         FakeDirectActionDefinition list = reporter.mActions.get(0);
         assertEquals("list_assistant_actions", list.mId);
-        assertEquals(3, list.mParameters.size());
+        assertEquals(2, list.mParameters.size());
         assertEquals("user_name", list.mParameters.get(0).mName);
         assertEquals(Type.STRING, list.mParameters.get(0).mType);
         assertEquals(false, list.mParameters.get(0).mRequired);
         assertEquals("experiment_ids", list.mParameters.get(1).mName);
         assertEquals(Type.STRING, list.mParameters.get(1).mType);
         assertEquals(false, list.mParameters.get(1).mRequired);
-        assertEquals("script_bundle", list.mParameters.get(2).mName);
-        assertEquals(Type.STRING, list.mParameters.get(2).mType);
-        assertEquals(false, list.mParameters.get(2).mRequired);
 
         assertEquals(1, list.mResults.size());
         assertEquals("names", list.mResults.get(0).mName);
@@ -120,6 +118,7 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testOnboarding() throws Exception {
         mModuleEntryProvider.setInstalled();
 
@@ -141,6 +140,7 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_greater_than = 22) // TODO(crbug/990118): re-enable
     public void testInstallModuleOnDemand() throws Exception {
         mModuleEntryProvider.setNotInstalled();
 
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandler.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandler.java
index 5d5486b..b3c25bd 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandler.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandler.java
@@ -22,11 +22,10 @@
      *
      * @param userName name of the user to use when sending RPCs. Might be empty.
      * @param experimentIds comma-separated set of experiment ids. Might be empty
-     * @param scriptBundle an optional ScriptBundle proto, base64 encoded. Usually empty.
      * @param arguments extra arguments to include into the RPC. Might be empty.
      * @param callback callback to report the result to
      */
-    void listActions(String userName, String experimentIds, String scriptBundle, Bundle arguments,
+    void listActions(String userName, String experimentIds, Bundle arguments,
             Callback<Set<String>> callback);
 
     /** Performs onboarding and returns the result to the callback. */
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
index bc12444d..c1b53f9 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
@@ -32,7 +32,6 @@
     private static final String ACTION_NAME = "name";
     private static final String EXPERIMENT_IDS = "experiment_ids";
     private static final String ONBOARDING_ACTION = "onboarding";
-    private static final String SCRIPT_BUNDLE = "script_bundle";
     private static final String USER_NAME = "user_name";
 
     /**
@@ -67,7 +66,6 @@
         reporter.addDirectAction(LIST_AA_ACTIONS)
                 .withParameter(USER_NAME, Type.STRING, /* required= */ false)
                 .withParameter(EXPERIMENT_IDS, Type.STRING, /* required= */ false)
-                .withParameter(SCRIPT_BUNDLE, Type.STRING, /* required= */ false)
                 .withResult(LIST_AA_ACTIONS_RESULT, Type.STRING);
 
         reporter.addDirectAction(PERFORM_AA_ACTION)
@@ -113,15 +111,12 @@
         String experimentIds = arguments.getString(EXPERIMENT_IDS, "");
         arguments.remove(EXPERIMENT_IDS);
 
-        String scriptBundle = arguments.getString(SCRIPT_BUNDLE, "");
-        arguments.remove(SCRIPT_BUNDLE);
-
         getDelegate(/* installIfNecessary= */ false, (delegate) -> {
             if (delegate == null) {
                 namesCallback.onResult(FALLBACK_ACTION_SET);
                 return;
             }
-            delegate.listActions(userName, experimentIds, scriptBundle, arguments, namesCallback);
+            delegate.listActions(userName, experimentIds, arguments, namesCallback);
         });
     }
 
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn
index 9a3863d1..0d9a901 100644
--- a/chrome/android/features/start_surface/internal/BUILD.gn
+++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -108,7 +108,7 @@
     deps += [
       "//chrome/android/public/profiles:java",
       "//content/public/android:content_java",
-      "//third_party/custom_tabs_client:custom_tabs_support_java",
+      "//third_party/android_sdk/androidx_browser:androidx_browser_java",
       "//third_party/feed:feed_lib_java",
       "//ui/android:ui_utils_java",
       "//ui/base/mojom:mojom_java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceNavigationDelegate.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceNavigationDelegate.java
index 9675009..8de5396b 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceNavigationDelegate.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceNavigationDelegate.java
@@ -8,7 +8,6 @@
 import android.net.Uri;
 import android.provider.Browser;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate;
@@ -17,6 +16,8 @@
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.mojom.WindowOpenDisposition;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /** Implementation of the {@link NativePageNavigationDelegate} for the explore surface. */
 class ExploreSurfaceNavigationDelegate implements NativePageNavigationDelegate {
     private final Context mContext;
@@ -56,4 +57,4 @@
     public void setIncognito(boolean isIncognito) {
         mIsInCognito = isIncognito;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 545468e1..22591d11 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -1169,7 +1169,7 @@
               <category android:name="androidx.browser.customtabs.category.ColorSchemeCustomization"/>
             </intent-filter>
         </service>
-        <service android:name="android.support.customtabs.PostMessageService" />
+        <service android:name="androidx.browser.customtabs.PostMessageService" />
 
         <!-- Crash reporting services. -->
         <service android:name="org.chromium.chrome.browser.crash.ChromeMinidumpUploadJobService"
diff --git a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
index 337c7b9..7c4c3c4 100644
--- a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
+++ b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
@@ -1578,7 +1578,7 @@
         <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY"/>
       </intent-filter>
     </service>
-    <service android:name="android.support.customtabs.PostMessageService"/>
+    <service android:name="androidx.browser.customtabs.PostMessageService"/>
     <service
         android:exported="true"
         android:externalService="true"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 12141d4..573ef39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -313,6 +313,7 @@
     public static final String SUBRESOURCE_FILTER = "SubresourceFilter";
     public static final String SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT =
             "SwapPixelFormatToFixConvertFromTranslucent";
+    public static final String SYNC_MANUAL_START_ANDROID = "SyncManualStartAndroid";
     public static final String TAB_ENGAGEMENT_REPORTING_ANDROID = "TabEngagementReportingAndroid";
     public static final String TAB_GROUPS_ANDROID = "TabGroupsAndroid";
     public static final String TAB_GROUPS_UI_IMPROVEMENTS_ANDROID =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index d0916c7..c0a4746 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -16,9 +16,6 @@
 import android.os.Bundle;
 import android.os.StrictMode;
 import android.support.annotation.IntDef;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.TrustedWebUtils;
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.CommandLine;
@@ -57,6 +54,10 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.UUID;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.TrustedWebUtils;
+
 /**
  * Dispatches incoming intents to the appropriate activity based on the current configuration and
  * Intent fired.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
index e24e9a9..70985ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
@@ -11,7 +11,6 @@
 import android.net.Uri;
 import android.provider.Browser;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ContextUtils;
@@ -41,6 +40,8 @@
 
 import java.util.List;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Tab Launcher to be used to launch new tabs from background Android Services,
  * when it is not known whether an activity is available. It will send an intent to launch the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java
index c1e0f06..57ccd40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionDataProvider.java
@@ -9,12 +9,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
 
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.util.IntentUtils;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * A model class that parses intent from third-party apps for data related with various browser
  * services related Intent types.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
index 505d60f..0abfec2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
@@ -5,9 +5,6 @@
 package org.chromium.chrome.browser.browserservices;
 
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.TrustedWebUtils;
 import android.support.v7.app.AppCompatActivity;
 
 import org.chromium.base.Log;
@@ -18,6 +15,10 @@
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.TrustedWebUtils;
+
 /**
  * Launched by {@link android.support.customtabs.TrustedWebUtils#launchBrowserSiteSettings}.
  * Verifies that url provided in intent has valid Digital Asset Link with the calling application,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
index 741695f..460629d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
@@ -11,8 +11,6 @@
 import android.os.SystemClock;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsService.Relation;
 import android.text.TextUtils;
 
 import org.chromium.base.CommandLine;
@@ -48,6 +46,8 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsService.Relation;
 import dagger.Reusable;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
index e860b0a..5027891 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java
@@ -5,9 +5,6 @@
 package org.chromium.chrome.browser.browserservices;
 
 import android.net.Uri;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageBackend;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
@@ -21,6 +18,10 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.PostMessageBackend;
+
 /**
  * A class that handles postMessage communications with a designated {@link CustomTabsSessionToken}.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
index d819ca9..7bffd3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionDataHolder.java
@@ -10,7 +10,6 @@
 import android.net.Uri;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.util.SparseArray;
 
 import org.chromium.base.Callback;
@@ -19,6 +18,8 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 import dagger.Lazy;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionHandler.java
index fcc8cc95..6745237 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/SessionHandler.java
@@ -10,9 +10,10 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.widget.RemoteViews;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Interface to handle browser services calls whenever the session id matched.
  * TODO(yusufo): Add a way to handle mayLaunchUrl as well.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
index 7e88948..3f04db4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -17,9 +17,6 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.support.annotation.Nullable;
-import android.support.customtabs.trusted.TrustedWebActivityService;
-import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager;
-import android.support.customtabs.trusted.TrustedWebActivityServiceWrapper;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
@@ -37,6 +34,10 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import androidx.browser.trusted.TrustedWebActivityService;
+import androidx.browser.trusted.TrustedWebActivityServiceConnectionManager;
+import androidx.browser.trusted.TrustedWebActivityServiceWrapper;
+
 /**
  * Uses a Trusted Web Activity client to display notifications.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
index ae8dfae..3b0db84 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityVerifier.java
@@ -8,7 +8,6 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsService;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ObserverList;
@@ -41,6 +40,7 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsService;
 import dagger.Lazy;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashImageHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashImageHolder.java
index 82da66ea..d774c520 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashImageHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/SplashImageHolder.java
@@ -6,7 +6,6 @@
 
 import android.graphics.Bitmap;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.util.ArrayMap;
 
 import java.util.Collections;
@@ -15,6 +14,8 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Stores the splash images received from TWA clients between the call to
  * {@link android.support.customtabs.CustomTabsService#receiveFile} and a Trusted Web Activity
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java
index 3472d63..3847f8b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java
@@ -13,8 +13,6 @@
 import android.graphics.Matrix;
 import android.os.Build;
 import android.os.Bundle;
-import android.support.customtabs.TrustedWebUtils;
-import android.support.customtabs.TrustedWebUtils.SplashScreenParamKey;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
@@ -34,6 +32,9 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.TrustedWebUtils;
+import androidx.browser.customtabs.TrustedWebUtils.SplashScreenParamKey;
+
 /**
  * Orchestrates the flow of showing and removing splash screens for apps based on Trusted Web
  * Activities.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
index 6b57a5f..630833556 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -15,11 +15,6 @@
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsService.Relation;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageServiceConnection;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.SparseBooleanArray;
@@ -50,6 +45,12 @@
 import java.util.Map;
 import java.util.Set;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsService.Relation;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.PostMessageServiceConnection;
+
 /** Manages the clients' state for Custom Tabs. This class is threadsafe. */
 class ClientManager {
     // Values for the "CustomTabs.MayLaunchUrlType" UMA histogram. Append-only.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
index 8970624..1362ef9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
@@ -13,7 +13,6 @@
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
 import android.text.TextUtils;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -35,6 +34,8 @@
 import java.util.List;
 import java.util.Set;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Container for all parameters related to creating a customizable button.
  */
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 f3ac4ff9..4cbb26c 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
@@ -4,11 +4,11 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
-
 import static org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason.USER_NAVIGATION;
 
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
+
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -24,9 +24,6 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.KeyEvent;
@@ -55,10 +52,12 @@
 import org.chromium.chrome.browser.browserservices.OriginVerifier;
 import org.chromium.chrome.browser.browserservices.SessionDataHolder;
 import org.chromium.chrome.browser.browserservices.SessionHandler;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler.IntentIgnoringCriterion;
 import org.chromium.chrome.browser.customtabs.content.TabCreationMode;
 import org.chromium.chrome.browser.customtabs.dependency_injection.CustomTabActivityComponent;
 import org.chromium.chrome.browser.customtabs.dependency_injection.CustomTabActivityModule;
@@ -71,7 +70,6 @@
 import org.chromium.chrome.browser.incognito.IncognitoTabHost;
 import org.chromium.chrome.browser.incognito.IncognitoTabHostRegistry;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
-import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.page_info.PageInfoController;
 import org.chromium.chrome.browser.tab.Tab;
@@ -89,6 +87,10 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * The activity for custom tabs. It will be launched on top of a client's task.
  */
@@ -118,6 +120,7 @@
     private CustomTabStatusBarColorProvider mCustomTabStatusBarColorProvider;
     private CustomTabToolbarCoordinator mToolbarCoordinator;
     private SessionDataHolder mSessionDataHolder;
+    private CustomTabIntentHandler mCustomTabIntentHandler;
 
     // This is to give the right package name while using the client's resources during an
     // overridePendingTransition call.
@@ -363,19 +366,9 @@
 
             @Override
             public boolean handleIntent(Intent intent) {
-                if (mIntentHandler.shouldIgnoreIntent(intent)) {
-                    Log.w(TAG, "Incoming intent to Custom Tab was ignored.");
-                    return false;
-                }
-                String url = IntentHandler.getUrlFromIntent(intent);
-                if (TextUtils.isEmpty(url)) return false;
-                LoadUrlParams params = new LoadUrlParams(url);
-
-                params.setUrl(DataReductionProxySettings.getInstance()
-                        .maybeRewriteWebliteUrl(params.getUrl()));
-                mNavigationController.navigate(params,
-                        IntentHandler.getTimestampFromIntent(intent));
-                return true;
+                // This method exists only for legacy reasons, see LaunchIntentDispatcher#
+                // clearTopIntentsForCustomTabsEnabled.
+                return handleNewIntent(intent);
             }
 
             @Override
@@ -415,17 +408,16 @@
         // Currently we can't handle arbitrary updates of intent parameters, so make sure
         // getIntent() returns the same intent as before.
         setIntent(originalIntent);
+
+        handleNewIntent(intent);
     }
 
-    @Override
-    public void onNewIntentWithNative(Intent intent) {
-        super.onNewIntentWithNative(intent);
-        mSessionDataHolder.setActiveHandler(mSessionHandler);
-        if (!mSessionDataHolder.handleIntent(intent)) {
-            int flagsToRemove = Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP;
-            intent.setFlags(intent.getFlags() & ~flagsToRemove);
-            startActivity(intent);
-        }
+    private boolean handleNewIntent(Intent intent) {
+        // Color scheme doesn't matter here: currently we don't support updating UI using Intents.
+        CustomTabIntentDataProvider dataProvider = new CustomTabIntentDataProvider(intent, this,
+                CustomTabsIntent.COLOR_SCHEME_LIGHT);
+
+        return mCustomTabIntentHandler.onNewIntent(dataProvider);
     }
 
     private void resetPostMessageHandlersForCurrentSession() {
@@ -768,8 +760,13 @@
     @Override
     protected CustomTabActivityComponent createComponent(
             ChromeActivityCommonsModule commonsModule) {
+        // mIntentHandler comes from the base class.
+        IntentIgnoringCriterion intentIgnoringCriterion =
+                (intent) -> mIntentHandler.shouldIgnoreIntent(intent);
+
         CustomTabActivityModule customTabsModule =
-                new CustomTabActivityModule(mIntentDataProvider, mNightModeStateController);
+                new CustomTabActivityModule(mIntentDataProvider, mNightModeStateController,
+                        intentIgnoringCriterion);
         CustomTabActivityComponent component =
                 ChromeApplication.getComponent().createCustomTabActivityComponent(
                         commonsModule, customTabsModule);
@@ -785,7 +782,7 @@
             if (reason == USER_NAVIGATION) recordClientConnectionStatus();
             handleFinishAndClose();
         });
-        component.resolveInitialPageLoader();
+        mCustomTabIntentHandler = component.resolveIntentHandler();
         mSessionDataHolder = component.getParent().resolveSessionDataHolder();
 
         if (mIntentDataProvider.isTrustedWebActivity()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
index a280b952..7d532c91 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -9,7 +9,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnLayoutChangeListener;
@@ -37,6 +36,8 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Delegate that manages bottom bar area inside of {@link CustomTabActivity}.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index f9c287b3..cb865b5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -4,8 +4,8 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_SYSTEM;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_SYSTEM;
 
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
@@ -21,10 +21,6 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabColorSchemeParams;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.TrustedWebUtils;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.view.View;
@@ -56,6 +52,11 @@
 import java.util.List;
 import java.util.regex.Pattern;
 
+import androidx.browser.customtabs.CustomTabColorSchemeParams;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.TrustedWebUtils;
+
 /**
  * A model class that parses the incoming intent for Custom Tabs specific customization data.
  *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java
index b4e249a8..e564da8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java
@@ -4,9 +4,6 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsSessionToken;
-
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -16,6 +13,9 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * An observer for firing navigation events on {@link CustomTabsCallback}.
  */
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 7e97613..f7e9540c 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
@@ -6,7 +6,6 @@
 
 import android.content.Intent;
 import android.support.annotation.NonNull;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.v7.app.AppCompatDelegate;
 
 import org.chromium.base.ObserverList;
@@ -18,6 +17,8 @@
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Maintains and provides the night mode state for {@link CustomTabActivity}.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
index a8224ac..0c25cc3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -11,7 +11,6 @@
 import android.net.Uri;
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 
@@ -34,6 +33,8 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * A {@link TabObserver} that also handles custom tabs specific logging and messaging.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
index c22ff34c..dacb04b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java
@@ -11,8 +11,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.WorkerThread;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.FileUtils;
 import org.chromium.base.Log;
@@ -22,6 +20,8 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
 import dagger.Lazy;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 2c602ec..ae1c4ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -19,11 +19,6 @@
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageServiceConnection;
 import android.text.TextUtils;
 import android.widget.RemoteViews;
 
@@ -89,6 +84,12 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.PostMessageServiceConnection;
+
 /**
  * Implementation of the ICustomTabsService interface.
  *
@@ -344,7 +345,11 @@
                         .onSessionDisconnected(session);
             }
         };
-        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(session);
+
+        // TODO(peconn): Make this not an anonymous class once PostMessageServiceConnection is made
+        // non-abstract in AndroidX.
+        PostMessageServiceConnection serviceConnection =
+                new PostMessageServiceConnection(session) {};
         PostMessageHandler handler = new PostMessageHandler(serviceConnection);
         return mClientManager.newSession(
                 session, Binder.getCallingUid(), onDisconnect, handler, serviceConnection);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
index 028c4ba..bfba782e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java
@@ -10,8 +10,6 @@
 import android.os.IBinder;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.browser.browserservices.Origin;
@@ -20,6 +18,9 @@
 
 import java.util.List;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Custom tabs connection service, used by the embedded Chrome activities.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
index fb75a3fa..730e0cfac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
@@ -9,7 +9,6 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 
 import org.chromium.base.ContextUtils;
@@ -28,6 +27,8 @@
 import org.chromium.network.mojom.ReferrerPolicy;
 import org.chromium.ui.base.WindowAndroid;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Holds a hidden tab which may be used to preload pages before a CustomTabActivity is launched.
  *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
index 8fa4dee..1301ff5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
@@ -5,13 +5,14 @@
 package org.chromium.chrome.browser.customtabs;
 
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsSessionToken;
 
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.WebContents;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Notifies the provided {@link CustomTabsConnection} of page load metrics, such as time until first
  * contentful paint.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityInitialPageLoader.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityInitialPageLoader.java
deleted file mode 100644
index ad137d6..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityInitialPageLoader.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.customtabs.content;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
-import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
-import org.chromium.chrome.browser.customtabs.CustomTabObserver;
-import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.util.UrlUtilities;
-import org.chromium.content_public.browser.LoadUrlParams;
-
-import javax.inject.Inject;
-
-import dagger.Lazy;
-
-/**
- * Loads the url received in the Intent as soon as the initial tab is created.
- *
- * Lifecycle: should be created once on Activity creation. When finishes its work, detaches
- * observers, and should get gc-ed. Consider adding @ActivityScope if this policy changes.
- */
-public class CustomTabActivityInitialPageLoader {
-    private final CustomTabActivityTabProvider mTabProvider;
-    private final CustomTabIntentDataProvider mIntentDataProvider;
-    private final Lazy<CustomTabObserver> mCustomTabObserver;
-    private final CustomTabNavigationEventObserver mNavigationEventObserver;
-    private final CustomTabActivityNavigationController mNavigationController;
-
-    @Nullable
-    private final String mSpeculatedUrl;
-
-    @Inject
-    public CustomTabActivityInitialPageLoader(CustomTabActivityTabProvider tabProvider,
-            CustomTabIntentDataProvider intentDataProvider, CustomTabsConnection connection,
-            Lazy<CustomTabObserver> customTabObserver,
-            CustomTabNavigationEventObserver navigationEventObserver,
-            CustomTabActivityNavigationController navigationController) {
-        mTabProvider = tabProvider;
-        mIntentDataProvider = intentDataProvider;
-        mCustomTabObserver = customTabObserver;
-        mNavigationEventObserver = navigationEventObserver;
-        mNavigationController = navigationController;
-        mSpeculatedUrl = connection.getSpeculatedUrl(mIntentDataProvider.getSession());
-
-        mTabProvider.addObserver(new CustomTabActivityTabProvider.Observer() {
-            @Override
-            public void onInitialTabCreated(@NonNull Tab tab, @TabCreationMode int mode) {
-                loadInitialUrlIfNecessary(tab, mode);
-                mTabProvider.removeObserver(this);
-            }
-        });
-    }
-
-    private void loadInitialUrlIfNecessary(@NonNull Tab tab, @TabCreationMode int mode) {
-        if (mode == TabCreationMode.RESTORED) return;
-
-        if (mode == TabCreationMode.HIDDEN) {
-            handleInitialLoadForHiddedTab(tab);
-            return;
-        }
-
-        LoadUrlParams params = new LoadUrlParams(mIntentDataProvider.getUrlToLoad());
-
-        navigate(params);
-    }
-
-    // The hidden tab case needs a bit of special treatment.
-    private void handleInitialLoadForHiddedTab(Tab tab) {
-        String url = mIntentDataProvider.getUrlToLoad();
-
-        // Manually generating metrics in case the hidden tab has completely finished loading.
-        if (!tab.isLoading() && !tab.isShowingErrorPage()) {
-            mCustomTabObserver.get().onPageLoadStarted(tab, url);
-            mCustomTabObserver.get().onPageLoadFinished(tab, url);
-            mNavigationEventObserver.onPageLoadStarted(tab, url);
-            mNavigationEventObserver.onPageLoadFinished(tab, url);
-        }
-
-        // No actual load to do if the hidden tab already has the exact correct url.
-        if (TextUtils.equals(mSpeculatedUrl, url)) {
-            return;
-        }
-
-        LoadUrlParams params = new LoadUrlParams(url);
-
-        // The following block is a hack that deals with urls preloaded with
-        // the wrong fragment. Does an extra pageload and replaces history.
-        if (mSpeculatedUrl != null
-                && UrlUtilities.urlsFragmentsDiffer(mSpeculatedUrl, url)) {
-            params.setShouldReplaceCurrentEntry(true);
-        }
-
-        navigate(params);
-    }
-
-    private void navigate(LoadUrlParams params) {
-        mNavigationController.navigate(params,
-                IntentHandler.getTimestampFromIntent(mIntentDataProvider.getIntent()));
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
index ba5aa02..477747d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -10,7 +10,6 @@
 import android.provider.Browser;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 import android.view.Window;
 
@@ -56,6 +55,7 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
 import dagger.Lazy;
 
 /**
@@ -132,6 +132,9 @@
         mSession = mIntentDataProvider.getSession();
         mIntent = mIntentDataProvider.getIntent();
 
+        // Save speculated url, because it will be erased later with mConnection.takeHiddenTab().
+        mTabProvider.setSpeculatedUrl(mConnection.getSpeculatedUrl(mSession));
+
         lifecycleDispatcher.register(this);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java
index 76049ed8..5208d534 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java
@@ -32,6 +32,8 @@
     private Tab mTab;
     @TabCreationMode
     private int mTabCreationMode = TabCreationMode.NONE;
+    @Nullable
+    private String mSpeculatedUrl;
 
     @Inject
     CustomTabActivityTabProvider() {}
@@ -71,16 +73,31 @@
         return mTabCreationMode;
     }
 
+    /**
+     * Returns speculated url, if there was one.
+     */
+    @Nullable
+    public String getSpeculatedUrl() {
+        return mSpeculatedUrl;
+    }
+
     void setInitialTab(@NonNull Tab tab, @TabCreationMode int creationMode) {
         assert mTab == null;
         assert creationMode != TabCreationMode.NONE;
         mTab = tab;
         mTabCreationMode = creationMode;
+        if (creationMode != TabCreationMode.HIDDEN) {
+            mSpeculatedUrl = null;
+        }
         for (Observer observer : mObservers) {
             observer.onInitialTabCreated(tab, creationMode);
         }
     }
 
+    void setSpeculatedUrl(@Nullable String url) {
+        mSpeculatedUrl = url;
+    }
+
     void removeTab() {
         if (mTab == null) return;
         mTab = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandler.java
new file mode 100644
index 0000000..56842ab
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandler.java
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs.content;
+
+import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.ACTIVITY_CONTEXT;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.tab.Tab;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
+/**
+ * Handles the incoming intents: the one that starts the activity, as well as subsequent intents
+ * received in onNewIntent.
+ */
+@ActivityScope
+public class CustomTabIntentHandler {
+    private final CustomTabActivityTabProvider mTabProvider;
+    private final CustomTabIntentDataProvider mIntentDataProvider;
+    private final CustomTabIntentHandlingStrategy mHandlingStrategy;
+    private final IntentIgnoringCriterion mIntentIgnoringCriterion;
+    private final Context mContext;
+    @Nullable
+    private Runnable mOnTabCreatedRunnable;
+
+    @Inject
+    public CustomTabIntentHandler(CustomTabActivityTabProvider tabProvider,
+            CustomTabIntentDataProvider intentDataProvider,
+            CustomTabIntentHandlingStrategy handlingStrategy,
+            IntentIgnoringCriterion intentIgnoringCriterion,
+            @Named(ACTIVITY_CONTEXT) Context context) {
+        mTabProvider = tabProvider;
+        mIntentDataProvider = intentDataProvider;
+        mHandlingStrategy = handlingStrategy;
+        mIntentIgnoringCriterion = intentIgnoringCriterion;
+        mContext = context;
+
+        observeInitialTabCreationIfNecessary();
+        handleInitialIntent();
+    }
+
+    private void observeInitialTabCreationIfNecessary() {
+        if (mTabProvider.getTab() != null) {
+            return;
+        }
+        // Note that only one observer and one Runnable exists: if multiple intents arrive before
+        // native init, we want to handle only the last one.
+        mTabProvider.addObserver(new CustomTabActivityTabProvider.Observer() {
+            @Override
+            public void onInitialTabCreated(@NonNull Tab tab, @TabCreationMode int mode) {
+                if (mOnTabCreatedRunnable != null) {
+                    mOnTabCreatedRunnable.run();
+                    mOnTabCreatedRunnable = null;
+                }
+                mTabProvider.removeObserver(this);
+            }
+        });
+    }
+
+    private void handleInitialIntent() {
+        runWhenTabCreated(() -> {
+            if (mTabProvider.getInitialTabCreationMode() != TabCreationMode.RESTORED) {
+                mHandlingStrategy.handleInitialIntent(mIntentDataProvider);
+            }
+        });
+    }
+
+    /**
+     * Called from Activity#onNewIntent.
+     *
+     * @param intentDataProvider Data provider built from the new intent. It's different from
+     * the injectable instance of {@link CustomTabIntentDataProvider} - that one is always built
+     * from the initial intent.
+     */
+    public boolean onNewIntent(CustomTabIntentDataProvider intentDataProvider) {
+        Intent intent = intentDataProvider.getIntent();
+        CustomTabsSessionToken session = intentDataProvider.getSession();
+        if (session == null || !session.equals(mIntentDataProvider.getSession())) {
+            assert false : "New intent delivered into a Custom Tab with a different session";
+            int flagsToRemove = Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP;
+            intent.setFlags((intent.getFlags() & ~flagsToRemove) | Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(intent);
+            return false;
+        }
+
+        if (mIntentIgnoringCriterion.shouldIgnoreIntent(intent)) {
+            return false;
+        }
+
+        runWhenTabCreated(() ->
+            mHandlingStrategy.handleNewIntent(intentDataProvider)
+        );
+
+        return true;
+    }
+
+    private void runWhenTabCreated(Runnable runnable) {
+        if (mTabProvider.getTab() != null) {
+            runnable.run();
+        } else {
+            mOnTabCreatedRunnable = runnable;
+        }
+    }
+
+    /**
+     * Represents Chrome-wide rules for ignoring Intents.
+     */
+    public interface IntentIgnoringCriterion {
+        /**
+         * Returns whether given intent should be ignored.
+         */
+        boolean shouldIgnoreIntent(Intent intent);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java
new file mode 100644
index 0000000..91665afe
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs.content;
+
+import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
+
+/**
+ * Strategy of handling incoming intents.
+ */
+public interface CustomTabIntentHandlingStrategy {
+
+    /**
+     * Called on start of activity after initialization routines (native init, creating tab)
+     * have finished.
+     *
+     * @param intentDataProvider Provides the parameters sent with the initial intent.
+     */
+    void handleInitialIntent(CustomTabIntentDataProvider intentDataProvider);
+
+    /**
+     * Called when a valid new intent is delivered to the running Custom Tab. Initialization
+     * routines are guaranteed to have been completed when this method is called.
+     *
+     * @param intentDataProvider Provides the parameters sent with the new intent.
+     */
+    void handleNewIntent(CustomTabIntentDataProvider intentDataProvider);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
new file mode 100644
index 0000000..09d2ced
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
@@ -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.
+
+package org.chromium.chrome.browser.customtabs.content;
+
+import android.text.TextUtils;
+
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
+import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver;
+import org.chromium.chrome.browser.customtabs.CustomTabObserver;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlUtilities;
+import org.chromium.content_public.browser.LoadUrlParams;
+
+import javax.inject.Inject;
+
+import dagger.Lazy;
+
+/**
+ * Default implementation of {@link CustomTabIntentHandlingStrategy}.
+ * Navigates the Custom Tab to urls provided in intents.
+ */
+@ActivityScope
+public class DefaultCustomTabIntentHandlingStrategy implements CustomTabIntentHandlingStrategy {
+    private final CustomTabActivityTabProvider mTabProvider;
+    private final CustomTabActivityNavigationController mNavigationController;
+    private final CustomTabNavigationEventObserver mNavigationEventObserver;
+    private final Lazy<CustomTabObserver> mCustomTabObserver;
+
+    @Inject
+    public DefaultCustomTabIntentHandlingStrategy(CustomTabActivityTabProvider tabProvider,
+            CustomTabActivityNavigationController navigationController,
+            CustomTabNavigationEventObserver navigationEventObserver,
+            Lazy<CustomTabObserver> customTabObserver) {
+        mTabProvider = tabProvider;
+        mNavigationController = navigationController;
+        mNavigationEventObserver = navigationEventObserver;
+        mCustomTabObserver = customTabObserver;
+    }
+
+    @Override
+    public void handleInitialIntent(CustomTabIntentDataProvider intentDataProvider) {
+        if (mTabProvider.getInitialTabCreationMode() == TabCreationMode.HIDDEN) {
+            handleInitialLoadForHiddedTab(intentDataProvider);
+        } else {
+            LoadUrlParams params = new LoadUrlParams(intentDataProvider.getUrlToLoad());
+            mNavigationController.navigate(params, getTimestamp(intentDataProvider));
+        }
+    }
+
+    // The hidden tab case needs a bit of special treatment.
+    private void handleInitialLoadForHiddedTab(CustomTabIntentDataProvider intentDataProvider) {
+        Tab tab = mTabProvider.getTab();
+        if (tab == null) {
+            throw new IllegalStateException("handleInitialIntent called before Tab created");
+        }
+        String url = intentDataProvider.getUrlToLoad();
+
+        // Manually generating metrics in case the hidden tab has completely finished loading.
+        if (!tab.isLoading() && !tab.isShowingErrorPage()) {
+            mCustomTabObserver.get().onPageLoadStarted(tab, url);
+            mCustomTabObserver.get().onPageLoadFinished(tab, url);
+            mNavigationEventObserver.onPageLoadStarted(tab, url);
+            mNavigationEventObserver.onPageLoadFinished(tab, url);
+        }
+
+        // No actual load to do if the hidden tab already has the exact correct url.
+        String speculatedUrl = mTabProvider.getSpeculatedUrl();
+        if (TextUtils.equals(speculatedUrl, url)) {
+            return;
+        }
+
+        LoadUrlParams params = new LoadUrlParams(url);
+
+        // The following block is a hack that deals with urls preloaded with
+        // the wrong fragment. Does an extra pageload and replaces history.
+        if (speculatedUrl != null
+                && UrlUtilities.urlsFragmentsDiffer(speculatedUrl, url)) {
+            params.setShouldReplaceCurrentEntry(true);
+        }
+
+        mNavigationController.navigate(params, getTimestamp(intentDataProvider));
+    }
+
+    @Override
+    public void handleNewIntent(CustomTabIntentDataProvider intentDataProvider) {
+        String url = intentDataProvider.getUrlToLoad();
+        if (TextUtils.isEmpty(url)) return;
+        LoadUrlParams params = new LoadUrlParams(url);
+        mNavigationController.navigate(params, getTimestamp(intentDataProvider));
+    }
+
+    private long getTimestamp(CustomTabIntentDataProvider intentDataProvider) {
+        return IntentHandler.getTimestampFromIntent(intentDataProvider.getIntent());
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
index 51f93240..59097f3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
@@ -9,7 +9,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabStatusBarColorProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy;
-import org.chromium.chrome.browser.customtabs.content.CustomTabActivityInitialPageLoader;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
@@ -38,7 +38,7 @@
     CustomTabActivityTabController resolveTabController();
     CustomTabActivityTabFactory resolveTabFactory();
     CustomTabActivityLifecycleUmaTracker resolveUmaTracker();
-    CustomTabActivityInitialPageLoader resolveInitialPageLoader();
+    CustomTabIntentHandler resolveIntentHandler();
     CustomTabActivityNavigationController resolveNavigationController();
     CustomTabActivityTabProvider resolveTabProvider();
     CustomTabStatusBarColorProvider resolveCustomTabStatusBarColorProvider();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java
index 2cb0572..098ac496 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java
@@ -7,6 +7,9 @@
 import org.chromium.chrome.browser.browserservices.ClientAppDataRegister;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabNightModeStateController;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler.IntentIgnoringCriterion;
+import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandlingStrategy;
+import org.chromium.chrome.browser.customtabs.content.DefaultCustomTabIntentHandlingStrategy;
 
 import dagger.Module;
 import dagger.Provides;
@@ -18,11 +21,14 @@
 public class CustomTabActivityModule {
     private final CustomTabIntentDataProvider mIntentDataProvider;
     private final CustomTabNightModeStateController mNightModeController;
+    private final IntentIgnoringCriterion mIntentIgnoringCriterion;
 
     public CustomTabActivityModule(CustomTabIntentDataProvider intentDataProvider,
-            CustomTabNightModeStateController nightModeController) {
+            CustomTabNightModeStateController nightModeController,
+            IntentIgnoringCriterion intentIgnoringCriterion) {
         mIntentDataProvider = intentDataProvider;
         mNightModeController = nightModeController;
+        mIntentIgnoringCriterion = intentIgnoringCriterion;
     }
 
     @Provides
@@ -39,4 +45,15 @@
     public CustomTabNightModeStateController provideNightModeController() {
         return mNightModeController;
     }
+
+    @Provides
+    public CustomTabIntentHandlingStrategy provideIntentHandler(
+            DefaultCustomTabIntentHandlingStrategy defaultHandler) {
+        return defaultHandler;
+    }
+
+    @Provides
+    public IntentIgnoringCriterion provideIntentIgnoringCriterion() {
+        return mIntentIgnoringCriterion;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java
index 4a3be88..435fec3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java
@@ -6,7 +6,8 @@
 
 import android.content.Context;
 import android.os.Bundle;
-import android.support.customtabs.PostMessageBackend;
+
+import androidx.browser.customtabs.PostMessageBackend;
 
 /**
  * A {@link PostMessageBackend} which delegates incoming notifications to the {@link
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
index dd0cf78..f4b2453d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -11,8 +11,6 @@
 import android.net.Uri;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.PostMessageBackend;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
@@ -55,6 +53,8 @@
 
 import javax.inject.Inject;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.PostMessageBackend;
 import dagger.Lazy;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java
index ecaf288..aa07693b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java
@@ -4,17 +4,16 @@
 
 package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
-import static android.support.customtabs.CustomTabsCallback.NAVIGATION_FAILED;
-import static android.support.customtabs.CustomTabsCallback.NAVIGATION_FINISHED;
-import static android.support.customtabs.CustomTabsCallback.NAVIGATION_STARTED;
-import static android.support.customtabs.CustomTabsCallback.TAB_HIDDEN;
-import static android.support.customtabs.CustomTabsCallback.TAB_SHOWN;
+import static androidx.browser.customtabs.CustomTabsCallback.NAVIGATION_FAILED;
+import static androidx.browser.customtabs.CustomTabsCallback.NAVIGATION_FINISHED;
+import static androidx.browser.customtabs.CustomTabsCallback.NAVIGATION_STARTED;
+import static androidx.browser.customtabs.CustomTabsCallback.TAB_HIDDEN;
+import static androidx.browser.customtabs.CustomTabsCallback.TAB_SHOWN;
 
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsCallback;
 import android.text.TextUtils;
 
 import org.chromium.base.VisibleForTesting;
@@ -28,6 +27,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+
 /**
  * An observer for firing navigation events to the CCT dynamic module.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
index deb2a5e..eb98eff9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
@@ -7,7 +7,6 @@
 import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.APP_CONTEXT;
 
 import android.content.Context;
-import android.support.customtabs.CustomTabsIntent;
 import android.text.TextUtils;
 import android.view.View;
 
@@ -39,6 +38,7 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import androidx.browser.customtabs.CustomTabsIntent;
 import dagger.Lazy;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java
index 76cf447f..3cd42a5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java
@@ -8,7 +8,6 @@
 import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.LAST_USED_PROFILE;
 
 import android.content.Context;
-import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.browser.WarmupManager;
@@ -23,6 +22,7 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import androidx.browser.trusted.TrustedWebActivityServiceConnectionManager;
 import dagger.Module;
 import dagger.Provides;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
index 66a1d84..75e9ecb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -8,7 +8,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.support.annotation.NonNull;
-import android.support.customtabs.CustomTabsIntent;
 import android.text.TextUtils;
 
 import org.chromium.base.CommandLine;
@@ -44,6 +43,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Manages UI effects for reader mode including hiding and showing the
  * reader mode and reader mode preferences toolbar icon and hiding the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java
index 1a7c05a..dae6e65a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java
@@ -17,7 +17,6 @@
 import android.net.Uri;
 import android.os.Build;
 import android.provider.Browser;
-import android.support.customtabs.CustomTabsIntent;
 import android.text.TextUtils;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -33,6 +32,8 @@
 
 import java.util.Locale;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * A class containing some utility static methods.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
index 824c255..0c8c0245 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
@@ -10,7 +10,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Browser;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ContextUtils;
@@ -41,6 +40,8 @@
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.widget.Toast;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Serves as an interface between Download Home UI and offline page related items that are to be
  * displayed in the downloads UI.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncPreferenceUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncPreferenceUtils.java
index bc320d8e..361d772 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncPreferenceUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncPreferenceUtils.java
@@ -11,7 +11,6 @@
 import android.net.Uri;
 import android.provider.Browser;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceFragmentCompat;
 
@@ -30,6 +29,8 @@
 import org.chromium.components.sync.StopSource;
 import org.chromium.ui.UiUtils;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Helper methods for sync preferences.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
index 6692173..b714c536 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -13,7 +13,6 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.v4.app.DialogFragment;
 import android.support.v4.app.Fragment;
 import android.support.v7.app.AlertDialog;
@@ -43,6 +42,8 @@
 import org.chromium.ui.text.SpanApplier;
 import org.chromium.ui.text.SpanApplier.SpanInfo;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Dialog to ask to user to enter their sync passphrase.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
index 3f337695..2f26f0f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
@@ -10,7 +10,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.v4.app.DialogFragment;
 import android.support.v7.app.AlertDialog;
 import android.text.SpannableString;
@@ -39,6 +38,8 @@
 import java.util.Date;
 import java.util.List;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Dialog to ask the user select what type of password to use for encryption.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
index 63a844a..bee31fac 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
@@ -11,7 +11,6 @@
 import android.net.Uri;
 import android.provider.Browser;
 import android.provider.ContactsContract;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.metrics.RecordUserAction;
@@ -37,6 +36,8 @@
 import java.net.URI;
 import java.util.Locale;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * A default {@link ContextMenuItemDelegate} that supports the context menu functionality in Tab.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
index 49cda5b..d327fd70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -10,7 +10,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.net.Uri;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.text.TextUtils;
 
 import org.chromium.base.ContextUtils;
@@ -23,6 +22,8 @@
 import org.chromium.content_public.common.ScreenOrientationValues;
 import org.chromium.webapk.lib.common.splash.SplashLayout;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Stores info about a web app.
  */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java
index be2e6e2..b1e0f83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappTabDelegate.java
@@ -9,7 +9,6 @@
 import android.net.Uri;
 import android.os.StrictMode;
 import android.provider.Browser;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -27,6 +26,8 @@
 import java.net.URISyntaxException;
 import java.util.List;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Asynchronously creates Tabs for navigation originating from an installed PWA.
  *
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
index 310017d..02e5753e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.browserservices;
 
 import android.net.Uri;
-import android.support.customtabs.CustomTabsService;
 import android.support.test.filters.SmallTest;
 
 import org.junit.Assert;
@@ -37,6 +36,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsService;
+
 /** Tests for OriginVerifier. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
index 00364e5..ccf87f7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -13,7 +13,6 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.ServiceTestRule;
@@ -38,6 +37,8 @@
 
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.trusted.TrustedWebActivityServiceConnectionManager;
+
 /**
  * Tests the TrustedWebActivityClient.
  *
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
index 3ee1926..c719db2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
@@ -8,9 +8,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Intent;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.TrustedWebUtils;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 
@@ -37,6 +34,10 @@
 
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.TrustedWebUtils;
+
 /**
  * Instrumentation tests for launching
  * {@link org.chromium.chrome.browser.customtabs.CustomTabActivity} in Trusted Web Activity Mode.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
index df2f619..b9fc507 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/ClientManagerTest.java
@@ -7,9 +7,6 @@
 import android.content.Context;
 import android.net.Uri;
 import android.os.Process;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageServiceConnection;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -32,6 +29,10 @@
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+import androidx.browser.customtabs.PostMessageServiceConnection;
+
 /** Tests for ClientManager. */
 @RunWith(BaseJUnit4ClassRunner.class)
 public class ClientManagerTest {
@@ -173,7 +174,10 @@
     @SmallTest
     public void testPostMessageOriginVerification() {
         final ClientManager cm = mClientManager;
-        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        // TODO(peconn): Get rid of this anonymous class once PostMessageServiceConnection is made
+        // non-abstract. Same with the other occurrences below.
+        PostMessageServiceConnection serviceConnection =
+                new PostMessageServiceConnection(mSession) {};
         Assert.assertTrue(cm.newSession(mSession, mUid, null,
                 new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
@@ -216,7 +220,8 @@
     @SmallTest
     public void testPostMessageOriginDifferentRelations() {
         final ClientManager cm = mClientManager;
-        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        PostMessageServiceConnection serviceConnection =
+                new PostMessageServiceConnection(mSession) {};
         Assert.assertTrue(cm.newSession(mSession, mUid, null,
                 new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
@@ -255,7 +260,8 @@
     @SmallTest
     public void testPostMessageOriginHttpNotAllowed() {
         final ClientManager cm = mClientManager;
-        PostMessageServiceConnection serviceConnection = new PostMessageServiceConnection(mSession);
+        PostMessageServiceConnection serviceConnection =
+                new PostMessageServiceConnection(mSession) {};
         Assert.assertTrue(cm.newSession(mSession, mUid, null,
                 new PostMessageHandler(serviceConnection), serviceConnection));
         // Should always start with no origin.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
index cf1768ac..5b5b132 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
@@ -6,7 +6,6 @@
 
 import android.content.Intent;
 import android.graphics.Color;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.view.MenuItem;
@@ -32,6 +31,8 @@
 
 import java.util.concurrent.ExecutionException;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Instrumentation tests for {@link CustomTabActivity} launched in incognito mode.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 2dd5efa..6761dd7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -34,11 +34,6 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.annotation.DrawableRes;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSession;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
@@ -143,6 +138,12 @@
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSession;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Instrumentation tests for app menu, context menu, and toolbar of a {@link CustomTabActivity}.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
index e63f864..ec03c34 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -13,12 +13,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Process;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsClient;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsServiceConnection;
-import android.support.customtabs.CustomTabsSession;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -51,6 +45,13 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsClient;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsServiceConnection;
+import androidx.browser.customtabs.CustomTabsSession;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /** Tests for CustomTabsConnection. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class CustomTabsConnectionTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
index 2c9929c..86e2116e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -10,12 +10,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Process;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsClient;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsServiceConnection;
-import android.support.customtabs.CustomTabsSession;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
 
 import org.junit.Assert;
@@ -31,6 +25,13 @@
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsClient;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsServiceConnection;
+import androidx.browser.customtabs.CustomTabsSession;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Utility class that contains convenience calls related with custom tabs testing.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
index 0945878..6734ed1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
@@ -9,11 +9,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.CustomTabsSession;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -53,6 +48,12 @@
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.CustomTabsSession;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /** Tests for detached resource requests. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class DetachedResourceRequestTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java
index a031eaa5..47545e7c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java
@@ -12,8 +12,6 @@
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.util.Pair;
@@ -69,6 +67,9 @@
 import java.util.Locale;
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * Instrumentation tests for showing the publisher URL for a trusted CDN.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
index 6fb583bb..12963bdf5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
 import android.content.Intent;
-import android.support.customtabs.CustomTabsCallback;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 
@@ -48,6 +47,8 @@
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+
 /**
  * Instrumentation tests for the CustomTabsDynamicModuleNavigationObserver.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
index f8e36c76..d9443ba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
@@ -12,8 +12,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsService;
-import android.support.customtabs.PostMessageBackend;
 import android.support.test.filters.SmallTest;
 
 import org.junit.After;
@@ -41,6 +39,9 @@
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.net.test.util.TestWebServer;
 
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.browser.customtabs.PostMessageBackend;
+
 /**
  * Instrumentation tests for the CCT Dynamic Module post message API.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
index ff4bca4..f791d70 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
@@ -20,7 +20,6 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.annotation.Nullable;
-import android.support.customtabs.CustomTabsCallback;
 import android.support.test.InstrumentationRegistry;
 
 import org.junit.Assert;
@@ -36,6 +35,8 @@
 import java.io.InputStream;
 import java.util.concurrent.TimeoutException;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+
 /**
  * Utility class that contains fake CCT dynamic module classes and convenience calls
  * related with CCT dynamic module testing.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
index ab7b3b01..1961cdd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -16,7 +16,6 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.provider.Browser;
-import android.support.customtabs.CustomTabsIntent;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.test.mock.MockPackageManager;
@@ -52,6 +51,8 @@
 import java.util.List;
 import java.util.regex.Pattern;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Instrumentation tests for {@link ExternalNavigationHandler}.
  */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesPreferencesTest.java
index 65fb4c4..90c511c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesPreferencesTest.java
@@ -15,6 +15,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
@@ -119,6 +120,7 @@
     @Test
     @SmallTest
     @Feature({"Sync"})
+    @DisabledTest(message = "https://crbug.com/991135")
     public void testSyncSwitchClearsServerAutofillCreditCards() {
         mSyncTestRule.setUpTestAccountAndSignIn();
         mSyncTestRule.setPaymentsIntegrationEnabled(true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
index dce4a9d8..38d5d314 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestRule.java
@@ -8,7 +8,6 @@
 
 import android.content.Intent;
 import android.net.Uri;
-import android.support.customtabs.TrustedWebUtils;
 import android.support.test.InstrumentationRegistry;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,6 +28,8 @@
 import org.chromium.content_public.browser.test.util.JavaScriptUtils;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import androidx.browser.customtabs.TrustedWebUtils;
+
 /**
  * Custom {@link ChromeActivityTestRule} for tests using {@link WebappActivity}.
  */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/SessionDataHolderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/SessionDataHolderTest.java
index 2297878..7d18a33 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/SessionDataHolderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/SessionDataHolderTest.java
@@ -12,8 +12,6 @@
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.Intent;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsSessionToken;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -31,6 +29,9 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.customtabs.TranslucentCustomTabActivity;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /** Unit tests for {@link SessionDataHolder}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
index 3176221..dd1ee52 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -15,9 +15,6 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager;
-import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager.ExecutionCallback;
-import android.support.customtabs.trusted.TrustedWebActivityServiceWrapper;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -32,6 +29,10 @@
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 
+import androidx.browser.trusted.TrustedWebActivityServiceConnectionManager;
+import androidx.browser.trusted.TrustedWebActivityServiceConnectionManager.ExecutionCallback;
+import androidx.browser.trusted.TrustedWebActivityServiceWrapper;
+
 /**
  * Unit tests for {@link TrustedWebActivityClient}.
  */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
index 836d35c..13e33886 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
@@ -4,14 +4,12 @@
 
 package org.chromium.chrome.browser.customtabs;
 
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
-import static android.support.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
-
 import static org.junit.Assert.assertEquals;
 
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK;
+import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT;
+
 import android.content.Intent;
-import android.support.customtabs.CustomTabColorSchemeParams;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -20,6 +18,9 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 
+import androidx.browser.customtabs.CustomTabColorSchemeParams;
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /** Tests for {@link CustomTabIntentDataProvider}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
index 80c5aa5..4b3f827 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -13,7 +13,6 @@
 
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.customtabs.CustomTabsSessionToken;
 import android.view.View;
 
 import org.junit.rules.TestWatcher;
@@ -33,7 +32,6 @@
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
-import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.customtabs.CloseButtonNavigator;
 import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
@@ -56,6 +54,8 @@
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.WebContents;
 
+import androidx.browser.customtabs.CustomTabsSessionToken;
+
 /**
  * A TestRule that sets up the mocks and contains helper methods for JUnit/Robolectric tests scoped
  * to the content layer of Custom Tabs code.
@@ -71,7 +71,6 @@
     @Mock public ChromeActivity activity;
     @Mock public CustomTabsConnection connection;
     @Mock public CustomTabIntentDataProvider intentDataProvider;
-    @Mock public TabContentManager tabContentManager;
     @Mock public TabObserverRegistrar tabObserverRegistrar;
     @Mock public CompositorViewHolder compositorViewHolder;
     @Mock public WarmupManager warmupManager;
@@ -132,13 +131,10 @@
 
     public CustomTabActivityTabController createTabController() {
         return new CustomTabActivityTabController(activity,
-                ()
-                        -> customTabDelegateFactory,
-                connection, intentDataProvider, activityTabProvider, tabObserverRegistrar,
-                ()
-                        -> compositorViewHolder,
-                lifecycleDispatcher, warmupManager, tabPersistencePolicy, tabFactory,
-                () -> customTabObserver, webContentsFactory, navigationEventObserver, tabProvider);
+                () -> customTabDelegateFactory, connection, intentDataProvider, activityTabProvider,
+                tabObserverRegistrar, () -> compositorViewHolder, lifecycleDispatcher,
+                warmupManager, tabPersistencePolicy, tabFactory, () -> customTabObserver,
+                webContentsFactory, navigationEventObserver, tabProvider);
     }
 
     public CustomTabActivityNavigationController createNavigationController(
@@ -149,11 +145,13 @@
                 () -> fullscreenManager);
     }
 
-    public CustomTabActivityInitialPageLoader createInitialPageLoader(
+    public CustomTabIntentHandler createIntentHandler(
             CustomTabActivityNavigationController navigationController) {
-        return new CustomTabActivityInitialPageLoader(tabProvider,
-                intentDataProvider, connection, () -> customTabObserver,
-                navigationEventObserver, navigationController);
+        CustomTabIntentHandlingStrategy strategy = new DefaultCustomTabIntentHandlingStrategy(
+                tabProvider, navigationController, navigationEventObserver,
+                () -> customTabObserver);
+        return new CustomTabIntentHandler(tabProvider,
+                intentDataProvider, strategy, (intent) -> false, activity);
     }
 
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
index e2c5cc44..1baa4103 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -11,6 +11,7 @@
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -18,6 +19,8 @@
 import static org.chromium.chrome.browser.customtabs.content.CustomTabActivityContentTestEnvironment.OTHER_URL;
 import static org.chromium.chrome.browser.customtabs.content.CustomTabActivityContentTestEnvironment.SPECULATED_URL;
 
+import android.content.Intent;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -25,6 +28,7 @@
 import org.mockito.InOrder;
 import org.robolectric.annotation.Config;
 
+import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.test.ShadowUrlUtilities;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -44,13 +48,13 @@
 
     private CustomTabActivityTabController mTabController;
     private CustomTabActivityNavigationController mNavigationController;
-    private CustomTabActivityInitialPageLoader mInitialPageLoader;
+    private CustomTabIntentHandler mIntentHandler;
 
     @Before
     public void setUp() {
         mTabController = env.createTabController();
         mNavigationController = env.createNavigationController(mTabController);
-        mInitialPageLoader = env.createInitialPageLoader(mNavigationController);
+        mIntentHandler = env.createIntentHandler(mNavigationController);
     }
 
     @Test
@@ -127,4 +131,30 @@
         env.reachNativeInit(mTabController);
         verify(hiddenTab).loadUrl(any());
     }
+
+    @Test
+    public void loadsUrlFromNewIntent() {
+        env.reachNativeInit(mTabController);
+        clearInvocations(env.tabFromFactory);
+
+        mIntentHandler.onNewIntent(createDataProviderForNewIntent(OTHER_URL));
+        verify(env.tabFromFactory).loadUrl(argThat(params -> OTHER_URL.equals(params.getUrl())));
+    }
+
+    @Test
+    public void loadsUrlFromTheLastIntent_IfTwoIntentsArriveBeforeNativeInit() {
+        mIntentHandler.onNewIntent(createDataProviderForNewIntent(OTHER_URL));
+        env.reachNativeInit(mTabController);
+
+        verify(env.tabFromFactory, times(1)).loadUrl(any()); // Check that only one call was made.
+        verify(env.tabFromFactory).loadUrl(argThat(params -> OTHER_URL.equals(params.getUrl())));
+    }
+
+    private CustomTabIntentDataProvider createDataProviderForNewIntent(String url) {
+        CustomTabIntentDataProvider dataProvider = mock(CustomTabIntentDataProvider.class);
+        when(dataProvider.getUrlToLoad()).thenReturn(url);
+        when(dataProvider.getSession()).thenReturn(env.session);
+        when(dataProvider.getIntent()).thenReturn(new Intent().setAction(Intent.ACTION_VIEW));
+        return dataProvider;
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java
index e1317c0..d2806eb 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java
@@ -11,7 +11,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserManager;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -43,6 +42,8 @@
 import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
 import org.chromium.webapk.test.WebApkTestHelper;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /** JUnit tests for first run triggering code. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE,
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabDelegate.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabDelegate.java
index b26af1a..92a7084 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabDelegate.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessTabDelegate.java
@@ -6,7 +6,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Browser;
-import android.support.customtabs.CustomTabsIntent;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.browser.IntentHandler;
@@ -20,6 +19,8 @@
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.util.UrlUtilities;
 
+import androidx.browser.customtabs.CustomTabsIntent;
+
 /**
  * Asynchronously creates Tabs for navigation originating from {@link NoTouchActivity}.
  *
diff --git a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
index 9d1ae1b..7081d86c 100644
--- a/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
+++ b/chrome/android/touchless/javatests/src/org/chromium/chrome/browser/touchless/NoTouchActivityTest.java
@@ -17,16 +17,12 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.browser.ChromeInactivityTracker;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.MockSafeBrowsingApiHandler;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
 import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -149,31 +145,4 @@
                         -> alternateUrl.equals(
                                 mActivity.getActivityTab().getWebContents().getLastCommittedUrl()));
     }
-
-    /**
-     * Tests that Safe Browsing and interstitials work.
-     */
-    @Test
-    @DisabledTest(message = "crbug.com/947232")
-    public void testSafeBrowsing() throws Throwable {
-        mActivityTestRule.startMainActivityFromLauncher();
-        mActivity = mActivityTestRule.getActivity();
-
-        SafeBrowsingApiBridge.setSafeBrowsingHandlerType(
-                new MockSafeBrowsingApiHandler().getClass());
-        final String url = mTestServer.getURL(TEST_PATH);
-        MockSafeBrowsingApiHandler.addMockResponse(url, "{\"matches\":[{\"threat_type\":\"5\"}]}");
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> mActivity.getActivityTab().loadUrl(new LoadUrlParams(url)));
-        // TODO(carlosil): For now, we check the presence of an interstitial through the title since
-        // isShowingInterstitialPage does not work with committed interstitials. Once we fully
-        // migrate to committed interstitials, this should be changed to a more robust check.
-        CriteriaHelper.pollUiThread(
-                ()
-                        -> mActivity.getActivityTab().getWebContents().getTitle().equals(
-                                "Security error"),
-                "Failed to show Safe Browsing Interstitial page", 5000, 50);
-
-        MockSafeBrowsingApiHandler.clearMockResponses();
-    }
 }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 2786e5a..67d2e75 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1783,9 +1783,6 @@
   <message name="IDS_NETWORK_TYPE_METERED_WIFI" desc="Label for metered Wi-Fi networks (i.e., Wi-Fi networks which have resticted data usage such as a monthly limit).">
     metered Wi-Fi
   </message>
-  <message name="IDS_NETWORK_TYPE_WIMAX" desc="Label for WiMAX networks.">
-    WiMAX
-  </message>
   <message name="IDS_NETWORK_TYPE_BLUETOOTH" desc="Label for Bluetooth networks.">
     Bluetooth
   </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 86d9b7eb..c6d0fde0 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2392,9 +2392,6 @@
     <message name="IDS_SETTINGS_INTERNET_TOGGLE_WIFI_ACCESSIBILITY_LABEL" desc="Accessibility only label for WiFi enable/disable toggle .">
       Wi-Fi enable
     </message>
-    <message name="IDS_SETTINGS_INTERNET_TOGGLE_WIMAX_ACCESSIBILITY_LABEL" desc="Accessibility only label for WiMAX enable/disable toggle .">
-      WiMAX enable
-    </message>
   </if>
 
   <!-- Network error strings. -->
@@ -2671,9 +2668,6 @@
     <message name="IDS_ONC_WIFI_SSID" desc="ONC Property label for WiFi.SSID">
       SSID
     </message>
-    <message name="IDS_ONC_WIMAX_EAP_IDENTITY" desc="ONC Property label for WiMAX.EAP.Identity">
-      Identity
-    </message>
   </if>
 
   <!-- On Startup Page -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a7e3ea8b..eec412cc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1554,6 +1554,8 @@
     "sharing/features.h",
     "sharing/ping_message_handler.cc",
     "sharing/ping_message_handler.h",
+    "sharing/shared_clipboard/feature_flags.cc",
+    "sharing/shared_clipboard/feature_flags.h",
     "sharing/sharing_constants.cc",
     "sharing/sharing_constants.h",
     "sharing/sharing_device_info.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1f68539..5793ae2 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -37,6 +37,7 @@
 #include "chrome/browser/search/ntp_features.h"
 #include "chrome/browser/sharing/click_to_call/feature.h"
 #include "chrome/browser/sharing/features.h"
+#include "chrome/browser/sharing/shared_clipboard/feature_flags.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
 #include "chrome/browser/ui/ui_features.h"
@@ -1750,6 +1751,9 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(kAccountConsistencyFeature,
                                     kAccountConsistencyFeatureVariations,
                                     "AccountConsistencyVariations")},
+    {"force-dice-migration", flag_descriptions::kForceDiceMigrationName,
+     flag_descriptions::kForceDiceMigrationDescription, kOsAll,
+     FEATURE_VALUE_TYPE(kForceDiceMigration)},
     {"show-sync-paused-reason-cookies-cleared-on-exit",
      flag_descriptions::kShowSyncPausedReasonCookiesClearedOnExitName,
      flag_descriptions::kShowSyncPausedReasonCookiesClearedOnExitDescription,
@@ -3631,6 +3635,15 @@
      FEATURE_VALUE_TYPE(kClickToCallUI)},
 #endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
 
+    {"shared-clipboard-receiver",
+     flag_descriptions::kSharedClipboardReceiverName,
+     flag_descriptions::kSharedClipboardReceiverDescription, kOsAll,
+     FEATURE_VALUE_TYPE(kSharedClipboardReceiver)},
+
+    {"shared-clipboard-ui", flag_descriptions::kSharedClipboardUIName,
+     flag_descriptions::kSharedClipboardUIDescription, kOsAll,
+     FEATURE_VALUE_TYPE(kSharedClipboardUI)},
+
     {"enable-ambient-authentication-in-incognito",
      flag_descriptions::kEnableAmbientAuthenticationInIncognitoName,
      flag_descriptions::kEnableAmbientAuthenticationInIncognitoDescription,
diff --git a/chrome/browser/android/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc
index 533eaba..8c68074 100644
--- a/chrome/browser/android/autofill_assistant/client_android.cc
+++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -212,24 +212,16 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& jcaller,
     const base::android::JavaParamRef<jstring>& jexperiment_ids,
-    const base::android::JavaParamRef<jbyteArray>& jscript_bundle,
     const base::android::JavaParamRef<jobjectArray>& jargument_names,
     const base::android::JavaParamRef<jobjectArray>& jargument_values,
     const base::android::JavaParamRef<jobject>& jcallback) {
   if (!controller_)
     CreateController(nullptr);
 
-  std::string script_bundle_bytes;
-  if (jscript_bundle) {
-    base::android::JavaByteArrayToString(env, jscript_bundle,
-                                         &script_bundle_bytes);
-  }
-
   base::android::ScopedJavaGlobalRef<jobject> scoped_jcallback(env, jcallback);
   controller_->Track(
       CreateTriggerContext(env, jexperiment_ids, jargument_names,
                            jargument_values),
-      script_bundle_bytes,
       base::BindOnce(&ClientAndroid::OnListDirectActions,
                      weak_ptr_factory_.GetWeakPtr(), scoped_jcallback));
 }
@@ -400,9 +392,9 @@
 
   // Delete the controller in a separate task. This avoids tricky ordering
   // issues when Shutdown is called from the controller.
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(&ClientAndroid::DestroyController,
-                                          weak_ptr_factory_.GetWeakPtr()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&ClientAndroid::DestroyController,
+                                weak_ptr_factory_.GetWeakPtr()));
 }
 
 void ClientAndroid::FetchAccessToken(
diff --git a/chrome/browser/android/autofill_assistant/client_android.h b/chrome/browser/android/autofill_assistant/client_android.h
index 1337bb8..3a920bd 100644
--- a/chrome/browser/android/autofill_assistant/client_android.h
+++ b/chrome/browser/android/autofill_assistant/client_android.h
@@ -66,7 +66,6 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& jcaller,
       const base::android::JavaParamRef<jstring>& jexperiment_ids,
-      const base::android::JavaParamRef<jbyteArray>& jscript_bundle,
       const base::android::JavaParamRef<jobjectArray>& jargument_names,
       const base::android::JavaParamRef<jobjectArray>& jargument_values,
       const base::android::JavaParamRef<jobject>& jcallback);
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
index d882a53..79a4e41 100644
--- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
+++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
@@ -92,10 +92,9 @@
 
   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&SetFaviconCallback, profile, node->url(), fake_icon_url,
-                     image_data, icon_type, &event));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&SetFaviconCallback, profile, node->url(),
+                                fake_icon_url, image_data, icon_type, &event));
   // TODO(aruslan): http://b/6397072 If possible - avoid using favicon service
   event.Wait();
 }
@@ -225,12 +224,11 @@
                                         bool fallback_to_server,
                                         int desired_favicon_size_px,
                                         FaviconFetchedCallback callback) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&PartnerBookmarksReader::GetFaviconImpl,
-                     base::Unretained(this), page_url, profile,
-                     fallback_to_server, desired_favicon_size_px,
-                     std::move(callback)));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&PartnerBookmarksReader::GetFaviconImpl,
+                                base::Unretained(this), page_url, profile,
+                                fallback_to_server, desired_favicon_size_px,
+                                std::move(callback)));
 }
 
 void PartnerBookmarksReader::GetFaviconImpl(const GURL& page_url,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index c51ce3c..ce6a4bb 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -16,6 +16,7 @@
 #include "chrome/common/chrome_features.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill_assistant/browser/features.h"
+#include "components/browser_sync/browser_sync_switches.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/download/public/common/download_features.h"
 #include "components/feed/feed_feature_list.h"
@@ -214,6 +215,7 @@
     &password_manager::features::kPasswordEditingAndroid,
     &safe_browsing::kCaptureSafetyNetId,
     &signin::kMiceFeature,
+    &switches::kSyncManualStartAndroid,
     &switches::kSyncSendTabToSelf,
     &translate::kTranslateMobileManualTrigger,
     &unified_consent::kUnifiedConsent,
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc
index 4565c25..cfcf278 100644
--- a/chrome/browser/android/download/download_controller.cc
+++ b/chrome/browser/android/download/download_controller.cc
@@ -250,14 +250,14 @@
         StoragePermissionType::STORAGE_PERMISSION_REQUESTED);
     RecordStoragePermission(
         StoragePermissionType::STORAGE_PERMISSION_NO_ACTION_NEEDED);
-    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::BindOnce(std::move(cb), true));
+    base::PostTask(FROM_HERE, {BrowserThread::UI},
+                   base::BindOnce(std::move(cb), true));
     return;
   } else if (vr::VrTabHelper::IsUiSuppressedInVr(
                  web_contents,
                  vr::UiSuppressedElement::kFileAccessPermission)) {
-    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::BindOnce(std::move(cb), false));
+    base::PostTask(FROM_HERE, {BrowserThread::UI},
+                   base::BindOnce(std::move(cb), false));
     return;
   }
 
@@ -275,10 +275,9 @@
 void DownloadController::CreateAndroidDownload(
     const content::WebContents::Getter& wc_getter,
     const DownloadInfo& info) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&DownloadController::StartAndroidDownload,
-                     base::Unretained(this), wc_getter, info));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&DownloadController::StartAndroidDownload,
+                                base::Unretained(this), wc_getter, info));
 }
 
 void DownloadController::AboutToResumeDownload(DownloadItem* download_item) {
@@ -443,7 +442,7 @@
     auto download_manager_getter = std::make_unique<DownloadManagerGetter>(
         BrowserContext::GetDownloadManager(
             content::DownloadItemUtils::GetBrowserContext(item)));
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(&RemoveDownloadItem, std::move(download_manager_getter),
                        item->GetGuid()));
diff --git a/chrome/browser/android/download/download_media_parser.cc b/chrome/browser/android/download/download_media_parser.cc
index b263d55..3516c3d3 100644
--- a/chrome/browser/android/download/download_media_parser.cc
+++ b/chrome/browser/android/download/download_media_parser.cc
@@ -60,8 +60,8 @@
                                          const base::FilePath& file_path)
     : mime_type_(mime_type),
       file_path_(file_path),
-      file_task_runner_(
-          base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})),
+      file_task_runner_(base::CreateSingleThreadTaskRunner(
+          {base::ThreadPool(), base::MayBlock()})),
       decode_done_(false),
       weak_factory_(this) {}
 
diff --git a/chrome/browser/android/explore_sites/explore_sites_service_factory.cc b/chrome/browser/android/explore_sites/explore_sites_service_factory.cc
index 122a160..b2314526 100644
--- a/chrome/browser/android/explore_sites/explore_sites_service_factory.cc
+++ b/chrome/browser/android/explore_sites/explore_sites_service_factory.cc
@@ -74,7 +74,7 @@
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()});
+      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock()});
   base::FilePath store_path =
       profile->GetPath().Append(kExploreSitesStoreDirname);
   auto explore_sites_store =
diff --git a/chrome/browser/android/history_report/data_provider.cc b/chrome/browser/android/history_report/data_provider.cc
index df1e7b6..5ca5661 100644
--- a/chrome/browser/android/history_report/data_provider.cc
+++ b/chrome/browser/android/history_report/data_provider.cc
@@ -122,10 +122,10 @@
     if (!entries->empty()) {
       Context context(history_service_,
                       &history_task_tracker_);
-      base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                               base::BindOnce(&QueryUrlsHistoryInUiThread,
-                                              base::Unretained(&context),
-                                              base::Unretained(entries.get())));
+      base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                     base::BindOnce(&QueryUrlsHistoryInUiThread,
+                                    base::Unretained(&context),
+                                    base::Unretained(entries.get())));
       std::vector<UrlAndTitle> bookmarks;
       bookmark_model_->model_loader()->BlockTillLoaded();
       bookmark_model_->GetBookmarks(&bookmarks);
@@ -159,12 +159,11 @@
   base::WaitableEvent finished(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                                base::WaitableEvent::InitialState::NOT_SIGNALED);
   buffer_service->Clear();
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&StartVisitMigrationToUsageBufferUiThread,
-                     base::Unretained(history_service_), buffer_service,
-                     base::Unretained(&finished),
-                     base::Unretained(&history_task_tracker_)));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&StartVisitMigrationToUsageBufferUiThread,
+                                base::Unretained(history_service_),
+                                buffer_service, base::Unretained(&finished),
+                                base::Unretained(&history_task_tracker_)));
   finished.Wait();
 }
 
@@ -178,7 +177,7 @@
     std::unique_ptr<history::HistoryDBTask> task =
         std::unique_ptr<history::HistoryDBTask>(
             new GetAllUrlsFromHistoryTask(&finished, &urls));
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
             base::IgnoreResult(&history::HistoryService::ScheduleDBTask),
diff --git a/chrome/browser/android/history_report/delta_file_service.cc b/chrome/browser/android/history_report/delta_file_service.cc
index 44001b9..233f9cb 100644
--- a/chrome/browser/android/history_report/delta_file_service.cc
+++ b/chrome/browser/android/history_report/delta_file_service.cc
@@ -78,8 +78,9 @@
 using content::BrowserThread;
 
 DeltaFileService::DeltaFileService(const base::FilePath& dir)
-    : task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+    : task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       delta_file_backend_(new DeltaFileBackend(dir)) {
   base::trace_event::MemoryDumpManager::GetInstance()
       ->RegisterDumpProviderWithSequencedTaskRunner(
diff --git a/chrome/browser/android/history_report/usage_reports_buffer_service.cc b/chrome/browser/android/history_report/usage_reports_buffer_service.cc
index 6c36117..aa97cd01 100644
--- a/chrome/browser/android/history_report/usage_reports_buffer_service.cc
+++ b/chrome/browser/android/history_report/usage_reports_buffer_service.cc
@@ -72,8 +72,9 @@
 namespace history_report {
 
 UsageReportsBufferService::UsageReportsBufferService(const base::FilePath& dir)
-    : task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+    : task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       backend_(new UsageReportsBufferBackend(dir)) {
   base::trace_event::MemoryDumpManager::GetInstance()
       ->RegisterDumpProviderWithSequencedTaskRunner(
diff --git a/chrome/browser/android/password_ui_view_android.cc b/chrome/browser/android/password_ui_view_android.cc
index f32b0ba2d..9e9c23f 100644
--- a/chrome/browser/android/password_ui_view_android.cc
+++ b/chrome/browser/android/password_ui_view_android.cc
@@ -181,8 +181,9 @@
   // but still long enough not to block the UI thread. The main concern here is
   // not to avoid the background computation if |this| is about to be deleted
   // but to simply avoid use after free from the background task runner.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(
           &PasswordUIViewAndroid::ObtainAndSerializePasswords,
           base::Unretained(this),
diff --git a/chrome/browser/android/usage_stats/usage_stats_database.cc b/chrome/browser/android/usage_stats/usage_stats_database.cc
index b352fd9..e365c0bd 100644
--- a/chrome/browser/android/usage_stats/usage_stats_database.cc
+++ b/chrome/browser/android/usage_stats/usage_stats_database.cc
@@ -44,8 +44,8 @@
   base::FilePath usage_stats_dir = profile->GetPath().Append(kNamespace);
 
   scoped_refptr<base::SequencedTaskRunner> db_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                       base::TaskPriority::BEST_EFFORT});
 
   website_event_db_ = db_provider->GetDB<WebsiteEvent>(
       leveldb_proto::ProtoDbType::USAGE_STATS_WEBSITE_EVENT,
diff --git a/chrome/browser/android/vr/mailbox_to_surface_bridge.cc b/chrome/browser/android/vr/mailbox_to_surface_bridge.cc
index cf991b4..227b4b3 100644
--- a/chrome/browser/android/vr/mailbox_to_surface_bridge.cc
+++ b/chrome/browser/android/vr/mailbox_to_surface_bridge.cc
@@ -257,7 +257,7 @@
       base::BindRepeating(&MailboxToSurfaceBridge::OnContextAvailableOnUiThread,
                           weak_ptr_factory_.GetWeakPtr());
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(
           [](int surface_handle,
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index f6c0ba2..7728b9e0 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -328,9 +328,9 @@
 
 // Returns task runner for running background tasks.
 scoped_refptr<base::TaskRunner> GetBackgroundTaskRunner() {
-  return base::CreateTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+  return base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                 base::TaskPriority::BEST_EFFORT,
+                                 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
 }  // anonymous namespace
diff --git a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
index 0bcf37f..d5a8bd8 100644
--- a/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
+++ b/chrome/browser/android/webapps/add_to_homescreen_data_fetcher.cc
@@ -321,9 +321,9 @@
   // The user is waiting for the icon to be processed before they can proceed
   // with add to homescreen. But if we shut down, there's no point starting the
   // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN.
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&CreateLauncherIconFromFaviconInBackground,
                      shortcut_info_.url, bitmap_result),
@@ -337,9 +337,9 @@
   // The user is waiting for the icon to be processed before they can proceed
   // with add to homescreen. But if we shut down, there's no point starting the
   // image processing. Use USER_VISIBLE with MayBlock and SKIP_ON_SHUTDOWN.
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&CreateLauncherIconInBackground, shortcut_info_.url, icon,
                      has_maskable_primary_icon_),
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
index 954f760..31cfdf4c 100644
--- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -52,19 +52,15 @@
 #include "services/network/public/cpp/network_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using captured_sites_test_utils::CapturedSiteParams;
+using captured_sites_test_utils::GetCapturedSites;
+
 namespace {
 
 const base::TimeDelta autofill_wait_for_action_interval =
     base::TimeDelta::FromSeconds(5);
 
-struct GetParamAsString {
-  template <class ParamType>
-  std::string operator()(const testing::TestParamInfo<ParamType>& info) const {
-    return info.param;
-  }
-};
-
-base::FilePath GetReplayFilesDirectory() {
+base::FilePath GetReplayFilesRootDirectory() {
   base::FilePath src_dir;
   if (base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) {
     return src_dir.AppendASCII("chrome")
@@ -78,29 +74,6 @@
   }
 }
 
-// Iterate through Autofill's Web Page Replay capture file directory to look
-// for captures sites and automation recipe files. Return a list of sites for
-// which recipe-based testing is available.
-std::vector<std::string> GetCapturedSites() {
-  std::vector<std::string> sites;
-  base::FileEnumerator capture_files(GetReplayFilesDirectory(), false,
-                                     base::FileEnumerator::FILES);
-  for (base::FilePath file = capture_files.Next(); !file.empty();
-       file = capture_files.Next()) {
-    // If a site capture file is found, also look to see if the directory has
-    // a corresponding recorded action recipe log file.
-    // A site capture file has no extension. A recorded action recipe log file
-    // has the '.test' extension.
-    if (file.Extension().empty() &&
-        base::PathExists(file.AddExtension(FILE_PATH_LITERAL(".test")))) {
-      sites.push_back(
-          captured_sites_test_utils::FilePathToUTF8(file.BaseName().value()));
-    }
-  }
-  std::sort(sites.begin(), sites.end());
-  return sites;
-}
-
 }  // namespace
 
 namespace autofill {
@@ -109,7 +82,7 @@
     : public AutofillUiTest,
       public captured_sites_test_utils::
           TestRecipeReplayChromeFeatureActionExecutor,
-      public ::testing::WithParamInterface<std::string> {
+      public ::testing::WithParamInterface<CapturedSiteParams> {
  public:
   // TestRecipeReplayChromeFeatureActionExecutor
   bool AutofillForm(const std::string& focus_element_css_selector,
@@ -226,11 +199,9 @@
             browser(), this);
     recipe_replayer()->Setup();
 
-    const base::FilePath capture_file_path =
-        GetReplayFilesDirectory().AppendASCII(GetParam().c_str());
     SetServerUrlLoader(std::make_unique<test::ServerUrlLoader>(
         std::make_unique<test::ServerCacheReplayer>(
-            capture_file_path,
+            GetParam().capture_file_path,
             test::ServerCacheReplayer::kOptionFailOnInvalidJsonRecord)));
   }
 
@@ -321,27 +292,42 @@
 
 IN_PROC_BROWSER_TEST_P(AutofillCapturedSitesInteractiveTest, Recipe) {
   // Prints the path of the test to be executed.
-  VLOG(1) << GetParam();
+  VLOG(1) << GetParam().site_name;
 
-  // Craft the capture file path.
   base::FilePath src_dir;
   ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
-  base::FilePath capture_file_path =
-      GetReplayFilesDirectory().AppendASCII(GetParam().c_str());
 
-  // Craft the recipe file path.
-  base::FilePath recipe_file_path = GetReplayFilesDirectory().AppendASCII(
-      base::StringPrintf("%s.test", GetParam().c_str()));
+  bool test_completed = recipe_replayer()->ReplayTest(
+      GetParam().capture_file_path, GetParam().recipe_file_path);
+  if (!test_completed)
+    ADD_FAILURE() << "Full execution was unable to complete.";
 
-  VLOG(1) << "Recipe file path: " << recipe_file_path;
-  VLOG(1) << "Capture file path: " << capture_file_path;
-
-  ASSERT_TRUE(
-      recipe_replayer()->ReplayTest(capture_file_path, recipe_file_path));
+  std::vector<testing::AssertionResult> validation_failures =
+      recipe_replayer()->GetValidationFailures();
+  if (GetParam().expectation == captured_sites_test_utils::kPass) {
+    if (validation_failures.empty()) {
+      VLOG(1) << "No Validation Failures";
+    } else {
+      LOG(INFO) << "There were " << validation_failures.size()
+              << " Validation Failure(s)";
+      for (auto& validation_failure : validation_failures)
+        ADD_FAILURE() << validation_failure.message();
+    }
+  } else {
+    if (validation_failures.empty()) {
+      VLOG(1) << "Expected Validation Failures but still succeeded. "
+              << "Time to update testcases.json file?";
+    } else {
+      VLOG(1) << "Validation Failures expected and received so skipping";
+      for (auto& validation_failure : validation_failures)
+        VLOG(1) << validation_failure.message();
+      GTEST_SKIP();
+    }
+  }
 }
-
-INSTANTIATE_TEST_SUITE_P(,
-                         AutofillCapturedSitesInteractiveTest,
-                         testing::ValuesIn(GetCapturedSites()),
-                         GetParamAsString());
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    AutofillCapturedSitesInteractiveTest,
+    testing::ValuesIn(GetCapturedSites(GetReplayFilesRootDirectory())),
+    captured_sites_test_utils::GetParamAsString());
 }  // namespace autofill
diff --git a/chrome/browser/autofill/captured_sites_test_utils.cc b/chrome/browser/autofill/captured_sites_test_utils.cc
index 73b21c0..5631a2c 100644
--- a/chrome/browser/autofill/captured_sites_test_utils.cc
+++ b/chrome/browser/autofill/captured_sites_test_utils.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/bind.h"
@@ -14,6 +15,7 @@
 #include "base/json/json_string_value_serializer.h"
 #include "base/path_service.h"
 #include "base/process/launch.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -44,6 +46,9 @@
 #include "ui/events/keycodes/keyboard_code_conversion.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 
+using base::JSONParserOptions;
+using base::JSONReader;
+
 namespace {
 // The maximum amount of time to wait for Chrome to finish autofilling a form.
 const base::TimeDelta kAutofillActionWaitForVisualUpdateTimeout =
@@ -72,6 +77,102 @@
 
 namespace captured_sites_test_utils {
 
+CapturedSiteParams::CapturedSiteParams() = default;
+CapturedSiteParams::~CapturedSiteParams() = default;
+CapturedSiteParams::CapturedSiteParams(const CapturedSiteParams& other) = default;
+
+std::ostream& operator<<(std::ostream& os, const CapturedSiteParams& param) {
+  if (param.scenario_dir.empty())
+    return os << "Site: " << param.site_name;
+  return os << "Scenario: " << param.scenario_dir
+            << ", Site: " << param.site_name;
+}
+
+// Iterate through Autofill's Web Page Replay capture file directory to look
+// for captures sites and automation recipe files. Return a list of sites for
+// which recipe-based testing is available.
+std::vector<CapturedSiteParams> GetCapturedSites(
+    const base::FilePath& replay_files_dir_path) {
+  std::vector<CapturedSiteParams> sites;
+  base::FilePath config_file_path =
+      replay_files_dir_path.AppendASCII("testcases.json");
+
+  std::string json_text;
+  {
+    if (!base::ReadFileToString(config_file_path, &json_text)) {
+      LOG(WARNING) << "Could not read json file: " << config_file_path;
+      return sites;
+    }
+  }
+  // Parse json text content to json value node.
+  base::Value root_node;
+  {
+    JSONReader::ValueWithError value_with_error =
+        JSONReader().ReadAndReturnValueWithError(
+            json_text, JSONParserOptions::JSON_PARSE_RFC);
+    if (value_with_error.error_code !=
+        JSONReader::JsonParseError::JSON_NO_ERROR) {
+      LOG(WARNING) << "Could not load test config from json file: "
+                   << "`testcases.json` because: "
+                   << value_with_error.error_message;
+      return sites;
+    }
+    if (!value_with_error.value) {
+      LOG(WARNING) << "JSON Reader could not any object from `testcases.json`";
+      return sites;
+    }
+    root_node = std::move(value_with_error.value.value());
+  }
+  base::Value* list_node = root_node.FindListKey("tests");
+  if (!list_node) {
+    LOG(WARNING) << "No tests found in `testcases.json` config";
+    return sites;
+  }
+
+  bool also_run_disabled = testing::FLAGS_gtest_also_run_disabled_tests == 1;
+  for (auto& item : list_node->GetList()) {
+    const base::DictionaryValue* dict;
+    if (!item.GetAsDictionary(&dict))
+      continue;
+    CapturedSiteParams param;
+    param.site_name = *(dict->FindStringKey("site_name"));
+    if (dict->HasKey("scenario_dir"))
+      param.scenario_dir = *(dict->FindStringKey("scenario_dir"));
+    param.is_disabled = dict->FindBoolKey("disabled").value_or(false);
+    if (param.is_disabled && !also_run_disabled)
+      continue;
+
+    const std::string* expectation_string = dict->FindStringKey("expectation");
+    if (expectation_string && *expectation_string == "FAIL") {
+      param.expectation = kFail;
+    } else {
+      param.expectation = kPass;
+    }
+    // Check that a pair of .test and .wpr files exist - otherwise skip
+    base::FilePath file_name = replay_files_dir_path;
+    if (!param.scenario_dir.empty())
+      file_name = file_name.AppendASCII(param.scenario_dir);
+    file_name = file_name.AppendASCII(param.site_name);
+
+    base::FilePath capture_file_path = file_name.AddExtensionASCII("wpr");
+    if (!base::PathExists(capture_file_path)) {
+      LOG(WARNING) << "Test `" << param.site_name
+                   << "` had no matching .wpr file";
+      continue;
+    }
+    base::FilePath recipe_file_path = file_name.AddExtensionASCII("test");
+    if (!base::PathExists(recipe_file_path)) {
+      LOG(WARNING) << "Test `" << param.site_name
+                   << "` had no matching .test file";
+      continue;
+    }
+    param.capture_file_path = capture_file_path;
+    param.recipe_file_path = recipe_file_path;
+    sites.push_back(param);
+  }
+  return sites;
+}
+
 constexpr base::TimeDelta PageActivityObserver::kPaintEventCheckInterval;
 
 std::string FilePathToUTF8(const base::FilePath::StringType& str) {
@@ -269,6 +370,11 @@
   return ReplayRecordedActions(recipe_file_path);
 }
 
+const std::vector<testing::AssertionResult>
+TestRecipeReplayer::GetValidationFailures() const {
+  return validation_failures_;
+}
+
 // static
 void TestRecipeReplayer::SetUpCommandLine(base::CommandLine* command_line) {
   // Direct traffic to the Web Page Replay server.
@@ -493,6 +599,19 @@
   return true;
 }
 
+const std::string* FindPopulateString(
+                        const base::DictionaryValue& container,
+                        const std::string key_name,
+                        const std::string key_descriptor) {
+  const std::string* string_value = container.FindStringKey(key_name);
+  if (!string_value) {
+    ADD_FAILURE() << "Failed to extract '" << key_descriptor
+                  << "' from container!";
+    return nullptr;
+  }
+  return string_value;
+}
+
 bool TestRecipeReplayer::ReplayRecordedActions(
     const base::FilePath& recipe_file_path) {
   // Read the text of the recipe file.
@@ -515,95 +634,78 @@
     return false;
 
   // Iterate through and execute each action in the recipe.
-  base::Value* action_list_container = recipe->FindKey("actions");
+  base::Value* action_list_container = recipe->FindListKey("actions");
   if (!action_list_container) {
     ADD_FAILURE() << "Failed to extract action list from the recipe!";
     return false;
   }
-
-  if (base::Value::Type::LIST != action_list_container->type()) {
-    ADD_FAILURE() << "The recipe's actions object is not a list!";
-    return false;
-  }
-
-  base::Value::ListStorage& action_list = action_list_container->GetList();
-
-  for (auto it_action = action_list.begin(); it_action != action_list.end();
-       ++it_action) {
+  for (auto& item : action_list_container->GetList()) {
     base::DictionaryValue* action;
-    if (!it_action->GetAsDictionary(&action)) {
+    if (!item.GetAsDictionary(&action)) {
       ADD_FAILURE()
           << "Failed to extract an individual action from the recipe!";
       return false;
     }
-
-    base::Value* type_container = action->FindKey("type");
-    if (!type_container) {
-      ADD_FAILURE() << "Failed to extract action type from the recipe!";
+    const std::string* type =
+        FindPopulateString(*action, "type", "action type");
+    if (!type)
       return false;
-    }
-    if (base::Value::Type::STRING != type_container->type()) {
-      ADD_FAILURE() << "Action type is not a string!";
-      return false;
-    }
-    std::string type = type_container->GetString();
-
-    if (base::CompareCaseInsensitiveASCII(type, "autofill") == 0) {
+    if (base::CompareCaseInsensitiveASCII(*type, "autofill") == 0) {
       if (!ExecuteAutofillAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "click") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "click") == 0) {
       if (!ExecuteClickAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "coolOff") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "coolOff") == 0) {
       if (!ExecuteCoolOffAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "executeScript") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "executeScript") == 0) {
       if (!ExecuteRunCommandAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "hover") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "hover") == 0) {
       if (!ExecuteHoverAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "loadPage") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "loadPage") == 0) {
       if (!ExecuteForceLoadPage(*action))
         return false;
-      // Load page is an no-op action.
-    } else if (base::CompareCaseInsensitiveASCII(type, "pressEnter") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "pressEnter") == 0) {
       if (!ExecutePressEnterAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "pressEscape") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "pressEscape") == 0) {
       if (!ExecutePressEscapeAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "savePassword") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "savePassword") == 0) {
       if (!ExecuteSavePasswordAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "select") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "select") == 0) {
       if (!ExecuteSelectDropdownAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "type") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "type") == 0) {
       if (!ExecuteTypeAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "typePassword") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "typePassword") == 0) {
       if (!ExecuteTypePasswordAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "updatePassword") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(
+                   *type, "updatePassword") == 0) {
       if (!ExecuteUpdatePasswordAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "validateField") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "validateField") == 0) {
       if (!ExecuteValidateFieldValueAction(*action))
         return false;
     } else if (base::CompareCaseInsensitiveASCII(
-                   type, "validateNoSavePasswordPrompt") == 0) {
+                   *type, "validateNoSavePasswordPrompt") == 0) {
       if (!ExecuteValidateNoSavePasswordPromptAction(*action))
         return false;
     } else if (base::CompareCaseInsensitiveASCII(
-                   type, "validatePasswordSaveFallback") == 0) {
+                   *type, "validatePasswordSaveFallback") == 0) {
       if (!ExecuteValidateSaveFallbackAction(*action))
         return false;
-    } else if (base::CompareCaseInsensitiveASCII(type, "waitFor") == 0) {
+    } else if (base::CompareCaseInsensitiveASCII(*type, "waitFor") == 0) {
       if (!ExecuteWaitForStateAction(*action))
         return false;
     } else {
-      ADD_FAILURE() << "Unrecognized action type: " << type;
+      ADD_FAILURE() << "Unrecognized action type: " << *type;
     }
   }  // end foreach action
 
@@ -637,25 +739,18 @@
     return false;
 
   // Extract the starting URL from the test recipe.
-  base::Value* starting_url_container = recipe->FindKey("startingURL");
-  if (!starting_url_container) {
+  const std::string* starting_url = recipe->FindStringKey("startingURL");
+  if (!starting_url) {
     ADD_FAILURE() << "Failed to extract the starting url from the recipe!";
     return false;
   }
 
-  if (base::Value::Type::STRING != starting_url_container->type()) {
-    ADD_FAILURE() << "Starting url is not a string!";
-    return false;
-  }
-
-  std::string starting_url = starting_url_container->GetString();
-
   // Navigate to the starting URL, wait for the page to complete loading.
   PageActivityObserver page_activity_observer(GetWebContents());
   if (!content::ExecuteScript(GetWebContents(),
                               base::StringPrintf("window.location.href = '%s';",
-                                                 starting_url.c_str()))) {
-    ADD_FAILURE() << "Failed to navigate Chrome to '" << starting_url << "'!";
+                                                 starting_url->c_str()))) {
+    ADD_FAILURE() << "Failed to navigate Chrome to '" << starting_url << "!";
     return false;
   }
 
@@ -751,7 +846,7 @@
   base::TimeDelta cool_off_time = cool_off_action_timeout;
   const base::Value* pause_time_container = action.FindKey("pauseTimeSec");
   if (pause_time_container) {
-    if (pause_time_container->type() != base::Value::Type::INTEGER) {
+    if (!pause_time_container->is_int()) {
       ADD_FAILURE() << "Pause time is not an integer!";
       return false;
     }
@@ -808,29 +903,15 @@
 
 bool TestRecipeReplayer::ExecuteForceLoadPage(
     const base::DictionaryValue& action) {
-  const base::Value* force_load_container = action.FindKey("force");
-  const base::Value* url_container = action.FindKey("url");
-  if (!force_load_container) {
-    // Nothing to do, load should have been made by previous action
-    return true;
-  }
-
-  if (force_load_container->type() != base::Value::Type::BOOLEAN) {
-    ADD_FAILURE() << "Force load is not a bool!";
-    return false;
-  }
-
-  bool shouldForce = force_load_container->GetBool();
+  bool shouldForce = action.FindBoolKey("force").value_or(false);
   if (!shouldForce)
     return true;
 
-  if (!url_container || url_container->type() != base::Value::Type::STRING) {
-    ADD_FAILURE() << "Force load url could not be parsed";
+  const std::string* url = FindPopulateString(action, "url", "Force Load URL");
+  if (!url)
     return false;
-  }
-  std::string url = url_container->GetString();
-  VLOG(1) << "Making explicit URL redirect to '" << url << "'";
-  ui_test_utils::NavigateToURL(browser_, GURL(url));
+  VLOG(1) << "Making explicit URL redirect to '" << *url << "'";
+  ui_test_utils::NavigateToURL(browser_, GURL(*url));
 
   PageActivityObserver page_activity_observer(GetWebContents());
   page_activity_observer.WaitTillPageIsIdle();
@@ -892,28 +973,17 @@
   // Extract the list of JavaScript commands into a vector.
   std::vector<std::string> commands;
 
-  const base::Value* commands_list_container = action.FindKey("commands");
-  if (!commands_list_container) {
-    ADD_FAILURE()
-        << "Failed to extract the list of commands from the run command "
-        << "action!";
+  const base::Value* list_container = action.FindListKey("commands");
+  if (!list_container) {
+    ADD_FAILURE() << "Failed to extract commands list from action";
     return false;
   }
-
-  if (base::Value::Type::LIST != commands_list_container->type()) {
-    ADD_FAILURE() << "commands is not an array!";
-    return false;
-  }
-
-  const base::Value::ListStorage& commands_list =
-      commands_list_container->GetList();
-  for (auto it_command = commands_list.begin();
-       it_command != commands_list.end(); ++it_command) {
-    if (base::Value::Type::STRING != it_command->type()) {
-      ADD_FAILURE() << "command is not a string!";
+  for (const auto& command : list_container->GetList()) {
+    if (!command.is_string()) {
+      ADD_FAILURE() << "command is not a string: " << command;
       return false;
     }
-    commands.push_back(it_command->GetString());
+    commands.push_back(command.GetString());
   }
 
   content::RenderFrameHost* frame;
@@ -960,20 +1030,12 @@
 
 bool TestRecipeReplayer::ExecuteSelectDropdownAction(
     const base::DictionaryValue& action) {
-  const base::Value* index_container = action.FindKey("index");
-  if (!index_container) {
-    ADD_FAILURE()
-        << "Failed to extract selection index from the select action!";
+  base::Optional<int> index = action.FindIntKey("index");
+  if (!index) {
+    ADD_FAILURE() << "Failed to extract Selection Index from action";
     return false;
   }
 
-  if (base::Value::Type::INTEGER != index_container->type()) {
-    ADD_FAILURE() << "Selection index is not an integer!";
-    return false;
-  }
-
-  int index = index_container->GetInt();
-
   std::string xpath;
   if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
     return false;
@@ -990,14 +1052,14 @@
   if (!WaitForElementToBeReady(xpath, visibility_enum_val, frame))
     return false;
 
-  VLOG(1) << "Select option '" << index << "' from `" << xpath << "`.";
+  VLOG(1) << "Select option '" << index.value() << "' from `" << xpath << "`.";
   PageActivityObserver page_activity_observer(frame);
   if (!ExecuteJavaScriptOnElementByXpath(
           frame, xpath,
           base::StringPrintf(
               "automation_helper"
               "  .selectOptionFromDropDownElementByIndex(target, %d);",
-              index_container->GetInt()))) {
+              index.value()))) {
     ADD_FAILURE() << "Failed to select drop down option with JavaScript!";
     return false;
   }
@@ -1008,18 +1070,10 @@
 
 bool TestRecipeReplayer::ExecuteTypeAction(
     const base::DictionaryValue& action) {
-  const base::Value* value_container = action.FindKey("value");
-  if (!value_container) {
-    ADD_FAILURE() << "Failed to extract value from the type action!";
+  const std::string* value =
+      FindPopulateString(action, "value", "typing value");
+  if (!value)
     return false;
-  }
-
-  if (base::Value::Type::STRING != value_container->type()) {
-    ADD_FAILURE() << "Value is not a string!";
-    return false;
-  }
-
-  std::string value = value_container->GetString();
 
   std::string xpath;
   if (!GetTargetHTMLElementXpathFromAction(action, &xpath))
@@ -1043,7 +1097,7 @@
           frame, xpath,
           base::StringPrintf(
               "automation_helper.setInputElementValue(target, `%s`);",
-              value.c_str()))) {
+              value->c_str()))) {
     ADD_FAILURE() << "Failed to type inside input element with JavaScript!";
     return false;
   }
@@ -1074,19 +1128,10 @@
   if (!WaitForElementToBeReady(xpath, visibility_enum_val, frame))
     return false;
 
-  const base::Value* value_container = action.FindKey("value");
-  if (!value_container) {
-    ADD_FAILURE() << "Failed to extract the value from the type password"
-                  << " action!";
+  const std::string* value =
+      FindPopulateString(action, "value", "password text");
+  if (!value)
     return false;
-  }
-
-  if (base::Value::Type::STRING != value_container->type()) {
-    ADD_FAILURE() << "Value is not a string!";
-    return false;
-  }
-
-  std::string value = value_container->GetString();
 
   // Clear the password field first, in case a previous value is there.
   if (!ExecuteJavaScriptOnElementByXpath(
@@ -1101,9 +1146,8 @@
 
   VLOG(1) << "Typing '" << value << "' inside `" << xpath << "`.";
 
-  const char* c_array = value.c_str();
-  for (size_t index = 0; index < value.size(); index++) {
-    ui::DomKey key = ui::DomKey::FromCharacter(c_array[index]);
+  for (size_t index = 0; index < value->size(); index++) {
+    ui::DomKey key = ui::DomKey::FromCharacter(value->at(index));
     ui::KeyboardCode key_code = ui::NonPrintableDomKeyToKeyboardCode(key);
     ui::DomCode code = ui::UsLayoutKeyboardCodeToDomCode(key_code);
     SimulateKeyPress(content::WebContents::FromRenderFrameHost(frame), key,
@@ -1160,7 +1204,7 @@
   const base::Value* autofill_prediction_container =
       action.FindKey("expectedAutofillType");
   if (autofill_prediction_container) {
-    if (base::Value::Type::STRING != autofill_prediction_container->type()) {
+    if (!autofill_prediction_container->is_string()) {
       ADD_FAILURE() << "Autofill prediction is not a string!";
       return false;
     }
@@ -1181,28 +1225,19 @@
     VLOG(1) << "Checking the field `" << xpath << "` has the autofill type '"
             << expected_autofill_prediction_type << "'";
     ExpectElementPropertyEquals(
-        frame, xpath.c_str(),
+        frame, xpath,
         "return target.getAttribute('autofill-prediction');",
-        expected_autofill_prediction_type, true);
+        expected_autofill_prediction_type, "autofill type mismatch", true);
   }
 
-  const base::Value* expected_value_container = action.FindKey("expectedValue");
-  if (!expected_value_container) {
-    ADD_FAILURE() << "Failed to extract the expected value field from the "
-                     "validate field value action!";
+  const std::string* expected_value = FindPopulateString(action,
+    "expectedValue", "validation expected value");
+  if(!expected_value)
     return false;
-  }
-
-  if (base::Value::Type::STRING != expected_value_container->type()) {
-    ADD_FAILURE() << "Expected value is not a string!";
-    return false;
-  }
-
-  std::string expected_value = expected_value_container->GetString();
 
   VLOG(1) << "Checking the field `" << xpath << "`.";
-  ExpectElementPropertyEquals(frame, xpath.c_str(), "return target.value;",
-                              expected_value);
+  ExpectElementPropertyEquals(frame, xpath, "return target.value;",
+                              *expected_value, "text value mismatch");
   return true;
 }
 
@@ -1224,26 +1259,17 @@
     const base::DictionaryValue& action) {
   // Extract the list of JavaScript assertions into a vector.
   std::vector<std::string> state_assertions;
-  const base::Value* assertions_list_container = action.FindKey("assertions");
-  if (!assertions_list_container) {
-    ADD_FAILURE()
-        << "Failed to extract assertions from the wait for state action!";
+
+  const base::Value* list_container = action.FindListKey("assertions");
+  if (!list_container) {
+    ADD_FAILURE() << "Failed to extract wait assertions list from action";
     return false;
   }
-
-  if (base::Value::Type::LIST != assertions_list_container->type()) {
-    ADD_FAILURE() << "Assertions is not a list!";
-    return false;
-  }
-
-  const base::Value::ListStorage& assertions_list =
-      assertions_list_container->GetList();
-  for (const base::Value& assertion : assertions_list) {
-    if (base::Value::Type::STRING != assertion.type()) {
-      ADD_FAILURE() << "Assertion is not a string!";
+  for (const base::Value& assertion : list_container->GetList()) {
+    if (!assertion.is_string()) {
+      ADD_FAILURE() << "Assertion is not a string: " << assertion;
       return false;
     }
-
     state_assertions.push_back(assertion.GetString());
   }
 
@@ -1261,18 +1287,11 @@
     const base::DictionaryValue& action,
     std::string* xpath) {
   xpath->clear();
-  const base::Value* xpath_container = action.FindKey("selector");
-  if (!xpath_container) {
-    ADD_FAILURE() << "Failed to extract the xpath selector from action!";
+  const std::string* xpath_text =
+      FindPopulateString(action, "selector", "xpath selector");
+  if (!xpath_text)
     return false;
-  }
-
-  if (base::Value::Type::STRING != xpath_container->type()) {
-    ADD_FAILURE() << "Xpath selector is not a string!";
-    return false;
-  }
-
-  *xpath = xpath_container->GetString();
+  *xpath = *xpath_text;
   return true;
 }
 
@@ -1288,7 +1307,7 @@
     return true;
   }
 
-  if (base::Value::Type::INTEGER != visibility_container->type()) {
+  if (!visibility_container->is_int()) {
     ADD_FAILURE() << "visibility property is not an integer!";
     return false;
   }
@@ -1312,19 +1331,12 @@
     return false;
   }
 
-  const base::Value* is_iframe_container = iframe->FindKey("isIframe");
+  base::Optional<bool> is_iframe_container = iframe->FindBoolKey("isIframe");
   if (!is_iframe_container) {
-    ADD_FAILURE()
-        << "Failed to extract the isIframe field from the iframe context!";
+    ADD_FAILURE() << "Failed to extract isIframe from the iframe context! ";
     return false;
   }
-
-  if (base::Value::Type::BOOLEAN != is_iframe_container->type()) {
-    ADD_FAILURE() << "isIframe is not a boolean value!";
-    return false;
-  }
-
-  if (!is_iframe_container->GetBool()) {
+  if (!is_iframe_container.value_or(false)) {
     *frame = GetWebContents()->GetMainFrame();
     return true;
   }
@@ -1337,20 +1349,18 @@
       iframe->FindPath({"browserTest", "url"});
   IFrameWaiter iframe_waiter(GetWebContents());
 
-  if (frame_name_container != nullptr &&
-      base::Value::Type::STRING != frame_name_container->type()) {
+  if (frame_name_container != nullptr && !frame_name_container->is_string()) {
     ADD_FAILURE() << "Iframe name is not a string!";
     return false;
   }
 
   if (frame_origin_container != nullptr &&
-      base::Value::Type::STRING != frame_origin_container->type()) {
+      !frame_origin_container->is_string()) {
     ADD_FAILURE() << "Iframe origin is not a string!";
     return false;
   }
 
-  if (frame_url_container != nullptr &&
-      base::Value::Type::STRING != frame_url_container->type()) {
+  if (frame_url_container != nullptr && !frame_url_container->is_string()) {
     ADD_FAILURE() << "Iframe url is not a string!";
     return false;
   }
@@ -1401,24 +1411,19 @@
     //    rendering process.
     return true;
   }
-
-  if (base::Value::Type::LIST != iframe_path_container->type()) {
+  if (!iframe_path_container->is_list()) {
     ADD_FAILURE() << "The action's iframe path is not a list!";
     return false;
   }
-
   const base::Value::ListStorage& iframe_xpath_list =
       iframe_path_container->GetList();
-  for (auto it_xpath = iframe_xpath_list.begin();
-       it_xpath != iframe_xpath_list.end(); ++it_xpath) {
-    std::string xpath;
-    if (!it_xpath->GetAsString(&xpath)) {
+  for (const auto& xpath : iframe_xpath_list) {
+    if (!xpath.is_string()) {
       ADD_FAILURE() << "Failed to extract the iframe xpath from action!";
       return false;
     }
-    iframe_path->push_back(xpath);
+    iframe_path->push_back(xpath.GetString());
   }
-
   return true;
 }
 
@@ -1465,13 +1470,13 @@
     content::RenderFrameHost* frame,
     const std::vector<std::string>& state_assertions,
     const base::TimeDelta& timeout) {
-  const base::TimeTicks start_time = base::TimeTicks::Now();
+  base::TimeTicks start_time = base::TimeTicks::Now();
   PageActivityObserver page_activity_observer(
       content::WebContents::FromRenderFrameHost(frame));
   while (!AllAssertionsPassed(frame, state_assertions)) {
     if (base::TimeTicks::Now() - start_time > timeout) {
-      ADD_FAILURE() << "State change hasn't completed within timeout.";
-      return false;
+        ADD_FAILURE() << "State change hasn't completed within timeout.";
+        return false;
     }
     page_activity_observer.WaitTillPageIsIdle();
   }
@@ -1543,7 +1548,8 @@
     const std::string& element_xpath,
     const std::string& get_property_function_body,
     const std::string& expected_value,
-    bool ignoreCase) {
+    const std::string& validation_field,
+    bool ignore_case) {
   std::string value;
   if (!GetElementProperty(frame, element_xpath, get_property_function_body,
                           &value)) {
@@ -1552,13 +1558,15 @@
     return false;
   }
 
-  if (ignoreCase) {
-    EXPECT_TRUE(base::EqualsCaseInsensitiveASCII(expected_value, value))
-        << "Field xpath: `" << element_xpath << "`, "
-        << "Expected: " << expected_value << ", actual: " << value;
-  } else {
-    EXPECT_EQ(expected_value, value)
-        << "Field xpath: `" << element_xpath << "`, ";
+  if ((ignore_case &&
+       !base::EqualsCaseInsensitiveASCII(expected_value, value)) ||
+      (!ignore_case && expected_value != value)) {
+    std::string error_message = base::StrCat(
+      {"Field xpath: `", element_xpath, "` ", validation_field, ", ",
+       "Expected: '" , expected_value, "', actual: '", value, "'"});
+    VLOG(1) << error_message;
+    validation_failures_.push_back(testing::AssertionFailure()
+                                   << error_message);
   }
   return true;
 }
@@ -1776,52 +1784,22 @@
 bool TestRecipeReplayer::HasChromeStoredCredential(
     const base::DictionaryValue& action,
     bool* stored_cred) {
-  const base::Value* orgin_container = action.FindKey("origin");
-
-  if (!orgin_container) {
-    ADD_FAILURE() << "Failed to extract the origin from the action!";
+  const std::string* origin = FindPopulateString(action, "origin", "Origin");
+  const std::string* username = FindPopulateString(action,
+                                                   "userName", "Username");
+  const std::string* password = FindPopulateString(action,
+                                                   "password", "Password");
+  if (!origin || !username || !password)
     return false;
-  }
-
-  if (base::Value::Type::STRING != orgin_container->type()) {
-    ADD_FAILURE() << "Origin is not a string!";
-    return false;
-  }
-
-  const base::Value* user_name_container = action.FindKey("userName");
-
-  if (!user_name_container) {
-    ADD_FAILURE() << "Failed to extract the user name from the action!";
-    return false;
-  }
-
-  if (base::Value::Type::STRING != user_name_container->type()) {
-    ADD_FAILURE() << "User name is not a string!";
-    return false;
-  }
-
-  const base::Value* password_container = action.FindKey("password");
-
-  if (!password_container) {
-    ADD_FAILURE() << "Failed to extract the password from the action!";
-    return false;
-  }
-
-  if (base::Value::Type::STRING != password_container->type()) {
-    ADD_FAILURE() << "Password is not a string!";
-    return false;
-  }
-
   *stored_cred = feature_action_executor()->HasChromeStoredCredential(
-      orgin_container->GetString(), user_name_container->GetString(),
-      password_container->GetString());
+      *origin, *username, *password);
 
   return true;
 }
 
 bool TestRecipeReplayer::SetupSavedAutofillProfile(
     const base::Value& saved_autofill_profile_container) {
-  if (base::Value::Type::LIST != saved_autofill_profile_container.type()) {
+  if (!saved_autofill_profile_container.is_list()) {
     ADD_FAILURE() << "Save Autofill Profile is not a list!";
     return false;
   }
@@ -1836,21 +1814,14 @@
       return false;
     }
 
-    const base::Value* type_container = entry->FindKey("type");
-    if (base::Value::Type::STRING != type_container->type()) {
-      ADD_FAILURE() << "Type is not a string!";
+    const std::string* type =
+        FindPopulateString(*entry, "type", "profile field type");
+    const std::string* value =
+        FindPopulateString(*entry, "value", "profile field value");
+    if (!type || !value)
       return false;
-    }
-    const std::string type = type_container->GetString();
 
-    const base::Value* value_container = entry->FindKey("value");
-    if (base::Value::Type::STRING != value_container->type()) {
-      ADD_FAILURE() << "Value is not a string!";
-      return false;
-    }
-    const std::string value = value_container->GetString();
-
-    if (!feature_action_executor()->AddAutofillProfileInfo(type, value)) {
+    if (!feature_action_executor()->AddAutofillProfileInfo(*type, *value)) {
       return false;
     }
   }
@@ -1870,7 +1841,7 @@
 
 bool TestRecipeReplayer::SetupSavedPasswords(
     const base::Value& saved_password_list_container) {
-  if (base::Value::Type::LIST != saved_password_list_container.type()) {
+  if (!saved_password_list_container.is_list()) {
     ADD_FAILURE() << "Saved Password List is not a list!";
     return false;
   }
@@ -1885,28 +1856,17 @@
       return false;
     }
 
-    const base::Value* origin_container = cred->FindKey("website");
-    if (base::Value::Type::STRING != origin_container->type()) {
-      ADD_FAILURE() << "Website is not a string!";
+    const std::string* origin =
+        FindPopulateString(*cred, "website", "Website");
+    const std::string* username =
+        FindPopulateString(*cred, "username", "Username");
+    const std::string* password =
+        FindPopulateString(*cred, "password", "Password");
+    if (!origin || !username || !password)
       return false;
-    }
-    const std::string origin = origin_container->GetString();
 
-    const base::Value* username_container = cred->FindKey("username");
-    if (base::Value::Type::STRING != username_container->type()) {
-      ADD_FAILURE() << "User name is not a string!";
-      return false;
-    }
-    const std::string username = username_container->GetString();
-
-    const base::Value* password_container = cred->FindKey("password");
-    if (base::Value::Type::STRING != password_container->type()) {
-      ADD_FAILURE() << "User name is not a string!";
-      return false;
-    }
-    const std::string password = password_container->GetString();
-
-    if (!feature_action_executor()->AddCredential(origin, username, password)) {
+    if (!feature_action_executor()->AddCredential(*origin, *username,
+          *password)) {
       return false;
     }
   }
diff --git a/chrome/browser/autofill/captured_sites_test_utils.h b/chrome/browser/autofill/captured_sites_test_utils.h
index 61528c60..0d83d2a 100644
--- a/chrome/browser/autofill/captured_sites_test_utils.h
+++ b/chrome/browser/autofill/captured_sites_test_utils.h
@@ -11,6 +11,7 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/strings/strcat.h"
 #include "chrome/browser/ui/browser.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/test/browser_test_utils.h"
@@ -44,6 +45,34 @@
 
 std::string FilePathToUTF8(const base::FilePath::StringType& str);
 
+enum ExpectedResult { kPass, kFail };
+struct CapturedSiteParams {
+  std::string scenario_dir;
+  std::string site_name;
+  ExpectedResult expectation = kPass;
+  bool is_disabled = false;
+  base::FilePath capture_file_path;
+  base::FilePath recipe_file_path;
+
+  CapturedSiteParams();
+  ~CapturedSiteParams();
+  CapturedSiteParams(const CapturedSiteParams& other);
+};
+
+std::ostream& operator<<(std::ostream& os, const CapturedSiteParams& data);
+
+std::vector<CapturedSiteParams> GetCapturedSites(
+    const base::FilePath& replay_files_dir_path);
+
+struct GetParamAsString {
+  template <class ParamType>
+  std::string operator()(const testing::TestParamInfo<ParamType>& info) const {
+    if (info.param.scenario_dir.empty())
+      return info.param.site_name;
+    return base::StrCat({info.param.scenario_dir, "_", info.param.site_name});
+  }
+};
+
 // PageActivityObserver
 //
 // PageActivityObserver is a universal wait-for-page-ready object that ensures
@@ -225,6 +254,8 @@
   bool ReplayTest(const base::FilePath capture_file_path,
                   const base::FilePath recipe_file_path);
 
+  const std::vector<testing::AssertionResult> GetValidationFailures() const;
+
   static void SetUpCommandLine(base::CommandLine* command_line);
   static bool ScrollElementIntoView(const std::string& element_xpath,
                                     content::RenderFrameHost* frame);
@@ -253,6 +284,7 @@
       gfx::Rect* output_rect);
 
   Browser* browser();
+
   TestRecipeReplayChromeFeatureActionExecutor* feature_action_executor();
   content::WebContents* GetWebContents();
   void CleanupSiteData();
@@ -318,6 +350,7 @@
       const std::string& element_xpath,
       const std::string& get_property_function_body,
       const std::string& expected_value,
+      const std::string& validation_field,
       const bool ignoreCase = false);
   void NavigateAwayAndDismissBeforeUnloadDialog();
   bool HasChromeStoredCredential(const base::DictionaryValue& action,
@@ -329,6 +362,8 @@
   Browser* browser_;
   TestRecipeReplayChromeFeatureActionExecutor* feature_action_executor_;
 
+  std::vector<testing::AssertionResult> validation_failures_;
+
   // The Web Page Replay server that serves the captured sites.
   base::Process web_page_replay_server_;
 
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
index de250a50..e840667 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
@@ -111,34 +112,34 @@
   }
 
   void CreateCookiesForTest() {
-    net::CookieOptions options;
+    base::Optional<base::Time> server_time = base::nullopt;
     auto cookie1 = net::CanonicalCookie::Create(
-        GURL("https://www.google.com"), "A=1", base::Time::Now(), options);
+        GURL("https://www.google.com"), "A=1", base::Time::Now(), server_time);
     auto cookie2 =
         net::CanonicalCookie::Create(GURL("https://www.gmail.google.com"),
-                                     "B=1", base::Time::Now(), options);
+                                     "B=1", base::Time::Now(), server_time);
 
     network::mojom::CookieManager* cookie_manager =
         storage_partition()->GetCookieManagerForBrowserProcess();
-    cookie_manager->SetCanonicalCookie(*cookie1, "https", options,
+    cookie_manager->SetCanonicalCookie(*cookie1, "https", net::CookieOptions(),
                                        base::DoNothing());
-    cookie_manager->SetCanonicalCookie(*cookie2, "https", options,
+    cookie_manager->SetCanonicalCookie(*cookie2, "https", net::CookieOptions(),
                                        base::DoNothing());
   }
 
   void CreateCookiesForDomainCookieTest() {
-    net::CookieOptions options;
+    base::Optional<base::Time> server_time = base::nullopt;
     auto cookie1 = net::CanonicalCookie::Create(
-        GURL("https://www.google.com"), "A=1", base::Time::Now(), options);
+        GURL("https://www.google.com"), "A=1", base::Time::Now(), server_time);
     auto cookie2 = net::CanonicalCookie::Create(GURL("https://www.google.com"),
                                                 "A=2; Domain=.www.google.com ",
-                                                base::Time::Now(), options);
+                                                base::Time::Now(), server_time);
 
     network::mojom::CookieManager* cookie_manager =
         storage_partition()->GetCookieManagerForBrowserProcess();
-    cookie_manager->SetCanonicalCookie(*cookie1, "https", options,
+    cookie_manager->SetCanonicalCookie(*cookie1, "https", net::CookieOptions(),
                                        base::DoNothing());
-    cookie_manager->SetCanonicalCookie(*cookie2, "https", options,
+    cookie_manager->SetCanonicalCookie(*cookie2, "https", net::CookieOptions(),
                                        base::DoNothing());
   }
 
@@ -272,12 +273,12 @@
 
   const GURL origin1("http://www.google.com");
   std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
-      origin1, "A=1", base::Time::Now(), net::CookieOptions()));
+      origin1, "A=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   helper->AddChangedCookie(origin1, origin1, *cookie1);
   const GURL origin2("http://www.gmail.google.com");
   std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
-      origin2, "B=1", base::Time::Now(), net::CookieOptions()));
+      origin2, "B=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   helper->AddChangedCookie(origin2, origin2, *cookie2);
 
@@ -306,12 +307,12 @@
 
   ASSERT_TRUE(helper->empty());
   std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
-      origin, "A=1", base::Time::Now(), net::CookieOptions()));
+      origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   helper->AddChangedCookie(origin, origin, *cookie1);
-  std::unique_ptr<net::CanonicalCookie> cookie2(
-      net::CanonicalCookie::Create(origin, "A=1; Domain=.www.google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
+      origin, "A=1; Domain=.www.google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   helper->AddChangedCookie(origin, origin, *cookie2);
 
@@ -337,7 +338,7 @@
 
   ASSERT_TRUE(helper->empty());
   std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
-      origin, "A=1", base::Time::Now(), net::CookieOptions()));
+      origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie);
   helper->AddChangedCookie(origin, origin, *cookie);
   helper->AddChangedCookie(origin, origin, *cookie);
@@ -364,50 +365,52 @@
 
   ASSERT_TRUE(helper->empty());
   std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
-      origin, "A=1", base::Time::Now(), net::CookieOptions()));
+      origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   helper->AddChangedCookie(origin, origin, *cookie1);
   std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
-      origin, "A=2", base::Time::Now(), net::CookieOptions()));
+      origin, "A=2", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   helper->AddChangedCookie(origin, origin, *cookie2);
   std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
-      origin, "A=3; Path=/example/0", base::Time::Now(), net::CookieOptions()));
+      origin, "A=3; Path=/example/0", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie3);
   helper->AddChangedCookie(origin, origin, *cookie3);
   std::unique_ptr<net::CanonicalCookie> cookie4(net::CanonicalCookie::Create(
-      origin, "A=4; Path=/example/0", base::Time::Now(), net::CookieOptions()));
+      origin, "A=4; Path=/example/0", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie4);
   helper->AddChangedCookie(origin, origin, *cookie4);
-  std::unique_ptr<net::CanonicalCookie> cookie5(
-      net::CanonicalCookie::Create(origin, "A=5; Domain=google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie5(net::CanonicalCookie::Create(
+      origin, "A=5; Domain=google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie5);
   helper->AddChangedCookie(origin, origin, *cookie5);
-  std::unique_ptr<net::CanonicalCookie> cookie6(
-      net::CanonicalCookie::Create(origin, "A=6; Domain=google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie6(net::CanonicalCookie::Create(
+      origin, "A=6; Domain=google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie6);
   helper->AddChangedCookie(origin, origin, *cookie6);
   std::unique_ptr<net::CanonicalCookie> cookie7(net::CanonicalCookie::Create(
       origin, "A=7; Domain=google.com; Path=/example/1", base::Time::Now(),
-      net::CookieOptions()));
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie7);
   helper->AddChangedCookie(origin, origin, *cookie7);
   std::unique_ptr<net::CanonicalCookie> cookie8(net::CanonicalCookie::Create(
       origin, "A=8; Domain=google.com; Path=/example/1", base::Time::Now(),
-      net::CookieOptions()));
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie8);
   helper->AddChangedCookie(origin, origin, *cookie8);
 
-  std::unique_ptr<net::CanonicalCookie> cookie9(
-      net::CanonicalCookie::Create(origin, "A=9; Domain=www.google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie9(net::CanonicalCookie::Create(
+      origin, "A=9; Domain=www.google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie9);
   helper->AddChangedCookie(origin, origin, *cookie9);
-  std::unique_ptr<net::CanonicalCookie> cookie10(
-      net::CanonicalCookie::Create(origin, "A=10; Domain=www.google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie10(net::CanonicalCookie::Create(
+      origin, "A=10; Domain=www.google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie10);
   helper->AddChangedCookie(origin, origin, *cookie10);
 
@@ -435,7 +438,7 @@
   ASSERT_TRUE(helper->empty());
   std::unique_ptr<net::CanonicalCookie> changed_cookie(
       net::CanonicalCookie::Create(url_google, "a=1", base::Time::Now(),
-                                   net::CookieOptions()));
+                                   base::nullopt /* server_time */));
   ASSERT_TRUE(changed_cookie);
   helper->AddChangedCookie(url_google, url_google, *changed_cookie);
   ASSERT_FALSE(helper->empty());
@@ -444,7 +447,7 @@
 
   net::CookieList cookies;
   std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
-      url_google, "a=1", base::Time::Now(), net::CookieOptions()));
+      url_google, "a=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie);
   cookies.push_back(*cookie);
 
@@ -464,15 +467,15 @@
 
   ASSERT_TRUE(helper->empty());
   std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
-      request_url, "a=1", base::Time::Now(), net::CookieOptions()));
+      request_url, "a=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   helper->AddChangedCookie(frame1_url, request_url, *cookie1);
   std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
-      request_url, "b=1", base::Time::Now(), net::CookieOptions()));
+      request_url, "b=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   helper->AddChangedCookie(frame1_url, request_url, *cookie2);
   std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
-      request_url, "c=1", base::Time::Now(), net::CookieOptions()));
+      request_url, "c=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie3);
   helper->AddChangedCookie(frame2_url, request_url, *cookie3);
 
@@ -502,12 +505,12 @@
   // cookies.
   EXPECT_EQ(0U, helper->GetCookieCount());
   std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
-      frame1_url, "A=1", base::Time::Now(), net::CookieOptions()));
+      frame1_url, "A=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   helper->AddChangedCookie(frame1_url, frame1_url, *cookie1);
   EXPECT_EQ(1U, helper->GetCookieCount());
   std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
-      frame1_url, "B=1", base::Time::Now(), net::CookieOptions()));
+      frame1_url, "B=1", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   helper->AddChangedCookie(frame1_url, frame1_url, *cookie2);
   EXPECT_EQ(2U, helper->GetCookieCount());
@@ -518,7 +521,7 @@
   // request to |frame1_url| is updated.
   // The cookie-name of |cookie3| must match the cookie-name of |cookie1|.
   std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
-      frame1_url, "A=2", base::Time::Now(), net::CookieOptions()));
+      frame1_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie3);
   helper->AddChangedCookie(frame2_url, frame1_url, *cookie3);
   EXPECT_EQ(2U, helper->GetCookieCount());
@@ -527,12 +530,12 @@
   // below have a differnt path-value since the request URLs have different
   // paths.
   std::unique_ptr<net::CanonicalCookie> cookie4(net::CanonicalCookie::Create(
-      request1_url, "A=2", base::Time::Now(), net::CookieOptions()));
+      request1_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie4);
   helper->AddChangedCookie(frame2_url, request1_url, *cookie4);
   EXPECT_EQ(3U, helper->GetCookieCount());
   std::unique_ptr<net::CanonicalCookie> cookie5(net::CanonicalCookie::Create(
-      request2_url, "A=2", base::Time::Now(), net::CookieOptions()));
+      request2_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie5);
   helper->AddChangedCookie(frame2_url, request2_url, *cookie5);
   EXPECT_EQ(4U, helper->GetCookieCount());
@@ -543,9 +546,9 @@
   //   "A=1;
   //   "A=3; Domain=www.google.com"
   // Add a domain cookie and check if it increases the cookie count.
-  std::unique_ptr<net::CanonicalCookie> cookie6(
-      net::CanonicalCookie::Create(frame1_url, "A=3; Domain=.www.google.com",
-                                   base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cookie6(net::CanonicalCookie::Create(
+      frame1_url, "A=3; Domain=.www.google.com", base::Time::Now(),
+      base::nullopt /* server_time */));
   ASSERT_TRUE(cookie6);
   helper->AddChangedCookie(frame2_url, frame1_url, *cookie6);
   EXPECT_EQ(5U, helper->GetCookieCount());
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 5cd1aaa..80c45bd 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
@@ -284,11 +284,10 @@
 
   void AddCookie() {
     base::RunLoop run_loop;
-    net::CookieOptions options;
-    auto cookie = net::CanonicalCookie::Create(kOrigin1, "A=1",
-                                               base::Time::Now(), options);
+    auto cookie = net::CanonicalCookie::Create(
+        kOrigin1, "A=1", base::Time::Now(), base::nullopt /* server_time */);
     cookie_manager_->SetCanonicalCookie(
-        *cookie, "http", options,
+        *cookie, "http", net::CookieOptions(),
         base::BindLambdaForTesting(
             [&](net::CanonicalCookie::CookieInclusionStatus result) {
               EXPECT_EQ(net::CanonicalCookie::CookieInclusionStatus::INCLUDE,
diff --git a/chrome/browser/browsing_data/mock_browsing_data_cookie_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_cookie_helper.cc
index 44e618b..5f79dd0 100644
--- a/chrome/browser/browsing_data/mock_browsing_data_cookie_helper.cc
+++ b/chrome/browser/browsing_data/mock_browsing_data_cookie_helper.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/logging.h"
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/time/time.h"
 #include "chrome/browser/profiles/profile.h"
@@ -37,7 +38,7 @@
 void MockBrowsingDataCookieHelper::AddCookieSamples(
     const GURL& url, const std::string& cookie_line) {
   std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-      url, cookie_line, base::Time::Now(), net::CookieOptions()));
+      url, cookie_line, base::Time::Now(), base::nullopt /* server_time */));
 
   if (cc.get()) {
     for (const auto& cookie : cookie_list_) {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8baa99ff..9bf0dad 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -529,6 +529,7 @@
 #include "chrome/browser/apps/platform_apps/platform_app_navigation_redirector.h"
 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
+#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/user_script_listener.h"
 #include "chrome/browser/media/cast_transport_host_filter.h"
 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
@@ -543,7 +544,6 @@
 #include "extensions/browser/extension_protocols.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
-#include "extensions/browser/extension_util.h"
 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
index 0013d07..663ee5c 100644
--- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -55,6 +55,7 @@
 #include "chrome/browser/chromeos/policy/external_data_handlers/print_servers_external_data_handler.h"
 #include "chrome/browser/chromeos/policy/external_data_handlers/user_avatar_image_external_data_handler.h"
 #include "chrome/browser/chromeos/policy/external_data_handlers/wallpaper_image_external_data_handler.h"
+#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/session_length_limiter.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -286,12 +287,11 @@
   return false;
 }
 
-bool AreForcedNetworkCertificatesInstalled() {
-  return !g_browser_process->platform_part()
-              ->browser_policy_connector_chromeos()
-              ->GetDeviceNetworkConfigurationUpdater()
-              ->GetAllAuthorityCertificates()
-              .empty();
+bool PolicyHasWebTrustedAuthorityCertificate(
+    policy::DeviceLocalAccountPolicyBroker* broker) {
+  return policy::UserNetworkConfigurationUpdater::
+      PolicyHasWebTrustedAuthorityCertificate(
+          broker->core()->store()->policy_map());
 }
 
 }  // namespace
@@ -1437,7 +1437,7 @@
   return IsManagedSessionEnabled(broker) &&
          (AreRiskyPoliciesUsed(broker) ||
           AreRiskyExtensionsForceInstalled(broker) ||
-          AreForcedNetworkCertificatesInstalled() ||
+          PolicyHasWebTrustedAuthorityCertificate(broker) ||
           IsProxyUsed(GetLocalState()));
 }
 
diff --git a/chrome/browser/chromeos/network_change_manager_client.cc b/chrome/browser/chromeos/network_change_manager_client.cc
index c3800e7c..692365e 100644
--- a/chrome/browser/chromeos/network_change_manager_client.cc
+++ b/chrome/browser/chromeos/network_change_manager_client.cc
@@ -207,8 +207,6 @@
     return net::NetworkChangeNotifier::CONNECTION_ETHERNET;
   if (type == shill::kTypeWifi)
     return net::NetworkChangeNotifier::CONNECTION_WIFI;
-  if (type == shill::kTypeWimax)
-    return net::NetworkChangeNotifier::CONNECTION_4G;
   if (type == shill::kTypeBluetooth)
     return net::NetworkChangeNotifier::CONNECTION_BLUETOOTH;
 
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
index 680768a..ead84f1 100644
--- a/chrome/browser/chromeos/network_change_manager_client_unittest.cc
+++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -73,7 +73,6 @@
   TypeMapping type_mappings[] = {
       {shill::kTypeEthernet, "", NetworkChangeNotifier::CONNECTION_ETHERNET},
       {shill::kTypeWifi, "", NetworkChangeNotifier::CONNECTION_WIFI},
-      {shill::kTypeWimax, "", NetworkChangeNotifier::CONNECTION_4G},
       {"unknown type", "unknown technology",
        NetworkChangeNotifier::CONNECTION_UNKNOWN},
       {shill::kTypeCellular, shill::kNetworkTechnology1Xrtt,
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 05499da..dc8f6cc 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -2545,11 +2545,13 @@
 IN_PROC_BROWSER_TEST_F(ManagedSessionsTest, NetworkCertificate) {
   SetManagedSessionsEnabled(/* managed_sessions_enabled */ true);
 
-  // Install and refresh the device policy now. This will also fetch the initial
-  // user policy for the device-local account now.
+  device_local_account_policy_.payload()
+      .mutable_opennetworkconfiguration()
+      ->set_value(kFakeOncWithCertificate);
+
   UploadAndInstallDeviceLocalAccountPolicy();
   AddPublicSessionToDevicePolicy(kAccountId1);
-  AddNetworkCertificateToDevicePolicy();
+
   WaitForPolicy();
 
   const user_manager::User* user =
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 2086a856..be8a9f2 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -115,15 +115,19 @@
 }
 
 std::unique_ptr<base::Value> DecodeConnectionType(int value) {
-  static const char* const kConnectionTypes[] = {
-      shill::kTypeEthernet,  shill::kTypeWifi,     shill::kTypeWimax,
-      shill::kTypeBluetooth, shill::kTypeCellular,
+  const std::map<int, std::string> kConnectionTypes = {
+      {em::AutoUpdateSettingsProto::CONNECTION_TYPE_ETHERNET,
+       shill::kTypeEthernet},
+      {em::AutoUpdateSettingsProto::CONNECTION_TYPE_WIFI, shill::kTypeWifi},
+      {em::AutoUpdateSettingsProto::CONNECTION_TYPE_BLUETOOTH,
+       shill::kTypeBluetooth},
+      {em::AutoUpdateSettingsProto::CONNECTION_TYPE_CELLULAR,
+       shill::kTypeCellular},
   };
-
-  if (value < 0 || value >= static_cast<int>(base::size(kConnectionTypes)))
+  const auto iter = kConnectionTypes.find(value);
+  if (iter == kConnectionTypes.end())
     return nullptr;
-
-  return std::make_unique<base::Value>(kConnectionTypes[value]);
+  return std::make_unique<base::Value>(iter->second);
 }
 
 void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy,
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater.cc b/chrome/browser/chromeos/policy/network_configuration_updater.cc
index 6b09eec0..d36f6d1 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater.cc
@@ -172,6 +172,35 @@
       global_network_config, certificates);
 }
 
+// static
+bool NetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+    const PolicyMap& policy_map,
+    onc::ONCSource onc_source,
+    const std::string& policy_key) {
+  const base::Value* policy_value = policy_map.GetValue(policy_key);
+
+  if (!policy_value || policy_value->type() != base::Value::Type::STRING)
+    return false;
+
+  base::ListValue certificates_value;
+  chromeos::onc::ParseAndValidateOncForImport(
+      policy_value->GetString(), onc_source, /*passphrase=*/std::string(),
+      /*network_configs=*/nullptr, /*global_network_config=*/nullptr,
+      &certificates_value);
+  chromeos::onc::OncParsedCertificates onc_parsed_certificates(
+      certificates_value);
+  for (const auto& server_or_authority_cert :
+       onc_parsed_certificates.server_or_authority_certificates()) {
+    if (server_or_authority_cert.type() ==
+            OncParsedCertificates::ServerOrAuthorityCertificate::Type::
+                kAuthority &&
+        server_or_authority_cert.web_trust_requested()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 const std::vector<OncParsedCertificates::ClientCertificate>&
 NetworkConfigurationUpdater::GetClientCertificates() const {
   return certs_->client_certificates();
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater.h b/chrome/browser/chromeos/policy/network_configuration_updater.h
index 5639710..fde3f45 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater.h
+++ b/chrome/browser/chromeos/policy/network_configuration_updater.h
@@ -91,6 +91,14 @@
                           base::DictionaryValue* global_network_config,
                           base::ListValue* certificates);
 
+  // Determines if |policy_map| contains an ONC policy under |policy_key| that
+  // mandates that at least one additional certificate should be used and
+  // assignd 'Web' trust.
+  static bool PolicyHasWebTrustedAuthorityCertificate(
+      const PolicyMap& policy_map,
+      onc::ONCSource onc_source,
+      const std::string& policy_key);
+
   const std::vector<chromeos::onc::OncParsedCertificates::ClientCertificate>&
   GetClientCertificates() const;
 
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
index ee27c6ee..9c3cff9e 100644
--- a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
+++ b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
@@ -667,6 +667,97 @@
   MarkPolicyProviderInitialized();
 }
 
+TEST(UserNetworkConfigurationStaticsTest, TestHasWebTrustedCertsNo) {
+  const char kONCWithoutWebTrustedCert[] = R"(
+    { "Certificates": [
+        { "GUID": "{d443ad0d-ea16-4301-9089-588115e2f5c4}",
+          "Type": "Authority",
+          "X509": "-----BEGIN CERTIFICATE-----\n
+    MIIC8zCCAdugAwIBAgIJALF9qhLor0+aMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV\n
+    BAMMDFRlc3QgUm9vdCBDQTAeFw0xNDA4MTQwMzA1MjlaFw0yNDA4MTEwMzA1Mjla\n
+    MBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\n
+    ADCCAQoCggEBALZJQeNCAVGofzx6cdP7zZE1F4QajvY2x9FwHfqG8267dm/oMi43\n
+    /TiSPWjkin1CMxRGG9wE9pFuVEDECgn97C1i4l7huiycwbFgTNrH+CJcgiBlQh5W\n
+    d3VP65AsSupXDiKNbJWsEerM1+72cA0J3aY1YV3Jdm2w8h6/MIbYd1I2lZcO0UbF\n
+    7YE9G7DyYZU8wUA4719dumGf7yucn4WJdHBj1XboNX7OAeHzERGQHA31/Y3OEGyt\n
+    fFUaIW/XLfR4FeovOL2RnjwdB0b1Q8GCi68SU2UZimlpZgay2gv6KgChKhWESfEB\n
+    v5swBtAVoB+dUZFH4VNf717swmF5whSfxOMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw\n
+    AwEB/zAdBgNVHQ4EFgQUvPcw0TzA8nn675/JbFyT84poq4MwDgYDVR0PAQH/BAQD\n
+    AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBXByn7f+j/sObYWGrDkKE4HLTzaLHs6Ikj\n
+    JNeo8iHDYOSkSVwAv9/HgniAKxj3rd3QYl6nsMzwqrTOcBJZZWd2BQAYmv/EKhfj\n
+    8VXYvlxe68rLU4cQ1QkyNqdeQfRT2n5WYNJ+TpqlCF9ddennMMsi6e8ZSYOlI6H4\n
+    YEzlNtU5eBjxXr/OqgtTgSx4qQpr2xMQIRR/G3A9iRpAigYsXVAZYvnHRYnyPWYF\n
+    PX11W1UegEJyoZp8bQp09u6mIWw6mPt3gl/ya1bm3ZuOUPDGrv3qpgUHqSYGVrOy\n
+    2bI3oCE+eQYfuVG+9LFJTZC1M+UOx15bQMVqBNFDepRqpE9h/ILg\n
+    -----END CERTIFICATE-----" }
+      ],
+      "Type": "UnencryptedConfiguration"
+    })";
+  PolicyMap policy;
+  policy.Set(key::kOpenNetworkConfiguration, POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+             std::make_unique<base::Value>(kONCWithoutWebTrustedCert), nullptr);
+  EXPECT_FALSE(
+      UserNetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+          policy));
+}
+
+TEST(UserNetworkConfigurationStaticsTest, TestHasWebTrustedCertsYes) {
+  const char kONCWithWebTrustedCert[] = R"(
+    { "Certificates": [
+        { "GUID": "{d443ad0d-ea16-4301-9089-588115e2f5c4}",
+          "TrustBits": [
+             "Web"
+          ],
+          "Type": "Authority",
+          "X509": "-----BEGIN CERTIFICATE-----\n
+    MIIC8zCCAdugAwIBAgIJALF9qhLor0+aMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV\n
+    BAMMDFRlc3QgUm9vdCBDQTAeFw0xNDA4MTQwMzA1MjlaFw0yNDA4MTEwMzA1Mjla\n
+    MBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP\n
+    ADCCAQoCggEBALZJQeNCAVGofzx6cdP7zZE1F4QajvY2x9FwHfqG8267dm/oMi43\n
+    /TiSPWjkin1CMxRGG9wE9pFuVEDECgn97C1i4l7huiycwbFgTNrH+CJcgiBlQh5W\n
+    d3VP65AsSupXDiKNbJWsEerM1+72cA0J3aY1YV3Jdm2w8h6/MIbYd1I2lZcO0UbF\n
+    7YE9G7DyYZU8wUA4719dumGf7yucn4WJdHBj1XboNX7OAeHzERGQHA31/Y3OEGyt\n
+    fFUaIW/XLfR4FeovOL2RnjwdB0b1Q8GCi68SU2UZimlpZgay2gv6KgChKhWESfEB\n
+    v5swBtAVoB+dUZFH4VNf717swmF5whSfxOMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw\n
+    AwEB/zAdBgNVHQ4EFgQUvPcw0TzA8nn675/JbFyT84poq4MwDgYDVR0PAQH/BAQD\n
+    AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBXByn7f+j/sObYWGrDkKE4HLTzaLHs6Ikj\n
+    JNeo8iHDYOSkSVwAv9/HgniAKxj3rd3QYl6nsMzwqrTOcBJZZWd2BQAYmv/EKhfj\n
+    8VXYvlxe68rLU4cQ1QkyNqdeQfRT2n5WYNJ+TpqlCF9ddennMMsi6e8ZSYOlI6H4\n
+    YEzlNtU5eBjxXr/OqgtTgSx4qQpr2xMQIRR/G3A9iRpAigYsXVAZYvnHRYnyPWYF\n
+    PX11W1UegEJyoZp8bQp09u6mIWw6mPt3gl/ya1bm3ZuOUPDGrv3qpgUHqSYGVrOy\n
+    2bI3oCE+eQYfuVG+9LFJTZC1M+UOx15bQMVqBNFDepRqpE9h/ILg\n
+    -----END CERTIFICATE-----" }
+      ],
+      "Type": "UnencryptedConfiguration"
+    })";
+  PolicyMap policy;
+  policy.Set(key::kOpenNetworkConfiguration, POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+             std::make_unique<base::Value>(kONCWithWebTrustedCert), nullptr);
+  EXPECT_TRUE(
+      UserNetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+          policy));
+}
+
+TEST(UserNetworkConfigurationStaticsTest, TestHasWebTrustedCertsNoPolicy) {
+  PolicyMap policy;
+  EXPECT_FALSE(
+      UserNetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+          policy));
+}
+
+TEST(UserNetworkConfigurationStaticsTest, TestHasWebTrustedCertsInvalidPolicy) {
+  const char kInvalidONC[] = "not even valid json";
+  PolicyMap policy;
+  policy.Set(key::kOpenNetworkConfiguration, POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
+             std::make_unique<base::Value>(kInvalidONC), nullptr);
+  EXPECT_FALSE(
+      UserNetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+          policy));
+}
+
 class NetworkConfigurationUpdaterTestWithParam
     : public NetworkConfigurationUpdaterTest,
       public testing::WithParamInterface<const char*> {
diff --git a/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc b/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
index ebd8b0a..b4a7eda 100644
--- a/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
@@ -12,17 +12,23 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/version_info/version_info.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_util.h"
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/features/feature_channel.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace content {
+class StoragePartition;
+}
+
 namespace policy {
 
 namespace {
@@ -135,6 +141,15 @@
     SigninProfileExtensionsPolicyPerChannelTest()
     : SigninProfileExtensionsPolicyTestBase(GetParam()) {}
 
+content::StoragePartition* GetStoragePartitionForSigninExtension(
+    Profile* profile,
+    const std::string& extension_id) {
+  const GURL site =
+      extensions::util::GetSiteForExtensionId(extension_id, profile);
+  return content::BrowserContext::GetStoragePartitionForSite(
+      profile, site, /*can_create=*/false);
+}
+
 }  // namespace
 
 // Tests that a whitelisted app gets installed on any browser channel.
@@ -312,4 +327,38 @@
   registry_observer2.WaitForExtensionLoaded();
 }
 
+// Tests that a sign-in profile app or a sign-in profile extension has isolated
+// storage, i.e. that it does not reuse the Profile's default StoragePartition.
+IN_PROC_BROWSER_TEST_F(SigninProfileExtensionsPolicyTest,
+                       IsolatedStoragePartition) {
+  Profile* profile = GetInitialProfile();
+
+  ExtensionBackgroundPageReadyObserver page_observer_for_app(kWhitelistedAppId);
+  ExtensionBackgroundPageReadyObserver page_observer_for_extension(
+      kWhitelistedExtensionId);
+
+  AddExtensionForForceInstallation(kWhitelistedAppId,
+                                   kWhitelistedAppUpdateManifestPath);
+  AddExtensionForForceInstallation(kWhitelistedExtensionId,
+                                   kWhitelistedExtensionUpdateManifestPath);
+
+  page_observer_for_app.Wait();
+  page_observer_for_extension.Wait();
+
+  content::StoragePartition* storage_partition_for_app =
+      GetStoragePartitionForSigninExtension(profile, kWhitelistedAppId);
+  content::StoragePartition* storage_partition_for_extension =
+      GetStoragePartitionForSigninExtension(profile, kWhitelistedExtensionId);
+  content::StoragePartition* default_storage_partition =
+      content::BrowserContext::GetDefaultStoragePartition(profile);
+
+  ASSERT_TRUE(storage_partition_for_app);
+  ASSERT_TRUE(storage_partition_for_extension);
+  ASSERT_TRUE(default_storage_partition);
+
+  EXPECT_NE(default_storage_partition, storage_partition_for_app);
+  EXPECT_NE(default_storage_partition, storage_partition_for_extension);
+  EXPECT_NE(storage_partition_for_app, storage_partition_for_extension);
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
index ed45477..420bfb0 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -1480,10 +1480,6 @@
           em::NetworkInterface::TYPE_WIFI,
       },
       {
-          shill::kTypeWimax,
-          em::NetworkInterface::TYPE_WIMAX,
-      },
-      {
           shill::kTypeBluetooth,
           em::NetworkInterface::TYPE_BLUETOOTH,
       },
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index 40d52cf..92857cff 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -1617,22 +1617,20 @@
       crostini::prefs::kCrostiniLastLaunchTerminaKernelVersion,
       kTerminaVmKernelVersion);
 
-  // Check that nothing is reported when the feature flag is not enabled:
+  // Check that the kernel version is reported as to the feature flag default:
+  GetStatus();
+  EXPECT_TRUE(got_session_status_);
+  EXPECT_EQ(kTerminaVmKernelVersion,
+            session_status_.crostini_status().last_launch_vm_kernel_version());
+
+  // Check that nothing is reported when the feature flag is disabled:
+  scoped_feature_list_.InitAndDisableFeature(
+      features::kCrostiniAdditionalEnterpriseReporting);
   GetStatus();
   EXPECT_TRUE(got_session_status_);
   EXPECT_TRUE(session_status_.crostini_status()
                   .last_launch_vm_kernel_version()
                   .empty());
-
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kCrostiniAdditionalEnterpriseReporting);
-
-  // Check that the kernel version is reported now that the feature flag is
-  // enabled:
-  GetStatus();
-  EXPECT_TRUE(got_session_status_);
-  EXPECT_EQ(kTerminaVmKernelVersion,
-            session_status_.crostini_status().last_launch_vm_kernel_version());
 }
 
 TEST_F(DeviceStatusCollectorTest, CrostiniAppUsageReporting) {
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
index 41fff31..f84e0f2 100644
--- a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
@@ -58,6 +58,13 @@
   SetClientCertificateImporter(std::move(client_certificate_importer));
 }
 
+// static
+bool UserNetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+    const PolicyMap& policy_map) {
+  return NetworkConfigurationUpdater::PolicyHasWebTrustedAuthorityCertificate(
+      policy_map, onc::ONC_SOURCE_USER_POLICY, key::kOpenNetworkConfiguration);
+}
+
 UserNetworkConfigurationUpdater::UserNetworkConfigurationUpdater(
     Profile* profile,
     bool allow_trusted_certs_from_policy,
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.h b/chrome/browser/chromeos/policy/user_network_configuration_updater.h
index 07848b86..9d7270cf 100644
--- a/chrome/browser/chromeos/policy/user_network_configuration_updater.h
+++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.h
@@ -43,6 +43,7 @@
 
 namespace policy {
 
+class PolicyMap;
 class PolicyService;
 
 // Implements additional special handling of ONC user policies. Namely string
@@ -73,6 +74,12 @@
   void SetClientCertificateImporterForTest(
       std::unique_ptr<chromeos::onc::CertificateImporter> certificate_importer);
 
+  // Determines if |policy_map| contains a OpenNetworkConfiguration policy that
+  // mandates that at least one additional certificate should be used and
+  // assignd 'Web' trust.
+  static bool PolicyHasWebTrustedAuthorityCertificate(
+      const PolicyMap& policy_map);
+
  private:
   class CrosTrustAnchorProvider;
 
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 52a31be..c7cae63 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -45,14 +45,6 @@
 
 const char kDisabledMessage[] = "This device has been disabled.";
 
-constexpr em::AutoUpdateSettingsProto_ConnectionType kConnectionTypes[] = {
-    em::AutoUpdateSettingsProto::CONNECTION_TYPE_ETHERNET,
-    em::AutoUpdateSettingsProto::CONNECTION_TYPE_WIFI,
-    em::AutoUpdateSettingsProto::CONNECTION_TYPE_WIMAX,
-    em::AutoUpdateSettingsProto::CONNECTION_TYPE_BLUETOOTH,
-    em::AutoUpdateSettingsProto::CONNECTION_TYPE_CELLULAR,
-};
-
 }  // namespace
 
 class DeviceSettingsProviderTest : public DeviceSettingsTestBase {
@@ -217,12 +209,13 @@
   }
 
   // Helper routine to set AutoUpdates connection types policy.
-  void SetAutoUpdateConnectionTypes(const std::vector<int>& values) {
+  void SetAutoUpdateConnectionTypes(
+      const std::vector<em::AutoUpdateSettingsProto::ConnectionType>& values) {
     em::AutoUpdateSettingsProto* proto =
         device_policy_->payload().mutable_auto_update_settings();
     proto->set_update_disabled(false);
     for (auto const& value : values) {
-      proto->add_allowed_connection_types(kConnectionTypes[value]);
+      proto->add_allowed_connection_types(value);
     }
     BuildAndInstallDevicePolicy();
   }
@@ -631,11 +624,12 @@
   VerifyPolicyValue(kAllowedConnectionTypesForUpdate, nullptr);
 
   // In case of empty list policy should not be set.
-  const std::vector<int> no_values = {};
+  const std::vector<em::AutoUpdateSettingsProto::ConnectionType> no_values = {};
   SetAutoUpdateConnectionTypes(no_values);
   VerifyPolicyValue(kAllowedConnectionTypesForUpdate, nullptr);
 
-  const std::vector<int> single_value = {0};
+  const std::vector<em::AutoUpdateSettingsProto::ConnectionType> single_value =
+      {em::AutoUpdateSettingsProto::CONNECTION_TYPE_ETHERNET};
   // Check some meaningful value. Policy should be set.
   SetAutoUpdateConnectionTypes(single_value);
   base::ListValue allowed_connections;
diff --git a/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc b/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
index 75f1e57..8d660db4 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
+++ b/chrome/browser/content_settings/tab_specific_content_settings_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -49,7 +50,6 @@
 TEST_F(TabSpecificContentSettingsTest, BlockedContent) {
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents());
-  net::CookieOptions options;
 
   // Check that after initializing, nothing is blocked.
 #if !defined(OS_ANDROID)
@@ -73,8 +73,8 @@
   // Set a cookie, block access to images, block mediastream access and block a
   // popup.
   GURL origin("http://google.com");
-  std::unique_ptr<net::CanonicalCookie> cookie1(
-      net::CanonicalCookie::Create(origin, "A=B", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
+      origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   web_contents()->OnCookieChange(origin, origin, *cookie1, false);
 #if !defined(OS_ANDROID)
@@ -113,8 +113,8 @@
   web_contents()->OnCookieChange(origin, origin, *cookie1, false);
 
   // Block a cookie.
-  std::unique_ptr<net::CanonicalCookie> cookie2(
-      net::CanonicalCookie::Create(origin, "C=D", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
+      origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   web_contents()->OnCookieChange(origin, origin, *cookie2, true);
   EXPECT_TRUE(
@@ -183,7 +183,6 @@
 TEST_F(TabSpecificContentSettingsTest, AllowedContent) {
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents());
-  net::CookieOptions options;
 
   // Test default settings.
   ASSERT_FALSE(
@@ -199,8 +198,8 @@
 
   // Record a cookie.
   GURL origin("http://google.com");
-  std::unique_ptr<net::CanonicalCookie> cookie1(
-      net::CanonicalCookie::Create(origin, "A=B", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
+      origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie1);
   web_contents()->OnCookieChange(origin, origin, *cookie1, false);
   ASSERT_TRUE(
@@ -209,8 +208,8 @@
       content_settings->IsContentBlocked(CONTENT_SETTINGS_TYPE_COOKIES));
 
   // Record a blocked cookie.
-  std::unique_ptr<net::CanonicalCookie> cookie2(
-      net::CanonicalCookie::Create(origin, "C=D", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
+      origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie2);
   web_contents()->OnCookieChange(origin, origin, *cookie2, true);
   ASSERT_TRUE(
@@ -243,10 +242,9 @@
   EXPECT_CALL(mock_observer, OnSiteDataAccessed()).Times(6);
 
   bool blocked_by_policy = false;
-  net::CookieOptions options;
   GURL origin("http://google.com");
-  std::unique_ptr<net::CanonicalCookie> cookie(
-      net::CanonicalCookie::Create(origin, "A=B", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
+      origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie);
   web_contents()->OnCookieChange(origin, origin, *cookie, blocked_by_policy);
 
@@ -254,7 +252,7 @@
   std::unique_ptr<net::CanonicalCookie> other_cookie(
       net::CanonicalCookie::Create(GURL("http://google.com"),
                                    "CookieName=CookieValue", base::Time::Now(),
-                                   net::CookieOptions()));
+                                   base::nullopt /* server_time */));
   ASSERT_TRUE(other_cookie);
 
   cookie_list.push_back(*other_cookie);
@@ -276,9 +274,9 @@
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents());
   bool blocked_by_policy = false;
-  auto cookie =
-      net::CanonicalCookie::Create(GURL("http://google.com"), "k=v",
-                                   base::Time::Now(), net::CookieOptions());
+  auto cookie = net::CanonicalCookie::Create(GURL("http://google.com"), "k=v",
+                                             base::Time::Now(),
+                                             base::nullopt /* server_time */);
   web_contents()->OnCookiesRead(GURL("http://google.com"),
                                 GURL("http://google.com"), {*cookie},
                                 blocked_by_policy);
@@ -309,25 +307,25 @@
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents());
   bool blocked_by_policy = false;
-  auto cookie1 =
-      net::CanonicalCookie::Create(GURL("http://google.com"), "k1=v",
-                                   base::Time::Now(), net::CookieOptions());
+  auto cookie1 = net::CanonicalCookie::Create(GURL("http://google.com"), "k1=v",
+                                              base::Time::Now(),
+                                              base::nullopt /* server_time */);
   auto cookie2 = net::CanonicalCookie::Create(
       GURL("http://www.google.com"), "k2=v; Domain=google.com",
-      base::Time::Now(), net::CookieOptions());
+      base::Time::Now(), base::nullopt /* server_time */);
   auto cookie3 = net::CanonicalCookie::Create(
       GURL("http://www.google.com"), "k3=v; Domain=.google.com",
-      base::Time::Now(), net::CookieOptions());
+      base::Time::Now(), base::nullopt /* server_time */);
   auto cookie4 = net::CanonicalCookie::Create(
       GURL("http://www.google.com"), "k4=v; Domain=.www.google.com",
-      base::Time::Now(), net::CookieOptions());
+      base::Time::Now(), base::nullopt /* server_time */);
   web_contents()->OnCookiesRead(
       GURL("http://www.google.com"), GURL("http://www.google.com"),
       {*cookie1, *cookie2, *cookie3, *cookie4}, blocked_by_policy);
 
-  auto cookie5 =
-      net::CanonicalCookie::Create(GURL("https://www.google.com"), "k5=v",
-                                   base::Time::Now(), net::CookieOptions());
+  auto cookie5 = net::CanonicalCookie::Create(GURL("https://www.google.com"),
+                                              "k5=v", base::Time::Now(),
+                                              base::nullopt /* server_time */);
   web_contents()->OnCookiesRead(GURL("https://www.google.com"),
                                 GURL("https://www.google.com"), {*cookie5},
                                 blocked_by_policy);
diff --git a/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
index 39c5cf0..78b98a5 100644
--- a/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_enabled_unittest.cc
@@ -37,8 +37,7 @@
 };
 
 TEST_F(ActivityLogEnabledTest, NoSwitch) {
-  std::unique_ptr<TestingProfile> profile(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile(CreateTestingProfile());
   EXPECT_FALSE(
       profile->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive));
 
@@ -51,10 +50,8 @@
 }
 
 TEST_F(ActivityLogEnabledTest, CommandLineSwitch) {
-  std::unique_ptr<TestingProfile> profile1(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
-  std::unique_ptr<TestingProfile> profile2(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile1(CreateTestingProfile());
+  std::unique_ptr<TestingProfile> profile2(CreateTestingProfile());
 
   ActivityLog* activity_log1;
   {
@@ -76,12 +73,9 @@
 }
 
 TEST_F(ActivityLogEnabledTest, PrefSwitch) {
-  std::unique_ptr<TestingProfile> profile1(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
-  std::unique_ptr<TestingProfile> profile2(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
-  std::unique_ptr<TestingProfile> profile3(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile1(CreateTestingProfile());
+  std::unique_ptr<TestingProfile> profile2(CreateTestingProfile());
+  std::unique_ptr<TestingProfile> profile3(CreateTestingProfile());
 
   EXPECT_EQ(0,
       profile1->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive));
@@ -112,10 +106,8 @@
 
 TEST_F(ActivityLogEnabledTest, WatchdogSwitch) {
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  std::unique_ptr<TestingProfile> profile1(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
-  std::unique_ptr<TestingProfile> profile2(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile1(CreateTestingProfile());
+  std::unique_ptr<TestingProfile> profile2(CreateTestingProfile());
   // Extension service is destroyed by the profile.
   ExtensionService* extension_service1 =
     static_cast<TestExtensionSystem*>(
@@ -219,8 +211,7 @@
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableExtensionActivityLogging);
 
-  std::unique_ptr<TestingProfile> profile(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile(CreateTestingProfile());
   // Extension service is destroyed by the profile.
   base::CommandLine no_program_command_line(base::CommandLine::NO_PROGRAM);
   ExtensionService* extension_service =
@@ -270,8 +261,7 @@
 // Tests that if the cached count in the profile preferences is incorrect, the
 // activity log will correct itself.
 TEST_F(ActivityLogEnabledTest, IncorrectPrefsRecovery) {
-  std::unique_ptr<TestingProfile> profile(
-      static_cast<TestingProfile*>(CreateBrowserContext()));
+  std::unique_ptr<TestingProfile> profile(CreateTestingProfile());
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   ExtensionService* extension_service =
     static_cast<TestExtensionSystem*>(
diff --git a/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
index fbfc993..2850af0e 100644
--- a/chrome/browser/extensions/api/cookies/cookies_unittest.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/cookies/cookies_api_constants.h"
@@ -186,9 +187,9 @@
 
 TEST_F(ExtensionCookiesTest, DecodeUTF8WithErrorHandling) {
   std::unique_ptr<net::CanonicalCookie> canonical_cookie(
-      net::CanonicalCookie::Create(GURL("http://test.com"),
-                                   "=011Q255bNX_1!yd\203e+;path=/path\203",
-                                   base::Time::Now(), net::CookieOptions()));
+      net::CanonicalCookie::Create(
+          GURL("http://test.com"), "=011Q255bNX_1!yd\203e+;path=/path\203",
+          base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_NE(nullptr, canonical_cookie.get());
   Cookie cookie =
       cookies_helpers::CreateCookie(*canonical_cookie, "some cookie store");
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index d8121216..bedfe82 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -363,9 +363,6 @@
     // Sends a notification about the added profile.
     profile_test_->AddProfile(kUser1ProfilePath, userhash_);
 
-    // Enable technologies.
-    manager_test_->AddTechnology("wimax", true);
-
     // Add IPConfigs
     base::DictionaryValue ipconfig;
     ipconfig.SetKey(shill::kAddressProperty, base::Value("0.0.0.0"));
@@ -442,15 +439,6 @@
         kWifi2ServicePath, shill::kTetheringProperty,
         base::Value(shill::kTetheringNotDetectedState));
 
-    AddService("stub_wimax", "wimax", shill::kTypeWimax, shill::kStateOnline);
-    service_test_->SetServiceProperty(
-        "stub_wimax", shill::kSignalStrengthProperty, base::Value(40));
-    service_test_->SetServiceProperty("stub_wimax", shill::kProfileProperty,
-                                      base::Value(kUser1ProfilePath));
-    service_test_->SetServiceProperty("stub_wimax", shill::kConnectableProperty,
-                                      base::Value(true));
-    profile_test_->AddService(kUser1ProfilePath, "stub_wimax");
-
     base::ListValue frequencies2;
     frequencies2.AppendInteger(2400);
     frequencies2.AppendInteger(5000);
@@ -573,8 +561,6 @@
   manager_test_->RemoveTechnology("cellular");
   manager_test_->AddTechnology("cellular", false /* disabled */);
   manager_test_->SetTechnologyInitializing("cellular", true);
-  manager_test_->RemoveTechnology("wimax");
-  manager_test_->AddTechnology("wimax", false /* disabled */);
   EXPECT_TRUE(RunNetworkingSubtest("getDeviceStates")) << message_;
 }
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 1696559..6038117b 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4907,9 +4907,9 @@
       extensions::ChromeExtensionCookies::Get(profile())
           ->GetCookieStoreForTesting();
   ASSERT_TRUE(cookie_store);
-  net::CookieOptions options;
   cookie_store->SetCookieWithOptionsAsync(
-      ext_url, "dummy=value", options,
+      ext_url, "dummy=value", net::CookieOptions(),
+      base::nullopt /* server_time */,
       base::BindOnce(&ExtensionCookieCallback::SetCookieCallback,
                      base::Unretained(&callback)));
   content::RunAllTasksUntilIdle();
@@ -5041,8 +5041,9 @@
   network::mojom::CookieManagerPtr cookie_manager_ptr;
   network_context->GetCookieManager(mojo::MakeRequest(&cookie_manager_ptr));
 
-  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-      origin1, "dummy=value", base::Time::Now(), net::CookieOptions()));
+  std::unique_ptr<net::CanonicalCookie> cc(
+      net::CanonicalCookie::Create(origin1, "dummy=value", base::Time::Now(),
+                                   base::nullopt /* server_time */));
   ASSERT_TRUE(cc.get());
 
   {
diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc
index 3fb8b048..f8f3933 100644
--- a/chrome/browser/extensions/extension_util.cc
+++ b/chrome/browser/extensions/extension_util.cc
@@ -47,6 +47,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/file_manager/app_id.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #endif
 
 namespace extensions {
@@ -79,6 +80,25 @@
 
 }  // namespace
 
+bool SiteHasIsolatedStorage(const GURL& extension_site_url,
+                            content::BrowserContext* context) {
+  const Extension* extension = ExtensionRegistry::Get(context)
+                                   ->enabled_extensions()
+                                   .GetExtensionOrAppByURL(extension_site_url);
+
+#if defined(OS_CHROMEOS)
+  const bool is_policy_extension =
+      extension && Manifest::IsPolicyLocation(extension->location());
+  Profile* profile = Profile::FromBrowserContext(context);
+  if (profile && chromeos::ProfileHelper::IsSigninProfile(profile) &&
+      is_policy_extension) {
+    return true;
+  }
+#endif
+
+  return extension && AppIsolationInfo::HasIsolatedStorage(extension);
+}
+
 void SetIsIncognitoEnabled(const std::string& extension_id,
                            content::BrowserContext* context,
                            bool enabled) {
diff --git a/chrome/browser/extensions/extension_util.h b/chrome/browser/extensions/extension_util.h
index 61acca1..00484af 100644
--- a/chrome/browser/extensions/extension_util.h
+++ b/chrome/browser/extensions/extension_util.h
@@ -34,6 +34,13 @@
 
 namespace util {
 
+// Returns true if the site URL corresponds to an extension or app which
+// has isolated storage. This can be either because it is an app that
+// requested this in its manifest, or because it is a policy-installed app or
+// extension running on the Chrome OS sign-in profile.
+bool SiteHasIsolatedStorage(const GURL& extension_site_url,
+                            content::BrowserContext* context);
+
 // Sets whether |extension_id| can run in an incognito window. Reloads the
 // extension if it's enabled since this permission is applied at loading time
 // only. Note that an ExtensionService must exist.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index daa0007..d18eaee8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -49,6 +49,11 @@
     "expiry_milestone": 80
   },
   {
+    "name": "force-dice-migration",
+    "owners": [ "msalama" ],
+    "expiry_milestone": 85
+  },
+  {
     "name": "show-sync-paused-reason-cookies-cleared-on-exit",
     "owners": [ "msalama" ],
     "expiry_milestone": 85
@@ -2026,7 +2031,7 @@
   },
   {
     "name": "force-use-chrome-camera",
-    "owners": [ "shenghao", "chromeos-camera-app-eng@google.com" ],
+    "owners": [ "shik", "chromeos-camera-app-eng@google.com" ],
     "expiry_milestone": 76
   },
   {
@@ -2814,6 +2819,16 @@
     "owners": [ "binji" ],
     "expiry_milestone": 78
   },
+	{
+    "name": "shared-clipboard-receiver",
+    "owners": [ "//chrome/browser/sharing/OWNERS" ],
+    "expiry_milestone": 80
+  },
+  {
+    "name": "shared-clipboard-ui",
+    "owners": [ "//chrome/browser/sharing/OWNERS" ],
+    "expiry_milestone": 80
+  },
   {
     "name": "shelf-dense-clamshell",
     "owners": [ "manucornet", "mmourgos" ],
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 81b32eb..90fb0a6b 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1701,6 +1701,18 @@
 const char kSettingsWindowDescription[] =
     "Settings will be shown in a dedicated window instead of as a browser tab.";
 
+const char kSharedClipboardReceiverName[] =
+    "Enable receiver device to handle shared clipboard feature";
+const char kSharedClipboardReceiverDescription[] =
+    "Enables receiver device to handle shared clipboard feature by showing a "
+    "notification to receive the clipboard to share.";
+
+const char kSharedClipboardUIName[] =
+    "Enable shared clipboard feature signals to be handled";
+const char kSharedClipboardUIDescription[] =
+    "Enables shared clipboard feature signals to be handled by showing "
+    "a list of user's available devices to share the clipboard.";
+
 const char kSharingDeviceRegistrationName[] =
     "Enable device registration for Sharing features";
 const char kSharingDeviceRegistrationDescription[] =
@@ -2657,6 +2669,10 @@
 const char kAccountConsistencyChoiceMirror[] = "Mirror";
 const char kAccountConsistencyChoiceDice[] = "Dice";
 
+const char kForceDiceMigrationName[] = "Force the migration to Dice";
+const char kForceDiceMigrationDescription[] =
+    "When enabled the account reconcilor will force the migration to dice";
+
 const char kShowSyncPausedReasonCookiesClearedOnExitName[] =
     "Show sync paused reason is the setup of cookie settings.";
 const char kShowSyncPausedReasonCookiesClearedOnExitDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e079d7a..2387a33c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1009,6 +1009,12 @@
 extern const char kSettingsWindowName[];
 extern const char kSettingsWindowDescription[];
 
+extern const char kSharedClipboardReceiverName[];
+extern const char kSharedClipboardReceiverDescription[];
+
+extern const char kSharedClipboardUIName[];
+extern const char kSharedClipboardUIDescription[];
+
 extern const char kSharingDeviceRegistrationName[];
 extern const char kSharingDeviceRegistrationDescription[];
 
@@ -1564,6 +1570,9 @@
 extern const char kAccountConsistencyChoiceMirror[];
 extern const char kAccountConsistencyChoiceDice[];
 
+extern const char kForceDiceMigrationName[];
+extern const char kForceDiceMigrationDescription[];
+
 extern const char kShowSyncPausedReasonCookiesClearedOnExitName[];
 extern const char kShowSyncPausedReasonCookiesClearedOnExitDescription[];
 
diff --git a/chrome/browser/metrics/bluetooth_available_utility.cc b/chrome/browser/metrics/bluetooth_available_utility.cc
index e046a5b..78417e5 100644
--- a/chrome/browser/metrics/bluetooth_available_utility.cc
+++ b/chrome/browser/metrics/bluetooth_available_utility.cc
@@ -57,7 +57,7 @@
   // GetAdapter must be called on the UI thread, because it creates a
   // WeakPtr, which is checked from that thread on future calls.
   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE,
         {content::BrowserThread::UI, base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&ReportBluetoothAvailability));
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index 5af7528e..92d7f8c 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -567,11 +567,11 @@
 #endif
 
   constexpr base::TaskTraits background_task_traits = {
-      base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-  base::PostTaskWithTraits(FROM_HERE, background_task_traits,
-                           base::BindOnce(&RecordLinuxDistro));
+  base::PostTask(FROM_HERE, background_task_traits,
+                 base::BindOnce(&RecordLinuxDistro));
 #endif
 
 #if defined(USE_OZONE) || defined(USE_X11)
@@ -595,11 +595,11 @@
 #if defined(OS_WIN)
   // RecordStartupMetrics calls into shell_integration::GetDefaultBrowser(),
   // which requires a COM thread on Windows.
-  base::CreateCOMSTATaskRunnerWithTraits(background_task_traits)
+  base::CreateCOMSTATaskRunner(background_task_traits)
       ->PostTask(FROM_HERE, base::BindOnce(&RecordStartupMetrics));
 #else
-  base::PostTaskWithTraits(FROM_HERE, background_task_traits,
-                           base::BindOnce(&RecordStartupMetrics));
+  base::PostTask(FROM_HERE, background_task_traits,
+                 base::BindOnce(&RecordStartupMetrics));
 #endif  // defined(OS_WIN)
 
 #if defined(OS_WIN)
@@ -607,7 +607,7 @@
   // breaking some tests, including all of the ProcessMemoryMetricsEmitterTest
   // tests. Figure out why there is a dependency and fix the tests.
   auto background_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(background_task_traits);
+      base::CreateSequencedTaskRunner(background_task_traits);
 
   background_task_runner->PostDelayedTask(
       FROM_HERE, base::BindOnce(&RecordIsPinnedToTaskbarHistogram),
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 61490caf..f30235d 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -244,9 +244,9 @@
   } else {
     // When metrics reporting is not enabled, any existing file should be
     // deleted in order to preserve user privacy.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE,
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
          base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
         base::BindOnce(base::IgnoreResult(&base::DeleteFile), metrics_file,
                        /*recursive=*/false));
@@ -298,13 +298,13 @@
     } else {
       // When metrics reporting is not enabled, any existing files should be
       // deleted in order to preserve user privacy.
-      base::PostTaskWithTraits(
-          FROM_HERE,
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-          base::BindOnce(base::IgnoreResult(&base::DeleteFile),
-                         std::move(browser_metrics_upload_dir),
-                         /*recursive=*/true));
+      base::PostTask(FROM_HERE,
+                     {base::ThreadPool(), base::MayBlock(),
+                      base::TaskPriority::BEST_EFFORT,
+                      base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+                     base::BindOnce(base::IgnoreResult(&base::DeleteFile),
+                                    std::move(browser_metrics_upload_dir),
+                                    /*recursive=*/true));
     }
   }
 
@@ -334,9 +334,10 @@
               metrics::FileMetricsProvider::ASSOCIATE_CURRENT_RUN,
               notification_helper::kNotificationHelperHistogramAllocatorName));
     } else {
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE,
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
           base::BindOnce(base::IgnoreResult(&base::DeleteFile),
                          std::move(notification_helper_metrics_upload_dir),
@@ -879,7 +880,7 @@
 #endif
 
   // Merge histograms from metrics providers into StatisticsRecorder.
-  base::PostTaskWithTraitsAndReply(
+  base::PostTaskAndReply(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&base::StatisticsRecorder::ImportProvidedHistograms),
       callback);
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
index 1a7383a..c14a061 100644
--- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -72,8 +72,9 @@
 // Posts |GoogleUpdateSettings::StoreMetricsClientInfo| on blocking pool thread
 // because it needs access to IO and cannot work from UI thread.
 void PostStoreMetricsClientInfo(const metrics::ClientInfo& client_info) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&GoogleUpdateSettings::StoreMetricsClientInfo,
                      client_info));
 }
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc
index b520f5f..be80655 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -204,9 +204,9 @@
     const base::Closure& callback) {
   // Run the (potentially expensive) task in the background to avoid blocking
   // the UI thread.
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::MayBlock(), base::WithBaseSyncPrimitives(),
+      {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
        base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&GetFullHardwareClassOnBackgroundThread),
diff --git a/chrome/browser/metrics/field_trial_synchronizer.cc b/chrome/browser/metrics/field_trial_synchronizer.cc
index 235098e..befe5930 100644
--- a/chrome/browser/metrics/field_trial_synchronizer.cc
+++ b/chrome/browser/metrics/field_trial_synchronizer.cc
@@ -57,10 +57,9 @@
   if (!content::BrowserThread::IsThreadInitialized(BrowserThread::UI))
     return;
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&FieldTrialSynchronizer::NotifyAllRenderers, this,
-                     field_trial_name, group_name));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&FieldTrialSynchronizer::NotifyAllRenderers,
+                                this, field_trial_name, group_name));
 }
 
 FieldTrialSynchronizer::~FieldTrialSynchronizer() {
diff --git a/chrome/browser/metrics/google_update_metrics_provider_win.cc b/chrome/browser/metrics/google_update_metrics_provider_win.cc
index e1cb5c3..626fc160 100644
--- a/chrome/browser/metrics/google_update_metrics_provider_win.cc
+++ b/chrome/browser/metrics/google_update_metrics_provider_win.cc
@@ -60,8 +60,9 @@
 
   // Schedules a task on a blocking pool thread to gather Google Update
   // statistics (requires Registry reads).
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&GoogleUpdateMetricsProviderWin::GetGoogleUpdateDataBlocking),
       base::Bind(&GoogleUpdateMetricsProviderWin::ReceiveGoogleUpdateData,
                  weak_ptr_factory_.GetWeakPtr(), done_callback));
diff --git a/chrome/browser/metrics/perf/heap_collector.cc b/chrome/browser/metrics/perf/heap_collector.cc
index 8556f584..57fb462 100644
--- a/chrome/browser/metrics/perf/heap_collector.cc
+++ b/chrome/browser/metrics/perf/heap_collector.cc
@@ -85,11 +85,12 @@
 const char kQuipperProcessPid[] = "pid";
 
 void DeleteFileAsync(const base::FilePath& path) {
-  base::PostTaskWithTraits(FROM_HERE,
-                           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-                            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-                           base::BindOnce(base::IgnoreResult(&base::DeleteFile),
-                                          std::move(path), false));
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+      base::BindOnce(base::IgnoreResult(&base::DeleteFile), std::move(path),
+                     false));
 }
 
 // Deletes the temp file when the object goes out of scope.
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc
index ec65ac26..7e458a6 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -252,9 +252,9 @@
   // in a separate thread.
   DCHECK(base::SequencedTaskRunnerHandle::IsSet());
   ui_task_runner_ = base::SequencedTaskRunnerHandle::Get();
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&PerfCollector::ParseCPUFrequencies, ui_task_runner_,
                      weak_factory_.GetWeakPtr()));
@@ -437,8 +437,9 @@
                   sampled_profile->mutable_cpu_max_frequency_mhz()));
   }
 
-  bool posted = base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  bool posted = base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&OnCollectProcessTypes, sampled_profile.get()),
       base::BindOnce(&PerfCollector::SaveSerializedPerfProto,
                      weak_factory_.GetWeakPtr(), std::move(sampled_profile),
diff --git a/chrome/browser/metrics/perf/perf_output.cc b/chrome/browser/metrics/perf/perf_output.cc
index 53f2c51c8..23e9a75 100644
--- a/chrome/browser/metrics/perf/perf_output.cc
+++ b/chrome/browser/metrics/perf/perf_output.cc
@@ -22,9 +22,9 @@
       weak_factory_(this) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
-  perf_data_pipe_reader_ =
-      std::make_unique<chromeos::PipeReader>(base::CreateTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
+  perf_data_pipe_reader_ = std::make_unique<chromeos::PipeReader>(
+      base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
+                              base::TaskPriority::USER_VISIBLE}));
 
   base::ScopedFD pipe_write_end =
       perf_data_pipe_reader_->StartIO(base::BindOnce(
diff --git a/chrome/browser/metrics/power_metrics_provider_mac.mm b/chrome/browser/metrics/power_metrics_provider_mac.mm
index 40c7d2b..667acde 100644
--- a/chrome/browser/metrics/power_metrics_provider_mac.mm
+++ b/chrome/browser/metrics/power_metrics_provider_mac.mm
@@ -205,8 +205,9 @@
  private:
   friend class base::RefCountedThreadSafe<Impl>;
   Impl(base::mac::ScopedIOObject<io_object_t> connect)
-      : task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-            {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      : task_runner_(base::CreateSequencedTaskRunner(
+            {base::ThreadPool(), base::MayBlock(),
+             base::TaskPriority::USER_VISIBLE,
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
         system_total_power_key_(connect, SMCParamStruct::SMCKey::TotalPower),
         cpu_package_cpu_power_key_(connect, SMCParamStruct::SMCKey::CPUPower),
diff --git a/chrome/browser/metrics/subprocess_metrics_provider.cc b/chrome/browser/metrics/subprocess_metrics_provider.cc
index 2036ba7e..e966058 100644
--- a/chrome/browser/metrics/subprocess_metrics_provider.cc
+++ b/chrome/browser/metrics/subprocess_metrics_provider.cc
@@ -126,7 +126,7 @@
   // managing the child in order to extract the metrics memory from it.
   // Unfortunately, the required lookup can only be performed on the IO
   // thread so do the necessary dance.
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE, {content::BrowserThread::IO},
       base::Bind(
           &SubprocessMetricsProvider::GetSubprocessHistogramAllocatorOnIOThread,
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc
index 5d6d5a8a..0fd772a 100644
--- a/chrome/browser/metrics/thread_watcher.cc
+++ b/chrome/browser/metrics/thread_watcher.cc
@@ -163,8 +163,7 @@
 ThreadWatcher::ThreadWatcher(const WatchingParams& params)
     : thread_id_(params.thread_id),
       thread_name_(params.thread_name),
-      watched_runner_(
-          base::CreateSingleThreadTaskRunnerWithTraits({params.thread_id})),
+      watched_runner_(base::CreateSingleThreadTaskRunner({params.thread_id})),
       sleep_time_(params.sleep_time),
       unresponsive_time_(params.unresponsive_time),
       ping_time_(base::TimeTicks::Now()),
@@ -636,8 +635,8 @@
   DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
 
   // Disarm the startup timebomb, even if stop has been called.
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(&DisarmStartupTimeBomb));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&DisarmStartupTimeBomb));
 
   // This method is deferred in relationship to its StopWatchingAll()
   // counterpart. If a previous initialization has already happened, or if
diff --git a/chrome/browser/metrics/thread_watcher_unittest.cc b/chrome/browser/metrics/thread_watcher_unittest.cc
index 93f70d7..6c2cf9f2 100644
--- a/chrome/browser/metrics/thread_watcher_unittest.cc
+++ b/chrome/browser/metrics/thread_watcher_unittest.cc
@@ -553,7 +553,7 @@
     // a very long time by posting a task on watched thread that keeps it busy.
     // It is safe to use base::Unretained because test is waiting for the method
     // to finish.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&CustomThreadWatcher::VeryLongMethod,
                        base::Unretained(io_watcher_), kUnresponsiveTime * 10));
@@ -627,7 +627,7 @@
     // a very long time by posting a task on watched thread that keeps it busy.
     // It is safe to use base::Unretained because test is waiting for the method
     // to finish.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&CustomThreadWatcher::VeryLongMethod,
                        base::Unretained(io_watcher_), kUnresponsiveTime * 10));
@@ -730,10 +730,10 @@
   ThreadWatcherList::StopWatchingAll();
   {
     base::RunLoop run_loop;
-    base::PostDelayedTaskWithTraits(
-        FROM_HERE, {BrowserThread::UI}, run_loop.QuitWhenIdleClosure(),
-        base::TimeDelta::FromSeconds(
-            ThreadWatcherList::g_initialize_delay_seconds));
+    base::PostDelayedTask(FROM_HERE, {BrowserThread::UI},
+                          run_loop.QuitWhenIdleClosure(),
+                          base::TimeDelta::FromSeconds(
+                              ThreadWatcherList::g_initialize_delay_seconds));
     run_loop.Run();
   }
 
@@ -744,7 +744,7 @@
   ThreadWatcherList::StartWatchingAll(*base::CommandLine::ForCurrentProcess());
   {
     base::RunLoop run_loop;
-    base::PostDelayedTaskWithTraits(
+    base::PostDelayedTask(
         FROM_HERE, {BrowserThread::UI}, run_loop.QuitWhenIdleClosure(),
         base::TimeDelta::FromSeconds(
             ThreadWatcherList::g_initialize_delay_seconds + 1));
@@ -758,10 +758,10 @@
   ThreadWatcherList::StopWatchingAll();
   {
     base::RunLoop run_loop;
-    base::PostDelayedTaskWithTraits(
-        FROM_HERE, {BrowserThread::UI}, run_loop.QuitWhenIdleClosure(),
-        base::TimeDelta::FromSeconds(
-            ThreadWatcherList::g_initialize_delay_seconds));
+    base::PostDelayedTask(FROM_HERE, {BrowserThread::UI},
+                          run_loop.QuitWhenIdleClosure(),
+                          base::TimeDelta::FromSeconds(
+                              ThreadWatcherList::g_initialize_delay_seconds));
     run_loop.Run();
   }
 
diff --git a/chrome/browser/notifications/notification_channels_provider_android.cc b/chrome/browser/notifications/notification_channels_provider_android.cc
index f16715d..c7c87780 100644
--- a/chrome/browser/notifications/notification_channels_provider_android.cc
+++ b/chrome/browser/notifications/notification_channels_provider_android.cc
@@ -289,7 +289,7 @@
     // underlying state of NotificationChannelsProviderAndroid, and allows us to
     // notify observers as soon as we detect changes to channels.
     auto* provider = const_cast<NotificationChannelsProviderAndroid*>(this);
-    base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
+    base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
         ->PostTask(FROM_HERE,
                    base::BindOnce(
                        &NotificationChannelsProviderAndroid::NotifyObservers,
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc
index cf0d031e..ea45ca0 100644
--- a/chrome/browser/notifications/notification_platform_bridge_android.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -352,7 +352,7 @@
     Profile* profile,
     GetDisplayedNotificationsCallback callback) const {
   std::set<std::string> displayed_notifications;
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(std::move(callback), std::move(displayed_notifications),
                      false /* supports_synchronization */));
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index 230481c7..171e43b3b 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -466,7 +466,7 @@
           ConnectionInitializationStatusCode::MISSING_REQUIRED_CAPABILITIES);
       return;
     }
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
             &NotificationPlatformBridgeLinuxImpl::SetBodyImagesSupported, this,
@@ -772,7 +772,7 @@
       if (data->profile_id == profile_id && data->is_incognito == incognito)
         displayed.insert(data->notification_id);
     }
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(std::move(callback), std::move(displayed), true));
   }
@@ -811,7 +811,7 @@
                                     const base::Optional<int>& action_index,
                                     const base::Optional<bool>& by_user) {
     DCHECK(task_runner_->RunsTasksInCurrentSequence());
-    base::PostTaskWithTraits(
+    base::PostTask(
         location, {content::BrowserThread::UI},
         base::BindOnce(ForwardNotificationOperationOnUiThread, operation,
                        data->notification_type, data->origin_url,
@@ -907,7 +907,7 @@
       CleanUpOnTaskRunner();
     }
 
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&NotificationPlatformBridgeLinuxImpl::
                            OnConnectionInitializationFinishedOnUiThread,
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm
index 08078c5f..f4e30466 100644
--- a/chrome/browser/notifications/notification_platform_bridge_mac.mm
+++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm
@@ -378,7 +378,7 @@
     action_index = button_index.intValue;
   }
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(DoProcessNotificationResponse,
                      static_cast<NotificationCommon::Operation>(
@@ -594,7 +594,7 @@
     for (NSString* alert in alerts)
       displayedNotifications.insert(base::SysNSStringToUTF8(alert));
 
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(copyable_callback, std::move(displayedNotifications),
                        true /* supports_synchronization */));
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc
index e914dbce..0278b39 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -568,7 +568,7 @@
       displayed_notifications.insert(launch_id.notification_id());
     }
 
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(std::move(callback), std::move(displayed_notifications),
                        /*supports_synchronization=*/true));
@@ -612,9 +612,8 @@
 
     LogSetReadyCallbackStatus(static_cast<SetReadyCallbackStatus>(status));
 
-    bool success =
-        base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                                 base::BindOnce(std::move(callback), enabled));
+    bool success = base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                                  base::BindOnce(std::move(callback), enabled));
     DCHECK(success);
   }
 
@@ -629,7 +628,7 @@
       return;
     }
 
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&ForwardNotificationOperationOnUiThread, operation,
                        launch_id.notification_type(), launch_id.origin_url(),
@@ -777,8 +776,8 @@
     NotificationPlatformBridgeWinImpl::notifier_for_testing_ = nullptr;
 
 NotificationPlatformBridgeWin::NotificationPlatformBridgeWin() {
-  notification_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+  notification_task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   impl_ = base::MakeRefCounted<NotificationPlatformBridgeWinImpl>(
       notification_task_runner_);
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
index 578f2d6..6db1d94 100644
--- a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
+++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
@@ -139,8 +139,9 @@
 void ConvertIconToString(SkBitmap image,
                          base::OnceCallback<void(std::string)> callback) {
   DCHECK(callback);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&ConvertIconToStringOnIOThread, std::move(image)),
       std::move(callback));
 }
@@ -149,8 +150,9 @@
 void ConvertStringToIcon(std::string data,
                          base::OnceCallback<void(SkBitmap)> callback) {
   DCHECK(callback);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&ConvertStringToIconOnIOThread, std::move(data)),
       std::move(callback));
 }
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
index 07bd38d..7ea1305 100644
--- a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
+++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -54,8 +54,8 @@
     return static_cast<KeyedService*>(new NoopNotificationScheduleService());
 
   auto config = SchedulerConfig::Create();
-  auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+  auto task_runner = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT});
   client_registrar->RegisterClient(SchedulerClientType::kWebUI,
                                    std::make_unique<WebUIClient>());
 
diff --git a/chrome/browser/notifications/win/notification_image_retainer.cc b/chrome/browser/notifications/win/notification_image_retainer.cc
index 6a4487b..f000ddb 100644
--- a/chrome/browser/notifications/win/notification_image_retainer.cc
+++ b/chrome/browser/notifications/win/notification_image_retainer.cc
@@ -89,8 +89,9 @@
 
 NotificationImageRetainer::NotificationImageRetainer()
     : NotificationImageRetainer(
-          base::CreateSequencedTaskRunnerWithTraits(
-              {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+          base::CreateSequencedTaskRunner(
+              {base::ThreadPool(), base::MayBlock(),
+               base::TaskPriority::BEST_EFFORT,
                base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}),
           base::DefaultTickClock::GetInstance()) {}
 
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc b/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc
index 55a995c..c11b050 100644
--- a/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc
+++ b/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc
@@ -83,7 +83,7 @@
 
   void SetUp() override;
   void TearDown() override;
-  content::BrowserContext* CreateBrowserContext() override;
+  std::unique_ptr<content::BrowserContext> CreateBrowserContext() override;
 
   void CreateNavigationSimulator(const GURL& url);
 
@@ -131,9 +131,9 @@
   content::RenderViewHostTestHarness::TearDown();
 }
 
-content::BrowserContext* OfflinePageTabHelperTest::CreateBrowserContext() {
-  TestingProfile::Builder builder;
-  return builder.Build().release();
+std::unique_ptr<content::BrowserContext>
+OfflinePageTabHelperTest::CreateBrowserContext() {
+  return TestingProfile::Builder().Build();
 }
 
 void OfflinePageTabHelperTest::CreateNavigationSimulator(const GURL& url) {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
index ce3747b..3e4d83eb 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -25,8 +25,11 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "net/base/net_errors.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
+#include "ui/base/page_transition_types.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
@@ -145,6 +148,36 @@
     ancestor_data->set_timing(timing.Clone());
 }
 
+void AdsPageLoadMetricsObserver::MaybeTriggerHeavyAdIntervention(
+    content::RenderFrameHost* render_frame_host,
+    FrameData* frame_data) {
+  DCHECK(render_frame_host);
+  if (!frame_data->MaybeTriggerHeavyAdIntervention())
+    return;
+
+  // Find the RenderFrameHost associated with this frame data. It is possible
+  // that this frame no longer exists. We do not care if the frame has
+  // moved to a new process because once the frame has been tagged as an ad, it
+  // is always considered an ad.
+  while (render_frame_host && render_frame_host->GetFrameTreeNodeId() !=
+                                  frame_data->frame_tree_node_id()) {
+    render_frame_host = render_frame_host->GetParent();
+  }
+  if (!render_frame_host)
+    return;
+
+  // Ensure that this RenderFrameHost is a subframe.
+  DCHECK(render_frame_host->GetParent());
+
+  // TODO(959849): Navigate the frame to an error page once error pages can be
+  // loaded from the browser process.
+  ADS_HISTOGRAM("HeavyAds.InterventionType", UMA_HISTOGRAM_ENUMERATION,
+                FrameData::FrameVisibility::kAnyVisibility,
+                frame_data->heavy_ad_status());
+  ADS_HISTOGRAM("HeavyAds.InterventionType", UMA_HISTOGRAM_ENUMERATION,
+                frame_data->visibility(), frame_data->heavy_ad_status());
+}
+
 void AdsPageLoadMetricsObserver::OnCpuTimingUpdate(
     content::RenderFrameHost* subframe_rfh,
     const page_load_metrics::mojom::CpuTiming& timing) {
@@ -169,6 +202,7 @@
   if (ancestor_data) {
     ancestor_data->UpdateCpuUsage(current_time, timing.task_time,
                                   interactive_status);
+    MaybeTriggerHeavyAdIntervention(subframe_rfh, ancestor_data);
   }
 }
 
@@ -311,8 +345,7 @@
         resources) {
   for (auto const& resource : resources) {
     ProcessResourceForPage(rfh->GetProcess()->GetID(), resource);
-    ProcessResourceForFrame(rfh->GetFrameTreeNodeId(),
-                            rfh->GetProcess()->GetID(), resource);
+    ProcessResourceForFrame(rfh, resource);
   }
 }
 
@@ -454,10 +487,10 @@
 }
 
 void AdsPageLoadMetricsObserver::ProcessResourceForFrame(
-    FrameTreeNodeId frame_tree_node_id,
-    int process_id,
+    content::RenderFrameHost* render_frame_host,
     const page_load_metrics::mojom::ResourceDataUpdatePtr& resource) {
-  const auto& id_and_data = ad_frames_data_.find(frame_tree_node_id);
+  const auto& id_and_data =
+      ad_frames_data_.find(render_frame_host->GetFrameTreeNodeId());
   if (id_and_data == ad_frames_data_.end()) {
     if (resource->is_primary_frame_resource) {
       // Only hold onto primary resources if their load has finished, otherwise
@@ -469,7 +502,8 @@
       // hasn't yet finished navigating. Hang onto the request info and replay
       // it once the frame finishes navigating.
       ongoing_navigation_resources_.emplace(
-          std::piecewise_construct, std::forward_as_tuple(frame_tree_node_id),
+          std::piecewise_construct,
+          std::forward_as_tuple(render_frame_host->GetFrameTreeNodeId()),
           std::forward_as_tuple(resource.Clone()));
     } else {
       // This is unexpected, it could be:
@@ -491,11 +525,14 @@
     return;
 
   auto mime_type = FrameData::GetResourceMimeType(resource);
-  int unaccounted_ad_bytes = GetUnaccountedAdBytes(process_id, resource);
-  ancestor_data->ProcessResourceLoadInFrame(
-      resource, process_id, GetDelegate()->GetResourceTracker());
+  int unaccounted_ad_bytes =
+      GetUnaccountedAdBytes(render_frame_host->GetProcess()->GetID(), resource);
   if (unaccounted_ad_bytes)
     ancestor_data->AdjustAdBytes(unaccounted_ad_bytes, mime_type);
+  ancestor_data->ProcessResourceLoadInFrame(
+      resource, render_frame_host->GetProcess()->GetID(),
+      GetDelegate()->GetResourceTracker());
+  MaybeTriggerHeavyAdIntervention(render_frame_host, ancestor_data);
 }
 
 void AdsPageLoadMetricsObserver::RecordPageResourceTotalHistograms(
@@ -764,6 +801,8 @@
     ADS_HISTOGRAM("FrameCounts.AdFrames.PerFrame.UserActivation",
                   UMA_HISTOGRAM_ENUMERATION, visibility,
                   ad_frame_data.user_activation_status());
+    ADS_HISTOGRAM("HeavyAds.ComputedType", UMA_HISTOGRAM_ENUMERATION,
+                  visibility, ad_frame_data.heavy_ad_status());
   }
 }
 
@@ -848,8 +887,7 @@
       ongoing_navigation_resources_.find(rfh->GetFrameTreeNodeId());
   if (frame_id_and_request == ongoing_navigation_resources_.end())
     return;
-  ProcessResourceForFrame(rfh->GetFrameTreeNodeId(), rfh->GetProcess()->GetID(),
-                          frame_id_and_request->second);
+  ProcessResourceForFrame(rfh, frame_id_and_request->second);
   ongoing_navigation_resources_.erase(frame_id_and_request);
 }
 
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
index af5abdf1..5db3f48 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
@@ -119,8 +119,7 @@
       int process_id,
       const page_load_metrics::mojom::ResourceDataUpdatePtr& resource);
   void ProcessResourceForFrame(
-      FrameTreeNodeId frame_tree_node_id,
-      int process_id,
+      content::RenderFrameHost* render_frame_host,
       const page_load_metrics::mojom::ResourceDataUpdatePtr& resource);
 
   void RecordPageResourceTotalHistograms(ukm::SourceId source_id);
@@ -140,6 +139,16 @@
   // |ad_frames_data_storage_|.
   FrameData* FindFrameData(FrameTreeNodeId id);
 
+  // Loads the heavy ad intervention page in the target frame if it is safe to
+  // do so on this origin, and the frame meets the criteria to be considered a
+  // heavy ad.
+  // TODO(johnidel): Ads may only automatically be unloaded 5 times per-origin
+  // per day and to prevent a side channel leak of cross-origin resource size /
+  // CPU usage.
+  void MaybeTriggerHeavyAdIntervention(
+      content::RenderFrameHost* render_frame_host,
+      FrameData* frame_data);
+
   // Stores the size data of each ad frame. Pointed to by ad_frames_ so use a
   // data structure that won't move the data around. This only stores ad frames
   // that are actively on the page. When a frame is destroyed, so should its
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
index 9d287a1..202ce17 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
@@ -24,17 +25,20 @@
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_tracker.h"
 #include "chrome/browser/subresource_filter/subresource_filter_test_harness.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
 #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
 #include "components/subresource_filter/core/common/load_policy.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "content/public/browser/global_request_id.h"
+#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/resource_type.h"
+#include "content/public/common/url_constants.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_navigation_throttle.h"
 #include "content/public/test/test_navigation_throttle_inserter.h"
@@ -1448,3 +1452,132 @@
   test_ukm_recorder().ExpectEntryMetric(
       entries.front(), ukm::builders::AdFrameLoad::kTiming_InteractiveName, 20);
 }
+
+// Tests that even when the intervention is not enabled, we still record the
+// computed heavy ad types for ad frames
+TEST_F(AdsPageLoadMetricsObserverTest, HeavyAdFeatureOff_UMARecorded) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kHeavyAdIntervention);
+
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame_none =
+      CreateAndNavigateSubFrame(kAdUrl, main_frame);
+  RenderFrameHost* ad_frame_net = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+  RenderFrameHost* ad_frame_cpu = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  // Load some bytes in each frame so they are considered ad iframes.
+  ResourceDataUpdate(ad_frame_none, ResourceCached::NOT_CACHED, 1);
+  ResourceDataUpdate(ad_frame_net, ResourceCached::NOT_CACHED, 1);
+  ResourceDataUpdate(ad_frame_cpu, ResourceCached::NOT_CACHED, 1);
+
+  // Make two of the ad frames hit thresholds for heavy ads.
+  ResourceDataUpdate(ad_frame_net, ResourceCached::NOT_CACHED,
+                     (heavy_ad_thresholds::kMaxNetworkBytes / 1024));
+  OnCpuTimingUpdate(ad_frame_cpu, base::TimeDelta::FromMilliseconds(
+                                      heavy_ad_thresholds::kMaxCpuTime));
+
+  // Navigate again to trigger histograms.
+  NavigateFrame(kNonAdUrl, main_frame);
+
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.ComputedType"), 3);
+  histogram_tester().ExpectBucketCount(
+      SuffixedHistogram("HeavyAds.ComputedType"),
+      FrameData::HeavyAdStatus::kNone, 1);
+  histogram_tester().ExpectBucketCount(
+      SuffixedHistogram("HeavyAds.ComputedType"),
+      FrameData::HeavyAdStatus::kNetwork, 1);
+  histogram_tester().ExpectBucketCount(
+      SuffixedHistogram("HeavyAds.ComputedType"),
+      FrameData::HeavyAdStatus::kCpu, 1);
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.InterventionType"), 0);
+}
+
+TEST_F(AdsPageLoadMetricsObserverTest, HeavyAdNetworkUsage_InterventionFired) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kHeavyAdIntervention);
+  OverrideVisibilityTrackerWithMockClock();
+
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  // Load just under the threshold amount of bytes.
+  ResourceDataUpdate(ad_frame, ResourceCached::NOT_CACHED,
+                     (heavy_ad_thresholds::kMaxNetworkBytes / 1024) - 1);
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.InterventionType"), 0);
+
+  // Load enough bytes to trigger the intervention.
+  ResourceDataUpdate(ad_frame, ResourceCached::NOT_CACHED, 2);
+
+  histogram_tester().ExpectUniqueSample(
+      SuffixedHistogram("HeavyAds.InterventionType"),
+      FrameData::HeavyAdStatus::kNetwork, 1);
+}
+
+TEST_F(AdsPageLoadMetricsObserverTest, HeavyAdCpuUsage_InterventionFired) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kHeavyAdIntervention);
+  OverrideVisibilityTrackerWithMockClock();
+
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  // Add some data to the ad frame so it get reported.
+  ResourceDataUpdate(ad_frame, ResourceCached::NOT_CACHED, 1);
+
+  // Use just under the threshold amount of CPU.
+  OnCpuTimingUpdate(ad_frame, base::TimeDelta::FromMilliseconds(
+                                  heavy_ad_thresholds::kMaxCpuTime - 1));
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.InterventionType"), 0);
+
+  // Use enough CPU to trigger the intervention.
+  OnCpuTimingUpdate(ad_frame, base::TimeDelta::FromMilliseconds(1));
+
+  histogram_tester().ExpectUniqueSample(
+      SuffixedHistogram("HeavyAds.InterventionType"),
+      FrameData::HeavyAdStatus::kCpu, 1);
+}
+
+TEST_F(AdsPageLoadMetricsObserverTest, HeavyAdFeatureDisabled_NotFired) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kHeavyAdIntervention);
+
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  // Add enough data to trigger the intervention.
+  ResourceDataUpdate(ad_frame, ResourceCached::NOT_CACHED,
+                     (heavy_ad_thresholds::kMaxNetworkBytes / 1024) + 1);
+
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.InterventionType"), 0);
+}
+
+TEST_F(AdsPageLoadMetricsObserverTest,
+       HeavyAdWithUserGesture_NotConsideredHeavy) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kHeavyAdIntervention);
+
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  // Give the frame a user activation before the threshold would be hit.
+  TriggerFirstUserActivation(ad_frame);
+
+  // Add enough data to trigger the intervention.
+  ResourceDataUpdate(ad_frame, ResourceCached::NOT_CACHED,
+                     (heavy_ad_thresholds::kMaxNetworkBytes / 1024) + 1);
+
+  histogram_tester().ExpectTotalCount(
+      SuffixedHistogram("HeavyAds.InterventionType"), 0);
+
+  // Navigate again to trigger histograms.
+  NavigateFrame(kNonAdUrl, main_frame);
+
+  histogram_tester().ExpectUniqueSample(
+      SuffixedHistogram("HeavyAds.ComputedType"),
+      FrameData::HeavyAdStatus::kNone, 1);
+}
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc
index 7a74032..c4e007f7 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc
@@ -8,7 +8,9 @@
 #include <limits>
 #include <string>
 
+#include "base/feature_list.h"
 #include "chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h"
+#include "chrome/common/chrome_features.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "net/base/mime_util.h"
@@ -63,7 +65,8 @@
       user_activation_status_(UserActivationStatus::kNoActivation),
       is_display_none_(false),
       visibility_(FrameVisibility::kVisible),
-      frame_size_(gfx::Size()) {}
+      frame_size_(gfx::Size()),
+      heavy_ad_status_(HeavyAdStatus::kNone) {}
 
 FrameData::~FrameData() = default;
 
@@ -179,6 +182,23 @@
   }
 }
 
+bool FrameData::MaybeTriggerHeavyAdIntervention() {
+  if (user_activation_status_ == UserActivationStatus::kReceivedActivation ||
+      heavy_ad_status_ != HeavyAdStatus::kNone)
+    return false;
+
+  heavy_ad_status_ = ComputeHeavyAdStatus();
+  if (heavy_ad_status_ == HeavyAdStatus::kNone)
+    return false;
+
+  // Only check if the feature is enabled once we have a heavy ad. This is done
+  // to ensure that any experiment for this feature will only be comparing
+  // groups who have seen a heavy ad.
+  if (!base::FeatureList::IsEnabled(features::kHeavyAdIntervention))
+    return false;
+  return true;
+}
+
 base::TimeDelta FrameData::GetInteractiveCpuUsage(
     InteractiveStatus status) const {
   return cpu_by_interactive_period_[static_cast<int>(status)];
@@ -205,15 +225,6 @@
   return ad_bytes_by_mime_[static_cast<size_t>(mime_type)];
 }
 
-void FrameData::UpdateFrameVisibility() {
-  visibility_ =
-      !is_display_none_ &&
-              frame_size_.GetCheckedArea().ValueOrDefault(
-                  std::numeric_limits<int>::max()) >= kMinimumVisibleFrameArea
-          ? FrameVisibility::kVisible
-          : FrameVisibility::kNonVisible;
-}
-
 void FrameData::MaybeUpdateFrameDepth(
     content::RenderFrameHost* render_frame_host) {
   if (!render_frame_host)
@@ -280,3 +291,23 @@
   }
   builder.Record(ukm_recorder->Get());
 }
+
+void FrameData::UpdateFrameVisibility() {
+  visibility_ =
+      !is_display_none_ &&
+              frame_size_.GetCheckedArea().ValueOrDefault(
+                  std::numeric_limits<int>::max()) >= kMinimumVisibleFrameArea
+          ? FrameVisibility::kVisible
+          : FrameVisibility::kNonVisible;
+}
+
+FrameData::HeavyAdStatus FrameData::ComputeHeavyAdStatus() const {
+  // Check if the frame meets the absolute CPU time threshold.
+  if (GetTotalCpuUsage().InMilliseconds() >= heavy_ad_thresholds::kMaxCpuTime)
+    return HeavyAdStatus::kCpu;
+
+  // Check if the frame meets the network threshold.
+  if (network_bytes_ >= heavy_ad_thresholds::kMaxNetworkBytes)
+    return HeavyAdStatus::kNetwork;
+  return HeavyAdStatus::kNone;
+}
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
index c3a6a26..fcc077f 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
@@ -13,6 +13,25 @@
 #include "ui/gfx/geometry/size.h"
 #include "url/origin.h"
 
+// Resource usage thresholds for the Heavy Ad Intervention feature. These
+// numbers are platform specific and are intended to target 1 in 1000 ad iframes
+// on each platform.
+namespace heavy_ad_thresholds {
+
+// Maximum number of network bytes allowed to be loaded by a frame. These
+// numbers reflect the 99.9th percentile of the
+// PageLoad.Clients.Ads.Bytes.AdFrames.PerFrame.Network histogram on mobile and
+// desktop.
+const int kMaxNetworkBytes = 4.0 * 1024 * 1024;
+
+// Maximum number of milliseconds of CPU use allowed to be used by a frame.
+// These numbers reflect the 99.9th percentile of the
+// PageLoad.Clients.Ads.Cpu.AdFrames.PerFrame.TotalUsage.Unactivated histogram
+// on mobile and desktop.
+const int kMaxCpuTime = 60 * 1000;
+
+}  // namespace heavy_ad_thresholds
+
 // Store information received for a frame on the page. FrameData is meant
 // to represent a frame along with it's entire subtree.
 class FrameData {
@@ -35,6 +54,15 @@
     kMaxValue = kAnyVisibility,
   };
 
+  // The type of heavy ad this frame is classified as per the Heavy Ad
+  // Intervention.
+  enum class HeavyAdStatus {
+    kNone = 0,
+    kNetwork = 1,
+    kCpu = 2,
+    kMaxValue = kCpu,
+  };
+
   // These values are persisted to logs. Entries should not be renumbered and
   // numeric values should never be reused. For any additions, also update the
   // corresponding PageEndReason enum in enums.xml.
@@ -114,6 +142,12 @@
                       base::TimeDelta update,
                       InteractiveStatus interactive);
 
+  // Returns whether the heavy ad intervention was triggered on this frame.
+  // This intervention is triggered when the frame is considered heavy, has not
+  // received user gesture, and the intervention feature is enabled. This
+  // returns true the first time the criteria is met, and false afterwards.
+  bool MaybeTriggerHeavyAdIntervention();
+
   // Get the cpu usage for the appropriate interactive period.
   base::TimeDelta GetInteractiveCpuUsage(InteractiveStatus status) const;
 
@@ -182,6 +216,8 @@
     timing_ = std::move(timing);
   }
 
+  HeavyAdStatus heavy_ad_status() const { return heavy_ad_status_; }
+
  private:
   // Time updates for the frame with a timestamp indicating when they arrived.
   // Used for windowed cpu load reporting.
@@ -195,6 +231,10 @@
   // Updates whether or not this frame meets the criteria for visibility.
   void UpdateFrameVisibility();
 
+  // Computes whether this frame meets the criteria for being a heavy frame for
+  // the heavy ad intervention and returns the type of threshold hit if any.
+  HeavyAdStatus ComputeHeavyAdStatus() const;
+
   // The most recently updated timing received for this frame.
   page_load_metrics::mojom::PageLoadTimingPtr timing_;
 
@@ -262,6 +302,11 @@
   url::Origin origin_;
   MediaStatus media_status_ = MediaStatus::kNotPlayed;
 
+  // Indicates whether or not this frame met the criteria for the heavy ad
+  // intervention. This should be not be set if the Heavy Ad Intervention is
+  // not enabled.
+  HeavyAdStatus heavy_ad_status_;
+
   DISALLOW_COPY_AND_ASSIGN(FrameData);
 };
 
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index b0de78bc..4a3151ae 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1710,9 +1710,8 @@
   // is relevant. By the time the reply is executed it is guaranteed that the
   // migration is completed.
   base::RunLoop run_loop;
-  base::PostTaskWithTraitsAndReply(FROM_HERE, {content::BrowserThread::IO},
-                                   base::BindOnce([]() {}),
-                                   run_loop.QuitClosure());
+  base::PostTaskAndReply(FROM_HERE, {content::BrowserThread::IO},
+                         base::BindOnce([]() {}), run_loop.QuitClosure());
   run_loop.Run();
 
   // Migration updates should touch the password store.
diff --git a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc
index edefa261..ffcd09d 100644
--- a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc
+++ b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc
@@ -19,15 +19,15 @@
 #include "components/password_manager/core/browser/test_password_store.h"
 #include "content/public/test/test_utils.h"
 
+using captured_sites_test_utils::CapturedSiteParams;
+using captured_sites_test_utils::GetCapturedSites;
+using captured_sites_test_utils::GetParamAsString;
+
 namespace {
 
 constexpr base::TimeDelta kWaitForSaveFallbackInterval =
     base::TimeDelta::FromSeconds(5);
 
-struct TestParams {
-  std::string scenarioDir;
-  std::string siteName;
-};
 
 // Return path to the Password Manager captured sites test root directory. The
 // directory contains subdirectories for different password manager test
@@ -48,44 +48,6 @@
   return src_dir;
 }
 
-// Iterate through Password Manager's Web Page Replay capture file directory to
-// look for captures sites and automation recipe files. Return a list of sites
-// for which recipe-based testing is available.
-std::vector<TestParams> GetCapturedSites() {
-  std::vector<TestParams> sites;
-  base::FileEnumerator sub_dirs(GetReplayFilesRootDirectory(), false,
-                                base::FileEnumerator::DIRECTORIES);
-  for (base::FilePath dir = sub_dirs.Next(); !dir.empty();
-       dir = sub_dirs.Next()) {
-    base::FileEnumerator capture_files(dir, false, base::FileEnumerator::FILES);
-    for (base::FilePath file = capture_files.Next(); !file.empty();
-         file = capture_files.Next()) {
-      // If a site capture file is found, also look to see if the directory has
-      // a corresponding recorded action recipe log file.
-      // A site capture file has no extension. A recorded action recipe log file
-      // has the '.test' extension.
-      if (file.Extension().empty() &&
-          base::PathExists(file.AddExtension(FILE_PATH_LITERAL(".test")))) {
-        TestParams params;
-        params.scenarioDir =
-            captured_sites_test_utils::FilePathToUTF8(dir.BaseName().value());
-        params.siteName =
-            captured_sites_test_utils::FilePathToUTF8(file.BaseName().value());
-        sites.push_back(params);
-      }
-    }
-  }
-  return sites;
-}
-
-struct GetParamAsString {
-  template <class ParamType>
-  std::string operator()(const testing::TestParamInfo<ParamType>& info) const {
-    return base::StringPrintf("%s_%s", info.param.scenarioDir.c_str(),
-                              info.param.siteName.c_str());
-  }
-};
-
 }  // namespace
 
 namespace password_manager {
@@ -101,7 +63,7 @@
     : public InProcessBrowserTest,
       public captured_sites_test_utils::
           TestRecipeReplayChromeFeatureActionExecutor,
-      public ::testing::WithParamInterface<TestParams> {
+      public ::testing::WithParamInterface<CapturedSiteParams> {
  public:
   // TestRecipeReplayChromeFeatureActionExecutor:
   bool AddCredential(const std::string& origin,
@@ -203,14 +165,9 @@
         std::make_unique<captured_sites_test_utils::TestRecipeReplayer>(
             browser(), this);
     recipe_replayer()->Setup();
-
-    base::FilePath capture_file_path =
-        GetReplayFilesRootDirectory()
-            .AppendASCII(GetParam().scenarioDir.c_str())
-            .AppendASCII(GetParam().siteName.c_str());
-    SetServerUrlLoader(
-        std::make_unique<ServerUrlLoader>(std::make_unique<ServerCacheReplayer>(
-            capture_file_path,
+    SetServerUrlLoader(std::make_unique<ServerUrlLoader>(
+        std::make_unique<ServerCacheReplayer>(
+            GetParam().capture_file_path,
             ServerCacheReplayer::kOptionFailOnInvalidJsonRecord)));
   }
 
@@ -253,27 +210,18 @@
 };
 
 IN_PROC_BROWSER_TEST_P(CapturedSitesPasswordManagerBrowserTest, Recipe) {
-  // Craft the capture file path.
   base::FilePath src_dir;
   ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
-  base::FilePath capture_file_path =
-      GetReplayFilesRootDirectory()
-          .AppendASCII(GetParam().scenarioDir.c_str())
-          .AppendASCII(GetParam().siteName.c_str());
 
-  // Craft the recipe file path.
-  base::FilePath recipe_file_path =
-      GetReplayFilesRootDirectory()
-          .AppendASCII(GetParam().scenarioDir.c_str())
-          .AppendASCII(
-              base::StringPrintf("%s.test", GetParam().siteName.c_str()));
-
-  ASSERT_TRUE(
-      recipe_replayer()->ReplayTest(capture_file_path, recipe_file_path));
+  bool test_completed = recipe_replayer()->ReplayTest(
+      GetParam().capture_file_path, GetParam().recipe_file_path);
+  if (!test_completed)
+    ADD_FAILURE() << "Full execution was unable to complete.";
 }
 
-INSTANTIATE_TEST_SUITE_P(,
-                         CapturedSitesPasswordManagerBrowserTest,
-                         testing::ValuesIn(GetCapturedSites()),
-                         GetParamAsString());
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    CapturedSitesPasswordManagerBrowserTest,
+    testing::ValuesIn(GetCapturedSites(GetReplayFilesRootDirectory())),
+    GetParamAsString());
 }  // namespace password_manager
diff --git a/chrome/browser/password_manager/password_manager_util_win.cc b/chrome/browser/password_manager/password_manager_util_win.cc
index 25dda7e..5d74bba 100644
--- a/chrome/browser/password_manager/password_manager_util_win.cc
+++ b/chrome/browser/password_manager/password_manager_util_win.cc
@@ -340,8 +340,9 @@
   PasswordCheckPrefs* prefs_weak = prefs.get();
   OsPasswordStatus* status_weak = status.get();
   // This task calls ::LogonUser(), hence MayBlock().
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&GetOsPasswordStatusInternal, prefs_weak, status_weak),
       base::Bind(&ReplyOsPasswordStatus, base::Passed(&prefs),
                  base::Passed(&status)));
@@ -532,9 +533,9 @@
 }  // namespace
 
 void DelayReportOsPassword() {
-  base::PostDelayedTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                                  base::BindOnce(&GetOsPasswordStatus),
-                                  base::TimeDelta::FromSeconds(40));
+  base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+                        base::BindOnce(&GetOsPasswordStatus),
+                        base::TimeDelta::FromSeconds(40));
 }
 
 bool AuthenticateUser(gfx::NativeWindow window,
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index 8ba37ee..914b6fae 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -62,8 +62,8 @@
 Singleton g_performance_manager;
 
 scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner() {
-  return base::CreateSequencedTaskRunnerWithTraits(
-      {base::TaskPriority::USER_VISIBLE,
+  return base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()});
 }
 
diff --git a/chrome/browser/performance_manager/persistence/site_data/leveldb_site_data_store.cc b/chrome/browser/performance_manager/persistence/site_data/leveldb_site_data_store.cc
index 5132720..bf37f98c 100644
--- a/chrome/browser/performance_manager/persistence/site_data/leveldb_site_data_store.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/leveldb_site_data_store.cc
@@ -419,10 +419,11 @@
 }
 
 LevelDBSiteDataStore::LevelDBSiteDataStore(const base::FilePath& db_path)
-    : blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+    : blocking_task_runner_(base::CreateSequencedTaskRunner(
           // The |BLOCK_SHUTDOWN| trait is required to ensure that a clearing of
           // the database won't be skipped.
-          {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       async_helper_(new AsyncHelper(db_path),
                     base::OnTaskRunnerDeleter(blocking_task_runner_)) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
index c0024dd..c7b0717 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
@@ -21,8 +21,9 @@
 TEST(SiteDataCacheFacadeTest, IsDataCacheRecordingForTesting) {
   content::TestBrowserThreadBundle test_browser_thread_bundle;
   std::unique_ptr<SiteDataCacheFactory, base::OnTaskRunnerDeleter> factory(
-      SiteDataCacheFactory::CreateForTesting(
-          base::CreateSequencedTaskRunner({})));
+      SiteDataCacheFactory::CreateForTesting(base::CreateSequencedTaskRunner({
+          base::ThreadPool(),
+      })));
 
   TestingProfile profile;
   // Uses an in-memory database.
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
index 3c49d47..62f1191 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
@@ -19,7 +19,9 @@
 class SiteDataCacheFactoryTest : public ::testing::Test {
  protected:
   SiteDataCacheFactoryTest()
-      : task_runner_(base::CreateSequencedTaskRunner({})),
+      : task_runner_(base::CreateSequencedTaskRunner({
+            base::ThreadPool(),
+        })),
         factory_(SiteDataCacheFactory::CreateForTesting(task_runner_)) {}
 
   ~SiteDataCacheFactoryTest() override {
diff --git a/chrome/browser/performance_manager/web_contents_proxy_unittest.cc b/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
index 6526ec68..3055d68 100644
--- a/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
+++ b/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
@@ -53,7 +53,7 @@
         base::BindLambdaForTesting(
             [&deref_proxy, page_node,
              quit_loop = run_loop.QuitClosure()](GraphImpl* graph) {
-              base::PostTaskWithTraits(
+              base::PostTask(
                   FROM_HERE, {content::BrowserThread::UI},
                   base::BindOnce(deref_proxy, page_node->contents_proxy(),
                                  std::move(quit_loop)));
@@ -72,10 +72,10 @@
         base::BindLambdaForTesting([&contents, &deref_proxy, page_node,
                                     quit_loop = run_loop.QuitClosure()](
                                        GraphImpl* graph) {
-          base::PostTaskWithTraits(
+          base::PostTask(
               FROM_HERE, {content::BrowserThread::UI},
               base::BindLambdaForTesting([&contents]() { contents.reset(); }));
-          base::PostTaskWithTraits(
+          base::PostTask(
               FROM_HERE, {content::BrowserThread::UI},
               base::BindOnce(deref_proxy, page_node->contents_proxy(),
                              std::move(quit_loop)));
diff --git a/chrome/browser/performance_manager/webui_graph_dump_impl.cc b/chrome/browser/performance_manager/webui_graph_dump_impl.cc
index 04f08af..7b2754f 100644
--- a/chrome/browser/performance_manager/webui_graph_dump_impl.cc
+++ b/chrome/browser/performance_manager/webui_graph_dump_impl.cc
@@ -283,7 +283,7 @@
   if (!page_node->main_frame_url().is_valid())
     return;
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&FaviconRequestHelper::RequestFavicon,
                      base::Unretained(EnsureFaviconRequestHelper()),
@@ -295,13 +295,12 @@
   if (!frame_node->url().is_valid())
     return;
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&FaviconRequestHelper::RequestFavicon,
-                     base::Unretained(EnsureFaviconRequestHelper()),
-                     frame_node->url(),
-                     frame_node->page_node()->contents_proxy(),
-                     NodeBase::GetSerializationId(frame_node)));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&FaviconRequestHelper::RequestFavicon,
+                                base::Unretained(EnsureFaviconRequestHelper()),
+                                frame_node->url(),
+                                frame_node->page_node()->contents_proxy(),
+                                NodeBase::GetSerializationId(frame_node)));
 }
 
 void WebUIGraphDumpImpl::SendFrameNotification(FrameNodeImpl* frame,
diff --git a/chrome/browser/permissions/permission_request_manager.cc b/chrome/browser/permissions/permission_request_manager.cc
index 32780f0d..cd58b0568 100644
--- a/chrome/browser/permissions/permission_request_manager.cc
+++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -339,7 +339,7 @@
   if (!main_frame_has_fully_loaded_)
     return;
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&PermissionRequestManager::DequeueRequestsAndShowBubble,
                      weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/platform_util_mac.mm b/chrome/browser/platform_util_mac.mm
index 4965e6c..438c89ea 100644
--- a/chrome/browser/platform_util_mac.mm
+++ b/chrome/browser/platform_util_mac.mm
@@ -58,8 +58,8 @@
 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) {
   switch (type) {
     case OPEN_FILE:
-      base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                               base::BindOnce(&OpenFileOnMainThread, path));
+      base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                     base::BindOnce(&OpenFileOnMainThread, path));
       return;
     case OPEN_FOLDER:
       NSString* path_string = base::SysUTF8ToNSString(path.value());
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index e5cb08a..8824c094 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -306,7 +306,7 @@
 
    private:
     ~DestructionMessageFilter() override {
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE, {content::BrowserThread::UI},
           base::BindOnce(&ChannelDestructionWatcher::OnChannelDestroyed,
                          base::Unretained(watcher_)));
diff --git a/chrome/browser/prerender/prerender_message_filter.cc b/chrome/browser/prerender/prerender_message_filter.cc
index f8986ee..f4fcafb 100644
--- a/chrome/browser/prerender/prerender_message_filter.cc
+++ b/chrome/browser/prerender/prerender_message_filter.cc
@@ -99,7 +99,7 @@
 }
 
 void PrerenderMessageFilter::OnChannelClosing() {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&PrerenderMessageFilter::OnChannelClosingInUIThread,
                      this));
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index fc6bebf..228d286 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -133,9 +133,9 @@
                       &found_manifest);
       // There seems to be some flakiness in the appcache getting back to us, so
       // use a timeout task to try the appcache query again.
-      base::PostDelayedTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                                      wait_loop.QuitClosure(),
-                                      base::TimeDelta::FromMilliseconds(2000));
+      base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+                            wait_loop.QuitClosure(),
+                            base::TimeDelta::FromMilliseconds(2000));
       wait_loop.Run();
     } while (!found_manifest);
   }
@@ -207,7 +207,7 @@
         }
       }
     }
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, callback);
+    base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
   }
 
   base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/prerender/prerender_test_utils.cc b/chrome/browser/prerender/prerender_test_utils.cc
index d0ff9fb4..65e9363 100644
--- a/chrome/browser/prerender/prerender_test_utils.cc
+++ b/chrome/browser/prerender/prerender_test_utils.cc
@@ -102,7 +102,7 @@
     return true;
   }
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
                      this, gurl, client));
diff --git a/chrome/browser/profiles/OWNERS b/chrome/browser/profiles/OWNERS
index f990387..dc79f9deb 100644
--- a/chrome/browser/profiles/OWNERS
+++ b/chrome/browser/profiles/OWNERS
@@ -1,5 +1,6 @@
 droger@chromium.org
 msarda@chromium.org
+sdefresne@chromium.org
 
 # ProfileManager and GetDefaultProfile and related
 skuhne@chromium.org
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc
index 9a3acc9..dca9e5f 100644
--- a/chrome/browser/profiles/off_the_record_profile_io_data.cc
+++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -86,12 +86,12 @@
   io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled,
       profile_->GetPrefs());
   io_data_->safe_browsing_enabled()->MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
 #if BUILDFLAG(ENABLE_PLUGINS)
   io_data_->always_open_pdf_externally()->Init(
       prefs::kPluginsAlwaysOpenPdfExternally, profile_->GetPrefs());
   io_data_->always_open_pdf_externally()->MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
 #endif
   io_data_->InitializeOnUIThread(profile_);
 }
diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc
index 1c7dcd1..90b93ba 100644
--- a/chrome/browser/profiles/profile_attributes_storage.cc
+++ b/chrome/browser/profiles/profile_attributes_storage.cc
@@ -101,7 +101,7 @@
     return;
   }
 
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, callback);
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
 }
 
 void RunCallbackIfFileMissing(const base::FilePath& file_path,
@@ -109,7 +109,7 @@
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
   if (!base::PathExists(file_path))
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, callback);
+    base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
 }
 
 // Compares two ProfileAttributesEntry using locale-sensitive comparison of
@@ -142,8 +142,9 @@
 
 ProfileAttributesStorage::ProfileAttributesStorage(PrefService* prefs)
     : prefs_(prefs),
-      file_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      file_task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
 ProfileAttributesStorage::~ProfileAttributesStorage() {
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 6aa069eb..d79d3a14 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -684,7 +684,7 @@
   void WaitForDestruction() {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     DCHECK(!watcher_);
-    base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})
+    base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock()})
         ->PostTask(FROM_HERE,
                    base::BindOnce(&FileDestructionWatcher::StartWatchingPath,
                                   base::Unretained(this)));
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index ea2d00b..2b4214e1 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -285,10 +285,11 @@
 
   DVLOG(1) << "Creating directory " << path.value();
   if (base::CreateDirectory(path) && create_readme) {
-    base::PostTaskWithTraits(FROM_HERE,
-                             {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-                              base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-                             base::BindOnce(&CreateProfileReadme, path));
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+         base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+        base::BindOnce(&CreateProfileReadme, path));
   }
 }
 
@@ -339,8 +340,9 @@
   // this profile are executed in expected order (what was previously assured by
   // the FILE thread).
   scoped_refptr<base::SequencedTaskRunner> io_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
+           base::MayBlock()});
   if (create_mode == CREATE_MODE_ASYNCHRONOUS) {
     DCHECK(delegate);
     CreateProfileDirectory(io_task_runner.get(), path, true);
@@ -719,8 +721,9 @@
   // Page Load Capping was remove in M74, so the database file should be removed
   // when users upgrade Chrome.
   // TODO(ryansturm): Remove this after M-79. https://crbug.com/937489
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::LOWEST, base::MayBlock()},
       base::BindOnce(base::IgnoreResult(&base::DeleteFile),
                      GetPath().Append(chrome::kPageLoadCappingOptOutDBFilename),
                      false));
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 159b134..dc0948e2 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -104,9 +104,8 @@
 
   io_data_->set_data_reduction_proxy_io_data(
       CreateDataReductionProxyChromeIOData(
-          profile_,
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})));
+          profile_, base::CreateSingleThreadTaskRunner({BrowserThread::IO}),
+          base::CreateSingleThreadTaskRunner({BrowserThread::UI})));
 
 #if defined(OS_CHROMEOS)
   io_data_->data_reduction_proxy_io_data()
@@ -133,8 +132,9 @@
 
 void ProfileImplIOData::Handle::InitializeDataReductionProxy() const {
   scoped_refptr<base::SequencedTaskRunner> db_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   std::unique_ptr<data_reduction_proxy::DataStore> store(
       new data_reduction_proxy::DataStoreImpl(io_data_->profile_path_));
@@ -145,7 +145,7 @@
           content::BrowserContext::GetDefaultStoragePartition(profile_)
               ->GetURLLoaderFactoryForBrowserProcess(),
           std::move(store),
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
+          base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
           db_task_runner);
 }
 
@@ -161,12 +161,12 @@
   io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled,
       pref_service);
   io_data_->safe_browsing_enabled()->MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
 #if BUILDFLAG(ENABLE_PLUGINS)
   io_data_->always_open_pdf_externally()->Init(
       prefs::kPluginsAlwaysOpenPdfExternally, pref_service);
   io_data_->always_open_pdf_externally()->MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
 #endif
   io_data_->InitializeOnUIThread(profile_);
 }
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 657a5ec..c659651 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -170,10 +170,9 @@
   if (token_info.has_value() && token_info->slot != -1) {
     DVLOG(1) << "Got TPM slot for " << username_hash << ": "
              << token_info->slot;
-    base::PostTaskWithTraits(
-        FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(&crypto::InitializeTPMForChromeOSUser, username_hash,
-                       token_info->slot));
+    base::PostTask(FROM_HERE, {BrowserThread::IO},
+                   base::BindOnce(&crypto::InitializeTPMForChromeOSUser,
+                                  username_hash, token_info->slot));
   } else {
     NOTREACHED() << "TPMTokenInfoGetter reported invalid token.";
   }
@@ -204,7 +203,7 @@
                                           const std::string& username_hash) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&GetTPMInfoForUserOnUIThread, account_id, username_hash));
 }
@@ -290,7 +289,7 @@
     if (user && !user->username_hash().empty()) {
       params->username_hash = user->username_hash();
       DCHECK(!params->username_hash.empty());
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE, {BrowserThread::IO},
           base::BindOnce(&StartNSSInitOnIOThread, user->GetAccountId(),
                          user->username_hash(), profile->GetPath()));
@@ -319,10 +318,10 @@
   signed_exchange_enabled_.Init(prefs::kSignedHTTPExchangeEnabled,
                                 pref_service);
   signed_exchange_enabled_.MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
 
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO});
 
   // These members are used only for sign in, which is not enabled in incognito
   // and guest modes. So no need to initialize them.
@@ -363,9 +362,8 @@
   // object to the IO thread after this function.
   BrowserContext::EnsureResourceContextInitialized(profile);
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&ProfileIOData::Init, base::Unretained(this)));
+  base::PostTask(FROM_HERE, {BrowserThread::IO},
+                 base::BindOnce(&ProfileIOData::Init, base::Unretained(this)));
 }
 
 ProfileIOData::ProfileParams::ProfileParams() = default;
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 0b2c3233..a47db7d 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -909,9 +909,9 @@
   // This uses a separate loop, because deleting the profile from the
   // ProfileInfoCache will modify indices.
   for (const base::FilePath& profile_path : profiles_to_delete) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE,
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
         base::BindOnce(&NukeProfileFromDisk, profile_path));
 
@@ -937,16 +937,17 @@
       if (base::PathExists(profile_path)) {
         LOG(WARNING) << "Files of a deleted profile still exist after restart. "
                         "Cleaning up now.";
-        base::PostTaskWithTraitsAndReply(
+        base::PostTaskAndReply(
             FROM_HERE,
-            {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+            {base::ThreadPool(), base::MayBlock(),
+             base::TaskPriority::BEST_EFFORT,
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
             base::BindOnce(&NukeProfileFromDisk, profile_path),
             base::BindOnce(&ProfileCleanedUp, &value));
       } else {
         // Everything is fine, the profile was removed on shutdown.
-        base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                                 base::BindOnce(&ProfileCleanedUp, &value));
+        base::PostTask(FROM_HERE, {BrowserThread::UI},
+                       base::BindOnce(&ProfileCleanedUp, &value));
       }
     } else {
       LOG(ERROR) << "Found invalid profile path in deleted_profiles: "
@@ -1278,7 +1279,7 @@
   // persistent memory.
   PreviewsServiceFactory::GetForProfile(profile)->Initialize(
       g_browser_process->optimization_guide_service(), proto_db_provider,
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}),
+      base::CreateSingleThreadTaskRunner({BrowserThread::UI}),
       profile->GetPath());
 
   IdentityManagerFactory::GetForProfile(profile)->OnNetworkInitialized();
@@ -1316,9 +1317,9 @@
 #endif
 
   // Log the profile size after a reasonable startup delay.
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&ProfileSizeTask, profile->GetPath(), enabled_app_count),
       base::TimeDelta::FromSeconds(112));
@@ -1543,10 +1544,11 @@
   } else {
     // We failed to load the profile, but it's safe to delete a not yet loaded
     // Profile from disk.
-    base::PostTaskWithTraits(FROM_HERE,
-                             {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-                              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-                             base::BindOnce(&NukeProfileFromDisk, profile_dir));
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+        base::BindOnce(&NukeProfileFromDisk, profile_dir));
   }
 
   storage.RemoveProfile(profile_dir);
@@ -1628,7 +1630,7 @@
 
         // GetPrimaryAccountMutator() returns nullptr on ChromeOS only.
         DCHECK(account_mutator);
-        base::PostTaskWithTraits(
+        base::PostTask(
             FROM_HERE, {BrowserThread::UI},
             base::BindOnce(
                 base::IgnoreResult(
diff --git a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
index e91b613..2ab47ea 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
@@ -125,9 +125,9 @@
       const base::Location& location,
       const base::FilePath& shortcut_path,
       const base::win::ShortcutProperties& expected_properties) {
-    base::CreateCOMSTATaskRunnerWithTraits({})->PostTask(
-        location, base::Bind(&base::win::ValidateShortcut, shortcut_path,
-                             expected_properties));
+    base::CreateCOMSTATaskRunner({base::ThreadPool()})
+        ->PostTask(location, base::Bind(&base::win::ValidateShortcut,
+                                        shortcut_path, expected_properties));
     thread_bundle_.RunUntilIdle();
   }
 
@@ -202,7 +202,8 @@
       ShellUtil::ShortcutLocation shortcut_location,
       const ShellUtil::ShortcutProperties& properties) {
     base::PostTaskAndReplyWithResult(
-        base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()}).get(),
+        base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock()})
+            .get(),
         location,
         base::Bind(&ShellUtil::CreateOrUpdateShortcut, shortcut_location,
                    properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS),
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index e1fd9ec..1d1f975f 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -247,9 +247,8 @@
   } else {
     SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, icon_path.value().c_str(), NULL);
   }
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&OnProfileIconCreateSuccess, profile_path));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&OnProfileIconCreateSuccess, profile_path));
   return icon_path;
 }
 
@@ -831,7 +830,7 @@
 
 void ProfileShortcutManagerWin::RemoveProfileShortcuts(
     const base::FilePath& profile_path) {
-  base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})
+  base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock()})
       ->PostTask(FROM_HERE,
                  base::BindOnce(&DeleteDesktopShortcuts, profile_path, false));
 }
@@ -840,7 +839,8 @@
     const base::FilePath& profile_path,
     const base::Callback<void(bool)>& callback) {
   base::PostTaskAndReplyWithResult(
-      base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()}).get(),
+      base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock()})
+          .get(),
       FROM_HERE, base::Bind(&HasAnyProfileShortcuts, profile_path), callback);
 }
 
@@ -907,7 +907,7 @@
         UPDATE_EXISTING_ONLY, IGNORE_NON_PROFILE_SHORTCUTS);
   }
 
-  base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})
+  base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock()})
       ->PostTask(FROM_HERE,
                  base::BindOnce(&DeleteDesktopShortcuts, profile_path,
                                 deleting_down_to_last_profile));
@@ -1010,7 +1010,7 @@
       }
     }
   }
-  base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})
+  base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock()})
       ->PostTask(FROM_HERE,
                  base::BindOnce(
                      &CreateOrUpdateDesktopShortcutsAndIconForProfile, params));
diff --git a/chrome/browser/profiles/profile_statistics_unittest.cc b/chrome/browser/profiles/profile_statistics_unittest.cc
index 5a5cfb6..f75a535 100644
--- a/chrome/browser/profiles/profile_statistics_unittest.cc
+++ b/chrome/browser/profiles/profile_statistics_unittest.cc
@@ -50,10 +50,9 @@
 
 void LoadBookmarkModel(Profile* profile,
                        bookmarks::BookmarkModel* bookmark_model) {
-  bookmark_model->Load(profile->GetPrefs(), profile->GetPath(),
-                       profile->GetIOTaskRunner(),
-                       base::CreateSingleThreadTaskRunnerWithTraits(
-                           {content::BrowserThread::UI}));
+  bookmark_model->Load(
+      profile->GetPrefs(), profile->GetPath(), profile->GetIOTaskRunner(),
+      base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}));
 }
 
 bookmarks::BookmarkModel* CreateBookmarkModelWithoutLoad(Profile* profile) {
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc
index 5e1b3ef..efc1e4f 100644
--- a/chrome/browser/profiling_host/profiling_process_host.cc
+++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -140,13 +140,14 @@
       [](base::FilePath dest, SaveTraceFinishedCallback done, bool success,
          std::string trace) {
         if (!success) {
-          base::CreateSingleThreadTaskRunnerWithTraits(
-              {content::BrowserThread::UI})
+          base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
               ->PostTask(FROM_HERE, base::BindOnce(std::move(done), false));
           return;
         }
-        base::PostTaskWithTraits(
-            FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+        base::PostTask(
+            FROM_HERE,
+            {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+             base::MayBlock()},
             base::BindOnce(
                 &ProfilingProcessHost::SaveTraceToFileOnBlockingThread,
                 base::Unretained(ProfilingProcessHost::GetInstance()),
@@ -196,7 +197,7 @@
   gzFile gz_file = gzdopen(fd, "w");
   if (!gz_file) {
     DLOG(ERROR) << "Cannot compress trace file";
-    base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
+    base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
         ->PostTask(FROM_HERE, base::BindOnce(std::move(done), false));
     return;
   }
@@ -204,7 +205,7 @@
   size_t written_bytes = gzwrite(gz_file, trace.c_str(), trace.size());
   gzclose(gz_file);
 
-  base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
+  base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
       ->PostTask(FROM_HERE, base::BindOnce(std::move(done),
                                            written_bytes == trace.size()));
 }
diff --git a/chrome/browser/resources/chromeos/camera/OWNERS b/chrome/browser/resources/chromeos/camera/OWNERS
index e8bf71e..a879800 100644
--- a/chrome/browser/resources/chromeos/camera/OWNERS
+++ b/chrome/browser/resources/chromeos/camera/OWNERS
@@ -1,7 +1,6 @@
 henryhsu@chromium.org
 inker@chromium.org
 jcliang@chromium.org
-shenghao@chromium.org
 shik@chromium.org
 wtlee@chromium.org
 yuli@chromium.org
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
index 14500c54..eda804c0 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog/internet_detail_dialog.js
@@ -560,8 +560,6 @@
           'Cellular.MIN');
     } else if (type == CrOnc.Type.WI_FI) {
       fields.push('RestrictedConnectivity');
-    } else if (type == CrOnc.Type.WI_MAX) {
-      fields.push('RestrictedConnectivity', 'WiMAX.EAP.Identity');
     }
     fields.push('MacAddress');
     return fields;
diff --git a/chrome/browser/resources/chromeos/login/network_select_login.js b/chrome/browser/resources/chromeos/login/network_select_login.js
index c7834e1..969795b 100644
--- a/chrome/browser/resources/chromeos/login/network_select_login.js
+++ b/chrome/browser/resources/chromeos/login/network_select_login.js
@@ -115,7 +115,6 @@
         OncTypeTether: loadTimeData.getString('OncTypeTether'),
         OncTypeVPN: loadTimeData.getString('OncTypeVPN'),
         OncTypeWiFi: loadTimeData.getString('OncTypeWiFi'),
-        OncTypeWiMAX: loadTimeData.getString('OncTypeWiMAX'),
         networkListItemConnected:
             loadTimeData.getString('networkListItemConnected'),
         networkListItemConnecting:
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.js b/chrome/browser/resources/chromeos/network_ui/network_ui.js
index 21eab80..3224232 100644
--- a/chrome/browser/resources/chromeos/network_ui/network_ui.js
+++ b/chrome/browser/resources/chromeos/network_ui/network_ui.js
@@ -30,7 +30,6 @@
     OncTypeTether: loadTimeData.getString('OncTypeTether'),
     OncTypeVPN: loadTimeData.getString('OncTypeVPN'),
     OncTypeWiFi: loadTimeData.getString('OncTypeWiFi'),
-    OncTypeWiMAX: loadTimeData.getString('OncTypeWiMAX'),
     networkListItemConnected:
         loadTimeData.getString('networkListItemConnected'),
     networkListItemConnecting:
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
index fe9bcac..91fe93e 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.js
@@ -146,7 +146,6 @@
       OncTypeTether: loadTimeData.getString('OncTypeTether'),
       OncTypeVPN: loadTimeData.getString('OncTypeVPN'),
       OncTypeWiFi: loadTimeData.getString('OncTypeWiFi'),
-      OncTypeWiMAX: loadTimeData.getString('OncTypeWiMAX'),
       networkListItemConnected:
           loadTimeData.getString('networkListItemConnected'),
       networkListItemConnecting:
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index 1df5974..cc9cca88 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -798,7 +798,7 @@
         return false;
       }
     }
-    if ((type == CrOnc.Type.WI_FI || type == CrOnc.Type.WI_MAX) &&
+    if (type == CrOnc.Type.WI_FI &&
         CrOnc.isConnectingOrConnected(networkProperties)) {
       return false;
     }
@@ -1392,8 +1392,6 @@
       }
     } else if (type == CrOnc.Type.WI_FI) {
       fields.push('RestrictedConnectivity');
-    } else if (type == CrOnc.Type.WI_MAX) {
-      fields.push('RestrictedConnectivity', 'WiMAX.EAP.Identity');
     }
     return fields;
   },
@@ -1445,8 +1443,6 @@
           'WiFi.SSID', 'WiFi.BSSID', 'WiFi.SignalStrength', 'WiFi.Security',
           'WiFi.EAP.Outer', 'WiFi.EAP.Inner', 'WiFi.EAP.SubjectMatch',
           'WiFi.EAP.Identity', 'WiFi.EAP.AnonymousIdentity', 'WiFi.Frequency');
-    } else if (type == CrOnc.Type.WI_MAX) {
-      fields.push('WiFi.SignalStrength');
     }
     return fields;
   },
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js
index 0b5b7863..5bd9634 100644
--- a/chrome/browser/resources/settings/internet_page/internet_subpage.js
+++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -4,7 +4,7 @@
 
 /**
  * @fileoverview Polymer element for displaying information about WiFi,
- * WiMAX, or virtual networks.
+ * Cellular, or virtual networks.
  */
 
 (function() {
@@ -402,8 +402,6 @@
         return this.i18n('internetToggleMobileA11yLabel');
       case mojom.NetworkType.kWiFi:
         return this.i18n('internetToggleWiFiA11yLabel');
-      case mojom.NetworkType.kWiMAX:
-        return this.i18n('internetToggleWiMAXA11yLabel');
     }
     assertNotReached();
     return '';
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js
index 70b08bd..842e1f7 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -4,7 +4,7 @@
 
 /**
  * @fileoverview Polymer element for displaying a summary of network states
- * by type: Ethernet, WiFi, Cellular, WiMAX, and VPN.
+ * by type: Ethernet, WiFi, Cellular, and VPN.
  */
 
 (function() {
@@ -177,7 +177,6 @@
       mojom.NetworkType.kWiFi,
       mojom.NetworkType.kCellular,
       mojom.NetworkType.kTether,
-      mojom.NetworkType.kWiMAX,
       mojom.NetworkType.kVPN,
     ];
 
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js
index 326cf06..95c7176 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -211,7 +211,6 @@
       case mojom.NetworkType.kTether:
         return true;
       case mojom.NetworkType.kWiFi:
-      case mojom.NetworkType.kWiMAX:
         return deviceState.deviceState != mojom.DeviceStateType.kUninitialized;
       case mojom.NetworkType.kCellular:
         return deviceState.deviceState !=
@@ -248,8 +247,6 @@
         return this.i18n('internetToggleMobileA11yLabel');
       case mojom.NetworkType.kWiFi:
         return this.i18n('internetToggleWiFiA11yLabel');
-      case mojom.NetworkType.kWiMAX:
-        return this.i18n('internetToggleWiMAXA11yLabel');
     }
     assertNotReached();
     return '';
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js
index bda40537..fdbbef2 100644
--- a/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -144,7 +144,6 @@
       OncTypeTether: loadTimeData.getString('OncTypeTether'),
       OncTypeVPN: loadTimeData.getString('OncTypeVPN'),
       OncTypeWiFi: loadTimeData.getString('OncTypeWiFi'),
-      OncTypeWiMAX: loadTimeData.getString('OncTypeWiMAX'),
       networkListItemConnected:
           loadTimeData.getString('networkListItemConnected'),
       networkListItemConnecting:
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index 111082f0..762e7c92 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -221,12 +221,9 @@
         sync_password_hash_provider, cache_manager_.get());
   }
 
-  content::BrowserContext* CreateBrowserContext() override {
-    TestingProfile::Builder builder;
-    std::unique_ptr<TestingProfile> profile =
-        IdentityTestEnvironmentProfileAdaptor::
-            CreateProfileForIdentityTestEnvironment(builder);
-    return profile.release();
+  TestingProfile::TestingFactories GetTestingFactories() const override {
+    return IdentityTestEnvironmentProfileAdaptor::
+        GetIdentityTestEnvironmentFactories();
   }
 
   syncer::FakeUserEventService* GetUserEventService() {
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index f5f02a0..99bbfd3 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -224,7 +224,7 @@
       pref_service_->GetBoolean(prefs::kNtpShortcutsVisible);
 
   if (profile_ && profile_->GetResourceContext()) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::IO},
         base::BindOnce(&InstantIOContext::SetUserDataOnIO,
                        profile->GetResourceContext(), instant_io_context_));
@@ -274,10 +274,9 @@
   process_ids_.insert(process_id);
 
   if (instant_io_context_.get()) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::IO},
-        base::BindOnce(&InstantIOContext::AddInstantProcessOnIO,
-                       instant_io_context_, process_id));
+    base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                   base::BindOnce(&InstantIOContext::AddInstantProcessOnIO,
+                                  instant_io_context_, process_id));
   }
 }
 
@@ -495,8 +494,9 @@
 }
 
 void InstantService::SelectLocalBackgroundImage(const base::FilePath& path) {
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(&CopyFileToProfilePath, path, profile_->GetPath()),
       base::BindOnce(&InstantService::SetBackgroundToLocalResource,
                      weak_ptr_factory_.GetWeakPtr()));
@@ -520,10 +520,9 @@
   process_ids_.clear();
 
   if (instant_io_context_.get()) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::IO},
-        base::BindOnce(&InstantIOContext::ClearInstantProcessesOnIO,
-                       instant_io_context_));
+    base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                   base::BindOnce(&InstantIOContext::ClearInstantProcessesOnIO,
+                                  instant_io_context_));
   }
 
   if (most_visited_sites_) {
@@ -593,10 +592,9 @@
   process_ids_.erase(process_id);
 
   if (instant_io_context_.get()) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::IO},
-        base::BindOnce(&InstantIOContext::RemoveInstantProcessOnIO,
-                       instant_io_context_, process_id));
+    base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                   base::BindOnce(&InstantIOContext::RemoveInstantProcessOnIO,
+                                  instant_io_context_, process_id));
   }
 }
 
@@ -882,8 +880,8 @@
   // Calculate the bitmap color asynchronously as it is slow (1-2 seconds for
   // the thumbnail). However, prefs should be updated on the main thread.
   if (!fetched_image.IsEmpty()) {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::ThreadPool(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&GetBitmapMainColor, *fetched_image.ToSkBitmap()),
         base::BindOnce(&InstantService::UpdateCustomBackgroundPrefsWithColor,
                        weak_ptr_factory_.GetWeakPtr(), timestamp));
@@ -941,8 +939,9 @@
 void InstantService::RemoveLocalBackgroundImageCopy() {
   base::FilePath path = profile_->GetPath().AppendASCII(
       chrome::kChromeSearchLocalNtpBackgroundFilename);
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock()},
       base::BindOnce(IgnoreResult(&base::DeleteFile), path, false));
 }
 
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index 72068d9..7f35f4f 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -841,8 +841,10 @@
   }
 
   if (stripped_path == chrome::kChromeSearchLocalNtpBackgroundFilename) {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+         base::MayBlock()},
         base::BindOnce(&ReadBackgroundImageData, profile_->GetPath()),
         base::BindOnce(&ServeBackgroundImageData, callback));
     return;
diff --git a/chrome/browser/sharing/shared_clipboard/feature_flags.cc b/chrome/browser/sharing/shared_clipboard/feature_flags.cc
new file mode 100644
index 0000000..6a8fc501
--- /dev/null
+++ b/chrome/browser/sharing/shared_clipboard/feature_flags.cc
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sharing/shared_clipboard/feature_flags.h"
+
+const base::Feature kSharedClipboardReceiver{"SharedClipboardReceiver",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kSharedClipboardUI{"SharedClipboardUI",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/sharing/shared_clipboard/feature_flags.h b/chrome/browser/sharing/shared_clipboard/feature_flags.h
new file mode 100644
index 0000000..79a7579
--- /dev/null
+++ b/chrome/browser/sharing/shared_clipboard/feature_flags.h
@@ -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.
+
+#ifndef CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_FEATURE_FLAGS_H_
+#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_FEATURE_FLAGS_H_
+
+#include "base/feature_list.h"
+
+// Feature to allow devices to receive the shared clipboard message.
+extern const base::Feature kSharedClipboardReceiver;
+
+// Feature to allow shared clipbpard gets processed.
+extern const base::Feature kSharedClipboardUI;
+
+#endif  // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_FEATURE_FLAGS_H_
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc
index d4be8f0c..1b12dc2 100644
--- a/chrome/browser/sharing/sharing_service.cc
+++ b/chrome/browser/sharing/sharing_service.cc
@@ -173,7 +173,7 @@
   std::string message_guid = base::GenerateGUID();
   send_message_callbacks_.emplace(message_guid, std::move(callback));
 
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE, {base::TaskPriority::BEST_EFFORT, content::BrowserThread::UI},
       base::BindOnce(&SharingService::InvokeSendMessageCallback,
                      weak_ptr_factory_.GetWeakPtr(), message_guid,
@@ -314,7 +314,7 @@
       backoff_entry_.InformOfRequest(false);
       // Transient error - try again after a delay.
       LOG(ERROR) << "Device registration failed with transient error";
-      base::PostDelayedTaskWithTraits(
+      base::PostDelayedTask(
           FROM_HERE,
           {base::TaskPriority::BEST_EFFORT, content::BrowserThread::UI},
           base::BindOnce(&SharingService::RegisterDevice,
diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc
index b8f6132..8bf187e 100644
--- a/chrome/browser/signin/account_consistency_mode_manager.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager.cc
@@ -13,6 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager_factory.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
@@ -26,13 +27,19 @@
 
 using signin::AccountConsistencyMethod;
 
+// TODO(droger): Verify if this feature flag is still required now that
+// DICE migration was enabled by default for all users.
 const base::Feature kAccountConsistencyFeature{
     "AccountConsistency", base::FEATURE_ENABLED_BY_DEFAULT};
 const char kAccountConsistencyFeatureMethodParameter[] = "method";
 const char kAccountConsistencyFeatureMethodMirror[] = "mirror";
 const char kAccountConsistencyFeatureMethodDiceMigration[] = "dice_migration";
+// TODO(msalama): Remove this method.
 const char kAccountConsistencyFeatureMethodDice[] = "dice";
 
+const base::Feature kForceDiceMigration{"ForceDiceMigration",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
+
 namespace {
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -58,15 +65,12 @@
 };
 
 DiceMigrationStatus GetDiceMigrationStatus(
-    AccountConsistencyMethod account_consistency,
-    bool is_ready_for_dice) {
+    AccountConsistencyMethod account_consistency) {
   switch (account_consistency) {
     case AccountConsistencyMethod::kDice:
       return DiceMigrationStatus::kEnabled;
     case AccountConsistencyMethod::kDiceMigration:
-      return is_ready_for_dice
-                 ? DiceMigrationStatus::kDisabledReadyForMigration
-                 : DiceMigrationStatus::kDisabledNotReadyForMigration;
+      return DiceMigrationStatus::kDisabledNotReadyForMigration;
     case AccountConsistencyMethod::kDisabled:
       return DiceMigrationStatus::kDisabled;
     case AccountConsistencyMethod::kMirror:
@@ -109,23 +113,26 @@
   account_consistency_ = ComputeAccountConsistencyMethod(profile_);
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
-  bool is_ready_for_dice = false;
-  if (account_consistency_ == AccountConsistencyMethod::kDiceMigration) {
-    is_ready_for_dice = IsReadyForDiceMigration(profile_);
-    if (is_ready_for_dice) {
-      VLOG(1) << "Profile is migrating to Dice";
-      prefs->SetBoolean(kDiceMigrationCompletePref, true);
+  if (signin::DiceMethodGreaterOrEqual(
+          account_consistency_, AccountConsistencyMethod::kDiceMigration)) {
+    if (IsReadyForDiceMigration(profile_)) {
+      // Note: Even when |account_consistency_| is kDice, there may be cases
+      // when |kDiceMigrationCompletePref| preference is not set (e.g. browser
+      // tests that force set DICE state to kDice).
+      SetDiceMigrationCompleted();
       account_consistency_ = AccountConsistencyMethod::kDice;
-    } else {
+    }
+
+    if (account_consistency_ == AccountConsistencyMethod::kDiceMigration) {
       UMA_HISTOGRAM_BOOLEAN(
           "Signin.TokenServiceDiceCompatible",
           prefs->GetBoolean(prefs::kTokenServiceDiceCompatible));
     }
   }
-  UMA_HISTOGRAM_ENUMERATION(
-      kDiceMigrationStatusHistogram,
-      GetDiceMigrationStatus(account_consistency_, is_ready_for_dice),
-      DiceMigrationStatus::kDiceMigrationStatusCount);
+
+  UMA_HISTOGRAM_ENUMERATION(kDiceMigrationStatusHistogram,
+                            GetDiceMigrationStatus(account_consistency_),
+                            DiceMigrationStatus::kDiceMigrationStatusCount);
 #endif
 
   DCHECK_EQ(account_consistency_, ComputeAccountConsistencyMethod(profile_));
@@ -164,6 +171,11 @@
 }
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
+void AccountConsistencyModeManager::SetDiceMigrationCompleted() {
+  VLOG(1) << "Dice migration completed.";
+  profile_->GetPrefs()->SetBoolean(kDiceMigrationCompletePref, true);
+}
+
 void AccountConsistencyModeManager::SetReadyForDiceMigration(bool is_ready) {
   SetDiceMigrationOnStartup(profile_->GetPrefs(), is_ready);
 }
@@ -182,6 +194,11 @@
          (profile->IsNewProfile() ||
           profile->GetPrefs()->GetBoolean(kDiceMigrationOnStartupPref));
 }
+
+// static
+bool AccountConsistencyModeManager::IsDiceMigrationCompleted(Profile* profile) {
+  return profile->GetPrefs()->GetBoolean(kDiceMigrationCompletePref);
+}
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
 // static
@@ -277,9 +294,16 @@
     return AccountConsistencyMethod::kDisabled;
   }
 
-  if (method == AccountConsistencyMethod::kDiceMigration &&
-      profile->GetPrefs()->GetBoolean(kDiceMigrationCompletePref)) {
-    return AccountConsistencyMethod::kDice;
+  if (method == AccountConsistencyMethod::kDiceMigration) {
+    if (IsDiceMigrationCompleted(profile))
+      return AccountConsistencyMethod::kDice;
+
+    if (!IsReadyForDiceMigration(profile) &&
+        profile->GetPrefs()->GetBoolean(prefs::kTokenServiceDiceCompatible) &&
+        base::FeatureList::IsEnabled(kForceDiceMigration)) {
+      // Force migration to Dice.
+      return AccountConsistencyMethod::kDice;
+    }
   }
 
   return method;
diff --git a/chrome/browser/signin/account_consistency_mode_manager.h b/chrome/browser/signin/account_consistency_mode_manager.h
index 9fef873..b6c46fe4 100644
--- a/chrome/browser/signin/account_consistency_mode_manager.h
+++ b/chrome/browser/signin/account_consistency_mode_manager.h
@@ -32,6 +32,8 @@
 extern const char kAccountConsistencyFeatureMethodDiceMigration[];
 extern const char kAccountConsistencyFeatureMethodDice[];
 
+extern const base::Feature kForceDiceMigration;
+
 // Manages the account consistency mode for each profile.
 class AccountConsistencyModeManager : public KeyedService {
  public:
@@ -50,6 +52,12 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   // Schedules migration to happen at next startup.
   void SetReadyForDiceMigration(bool is_ready);
+  // Sets migration to Dice as completed.
+  void SetDiceMigrationCompleted();
+  // Returns true if migration can happen on the next startup.
+  static bool IsReadyForDiceMigration(Profile* profile);
+  // Returns true if migration to Dice is completed.
+  static bool IsDiceMigrationCompleted(Profile* profile);
 #endif
 
   // If true, then account management is done through Gaia webpages.
@@ -81,14 +89,13 @@
                            SigninAllowedChangesDiceState);
   FRIEND_TEST_ALL_PREFIXES(AccountConsistencyModeManagerTest,
                            DisallowSigninSwitch);
+  FRIEND_TEST_ALL_PREFIXES(AccountConsistencyModeManagerTest,
+                           ForceDiceMigration);
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   // Schedules migration to happen at next startup. Exposed as a static function
   // for testing.
   static void SetDiceMigrationOnStartup(PrefService* prefs, bool migrate);
-
-  // Returns true if migration can happen on the next startup.
-  static bool IsReadyForDiceMigration(Profile* profile);
 #endif
 
   // Returns the account consistency method for the current profile.
diff --git a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
index 7cf4ecf..c0c7261 100644
--- a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
+++ b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
@@ -190,6 +190,37 @@
   }
 }
 
+TEST(AccountConsistencyModeManagerTest, ForceDiceMigration) {
+  content::TestBrowserThreadBundle test_thread_bundle;
+  std::unique_ptr<TestingProfile> profile =
+      BuildTestingProfile(/*is_new_profile=*/false);
+  EXPECT_EQ(signin::AccountConsistencyMethod::kDiceMigration,
+            AccountConsistencyModeManager::GetMethodForProfile(profile.get()));
+  base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_feature_list_.InitAndEnableFeature(kForceDiceMigration);
+  profile->GetPrefs()->SetBoolean(prefs::kTokenServiceDiceCompatible, true);
+  {
+    AccountConsistencyModeManager manager(profile.get());
+    EXPECT_EQ(signin::AccountConsistencyMethod::kDice,
+              manager.GetAccountConsistencyMethod());
+    EXPECT_FALSE(manager.IsReadyForDiceMigration(profile.get()));
+    // Migration is not completed yet, |kDiceMigrationCompletePref| should not
+    // be written.
+    EXPECT_FALSE(manager.IsDiceMigrationCompleted(profile.get()));
+  }
+
+  AccountConsistencyModeManager::SetDiceMigrationOnStartup(profile->GetPrefs(),
+                                                           true);
+  {
+    AccountConsistencyModeManager manager(profile.get());
+    EXPECT_TRUE(manager.IsReadyForDiceMigration(profile.get()));
+    EXPECT_EQ(signin::AccountConsistencyMethod::kDice,
+              manager.GetAccountConsistencyMethod());
+    // Migration completed.
+    EXPECT_TRUE(manager.IsDiceMigrationCompleted(profile.get()));
+  }
+}
+
 // Checks that new profiles are migrated at creation.
 TEST(AccountConsistencyModeManagerTest, NewProfile) {
   content::TestBrowserThreadBundle test_thread_bundle;
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc
index a0685d5..629ad112 100644
--- a/chrome/browser/signin/account_reconcilor_factory.cc
+++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -192,7 +192,9 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
       return std::make_unique<signin::DiceAccountReconcilorDelegate>(
           ChromeSigninClientFactory::GetForProfile(profile),
-          account_consistency);
+          account_consistency,
+          account_consistency == signin::AccountConsistencyMethod::kDice &&
+              AccountConsistencyModeManager::IsDiceMigrationCompleted(profile));
 #else
       NOTREACHED();
       return nullptr;
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index a373185..e8811b7 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -325,6 +325,15 @@
 #endif
 }
 
+void ChromeSigninClient::SetDiceMigrationCompleted() {
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+  AccountConsistencyModeManager::GetForProfile(profile_)
+      ->SetDiceMigrationCompleted();
+#else
+  NOTREACHED();
+#endif
+}
+
 void ChromeSigninClient::SetReadyForDiceMigration(bool is_ready) {
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   AccountConsistencyModeManager::GetForProfile(profile_)
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index 27dd0124..6c6f749 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -79,6 +79,7 @@
   void OnConnectionChanged(network::mojom::ConnectionType type) override;
 #endif
 
+  void SetDiceMigrationCompleted() override;
   void SetReadyForDiceMigration(bool is_ready) override;
 
   // Used in tests to override the URLLoaderFactory returned by
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 1001abb..0db7941 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -103,7 +103,7 @@
   }
 
   void DestroyOnUIAfterDelay() {
-    base::PostDelayedTaskWithTraits(
+    base::PostDelayedTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(base::DoNothing::Once<
                            scoped_refptr<AccountReconcilorLockWrapper>>(),
@@ -386,9 +386,9 @@
 
   // Post a task even if we are already on the UI thread to avoid making any
   // requests while processing a throttle event.
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(ProcessMirrorHeaderUIThread, params,
-                                          response->GetWebContentsGetter()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(ProcessMirrorHeaderUIThread, params,
+                                response->GetWebContentsGetter()));
 }
 
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -423,10 +423,9 @@
 
   // Post a task even if we are already on the UI thread to avoid making any
   // requests while processing a throttle event.
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(ProcessDiceHeaderUIThread, std::move(params),
-                     response->GetWebContentsGetter()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(ProcessDiceHeaderUIThread, std::move(params),
+                                response->GetWebContentsGetter()));
 }
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 
@@ -493,7 +492,7 @@
     if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
       lock_wrapper->CreateLockOnUI(request->GetWebContentsGetter());
     } else {
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE, {content::BrowserThread::UI},
           base::BindOnce(&AccountReconcilorLockWrapper::CreateLockOnUI,
                          lock_wrapper, request->GetWebContentsGetter()));
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
index 68c54ab..d1bf31f5 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
@@ -472,12 +472,12 @@
       base::BindRepeating(&content::WebContents::FromFrameTreeNodeId,
                           render_frame_host->GetFrameTreeNodeId());
 
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
-                           base::BindOnce(&ResourceContextData::StartProxying,
-                                          profile->GetResourceContext(),
-                                          std::move(web_contents_getter),
-                                          std::move(proxied_receiver),
-                                          std::move(target_factory_info)));
+  base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                 base::BindOnce(&ResourceContextData::StartProxying,
+                                profile->GetResourceContext(),
+                                std::move(web_contents_getter),
+                                std::move(proxied_receiver),
+                                std::move(target_factory_info)));
   return true;
 }
 
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc
index 804e7f2..f51d5e5 100644
--- a/chrome/browser/signin/dice_browsertest.cc
+++ b/chrome/browser/signin/dice_browsertest.cc
@@ -128,7 +128,7 @@
                        base::ThreadTaskRunnerHandle::Get(), FROM_HERE,
                        std::move(unblock_io_thread));
     // Pass |unblock_any_thread| to the caller on the UI thread.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(std::move(callback_), std::move(unblock_any_thread)));
   }
@@ -159,8 +159,8 @@
   if (it != request.headers.end())
     header_value = it->second;
 
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindRepeating(callback, header_value));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindRepeating(callback, header_value));
 
   // Add the SIGNIN dice header.
   std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
@@ -280,7 +280,7 @@
   if (!net::test_server::ShouldHandle(request, kOAuth2TokenRevokeURL))
     return nullptr;
 
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, callback);
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
 
   std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
   http_response->AddCustomHeader("Cache-Control", "no-store");
@@ -301,8 +301,8 @@
   auto it = request.headers.find(signin::kDiceRequestHeader);
   if (it != request.headers.end())
     dice_request_header = it->second;
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindRepeating(callback, dice_request_header));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindRepeating(callback, dice_request_header));
 
   std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
   http_response->AddCustomHeader("Cache-Control", "no-store");
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index ccfe4b16..c994e82 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -115,7 +115,8 @@
     AboutSigninInternals::RegisterPrefs(pref_service_.registry());
     auto account_reconcilor_delegate =
         std::make_unique<signin::DiceAccountReconcilorDelegate>(
-            &signin_client_, signin::AccountConsistencyMethod::kDiceMigration);
+            &signin_client_, signin::AccountConsistencyMethod::kDiceMigration,
+            /*migration_completed=*/false);
     account_reconcilor_ = std::make_unique<AccountReconcilor>(
         identity_test_env_.identity_manager(), &signin_client_,
         std::move(account_reconcilor_delegate));
diff --git a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
index b94a70a7..a2faab8 100644
--- a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
+++ b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
@@ -895,8 +895,8 @@
     if (text_received_)
       return;
 
-    auto ui_task_runner = base::CreateSingleThreadTaskRunnerWithTraits(
-        {content::BrowserThread::UI});
+    auto ui_task_runner =
+        base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
     ui_task_runner->PostDelayedTask(
         FROM_HERE,
         base::BindOnce(&MockSpellCheckHost::Timeout, base::Unretained(this)),
@@ -1007,8 +1007,8 @@
     if (!spell_check_hosts_.empty())
       return;
 
-    auto ui_task_runner = base::CreateSingleThreadTaskRunnerWithTraits(
-        {content::BrowserThread::UI});
+    auto ui_task_runner =
+        base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
     ui_task_runner->PostDelayedTask(
         FROM_HERE,
         base::BindOnce(&SpellCheckBrowserTestHelper::Timeout,
diff --git a/chrome/browser/site_isolation/site_per_process_text_input_browsertest.cc b/chrome/browser/site_isolation/site_per_process_text_input_browsertest.cc
index 7e72ec9..e85e9fa2 100644
--- a/chrome/browser/site_isolation/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/site_isolation/site_per_process_text_input_browsertest.cc
@@ -1488,8 +1488,7 @@
 
         // Quit the run loop on IO to make sure the message handler of
         // TextInputClientMac has successfully run on UI thread.
-        base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
-                                 callback_on_io);
+        base::PostTask(FROM_HERE, {content::BrowserThread::IO}, callback_on_io);
       },
       child_process_id, child_frame_routing_id,
       test_complete_waiter.QuitClosure()));
@@ -1558,8 +1557,7 @@
 
         // Quit the run loop on IO to make sure the message handler of
         // TextInputClientMac has successfully run on UI thread.
-        base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
-                                 callback_on_io);
+        base::PostTask(FROM_HERE, {content::BrowserThread::IO}, callback_on_io);
       },
       main_frame_process_id, main_frame_routing_id,
       test_complete_waiter.QuitClosure()));
diff --git a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
index 61947ad..4a222148 100644
--- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
+++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
@@ -101,10 +101,9 @@
 
   // Check that the render frame type is appropriate, and whether or not we
   // need to request permission from the user.
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&CheckRenderFrameType, std::move(callback),
-                     render_process_id, render_frame_id));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&CheckRenderFrameType, std::move(callback),
+                                render_process_id, render_frame_id));
 }
 
 content::SpeechRecognitionEventListener*
@@ -139,7 +138,7 @@
     // This happens for extensions. Manifest should be checked for permission.
     allowed = true;
     check_permission = false;
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(std::move(callback), check_permission, allowed));
     return;
@@ -166,7 +165,7 @@
   check_permission = true;
 #endif
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(std::move(callback), check_permission, allowed));
 }
diff --git a/chrome/browser/speech/speech_recognizer.cc b/chrome/browser/speech/speech_recognizer.cc
index a49d3054..b740333 100644
--- a/chrome/browser/speech/speech_recognizer.cc
+++ b/chrome/browser/speech/speech_recognizer.cc
@@ -183,7 +183,7 @@
 
 void SpeechRecognizer::EventListener::NotifyRecognitionStateChanged(
     SpeechRecognizerStatus new_state) {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&SpeechRecognizerDelegate::OnSpeechRecognitionStateChanged,
                      delegate_, new_state));
@@ -228,7 +228,7 @@
       final_count++;
     result_str += result->hypotheses[0]->utterance;
   }
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&SpeechRecognizerDelegate::OnSpeechResult, delegate_,
                      result_str, final_count == results.size()));
@@ -275,7 +275,7 @@
   // Both |volume| and |noise_volume| are defined to be in the range [0.0, 1.0].
   // See: content/public/browser/speech_recognition_event_listener.h
   int16_t sound_level = static_cast<int16_t>(INT16_MAX * volume);
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&SpeechRecognizerDelegate::OnSpeechSoundLevelChanged,
                      delegate_, sound_level));
@@ -315,7 +315,7 @@
   std::string auth_token;
   delegate_->GetSpeechAuthParameters(&auth_scope, &auth_token);
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(&SpeechRecognizer::EventListener::StartOnIOThread,
                      speech_event_listener_, auth_scope, auth_token, preamble));
@@ -323,7 +323,7 @@
 
 void SpeechRecognizer::Stop() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(&SpeechRecognizer::EventListener::StopOnIOThread,
                      speech_event_listener_));
diff --git a/chrome/browser/speech/tts_message_filter.cc b/chrome/browser/speech/tts_message_filter.cc
index a7df91b..cf08416 100644
--- a/chrome/browser/speech/tts_message_filter.cc
+++ b/chrome/browser/speech/tts_message_filter.cc
@@ -67,7 +67,7 @@
 void TtsMessageFilter::OnChannelClosing() {
   base::AutoLock lock(mutex_);
   valid_ = false;
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&TtsMessageFilter::OnChannelClosingInUIThread, this));
 }
diff --git a/chrome/browser/storage/storage_info_fetcher.cc b/chrome/browser/storage/storage_info_fetcher.cc
index ba4f890..f922058 100644
--- a/chrome/browser/storage/storage_info_fetcher.cc
+++ b/chrome/browser/storage/storage_info_fetcher.cc
@@ -31,7 +31,7 @@
 
   // QuotaManager must be called on IO thread, but the callback must then be
   // called on the UI thread.
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(
           &StorageInfoFetcher::GetUsageInfo, this,
@@ -47,7 +47,7 @@
   clear_callback_ = clear_callback;
   type_to_delete_ = type;
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(
           &storage::QuotaManager::DeleteHostData, quota_manager_, host, type,
@@ -66,9 +66,8 @@
 
   entries_ = std::move(entries);
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&StorageInfoFetcher::OnFetchCompleted, this));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&StorageInfoFetcher::OnFetchCompleted, this));
 }
 
 void StorageInfoFetcher::OnFetchCompleted() {
@@ -85,7 +84,7 @@
 
   quota_manager_->ResetUsageTracker(type_to_delete_);
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&StorageInfoFetcher::OnClearCompleted, this, code));
 }
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
index 2c4eb64..1f7143f 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -215,7 +215,7 @@
   // Trigger a sync reconfig to enable/disable the right SU data types.
   // The logic to do this lives in the SupervisedUserSyncModelTypeController.
   // TODO(crbug.com/946473): Get rid of this hack and instead call
-  // ReadyForStartChanged from the controller.
+  // DataTypePreconditionChanged from the controller.
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
   if (sync_service->GetUserSettings()->IsFirstSetupComplete()) {
diff --git a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc
index 33e4c44..9ceadc1 100644
--- a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc
+++ b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.cc
@@ -27,7 +27,9 @@
 SupervisedUserSyncModelTypeController::
     ~SupervisedUserSyncModelTypeController() {}
 
-bool SupervisedUserSyncModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+SupervisedUserSyncModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return profile_->IsSupervised();
+  return profile_->IsSupervised() ? PreconditionState::kPreconditionsMet
+                                  : PreconditionState::kMustStopAndClearData;
 }
diff --git a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h
index be5feec..b7a277a92 100644
--- a/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h
+++ b/chrome/browser/supervised_user/supervised_user_sync_model_type_controller.h
@@ -29,7 +29,7 @@
   ~SupervisedUserSyncModelTypeController() override;
 
   // DataTypeController override.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
  private:
   const Profile* const profile_;
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index d30098a..fc374334 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -191,7 +191,7 @@
 
   component_factory_ = std::make_unique<ProfileSyncComponentsFactoryImpl>(
       this, chrome::GetChannel(), prefs::kSavingBrowserHistoryDisabled,
-      base::CreateSequencedTaskRunnerWithTraits({content::BrowserThread::UI}),
+      base::CreateSequencedTaskRunner({content::BrowserThread::UI}),
       web_data_service_thread_, profile_web_data_service_,
       account_web_data_service_, password_store_,
       BookmarkSyncServiceFactory::GetForProfile(profile_));
@@ -586,7 +586,7 @@
                                               syncer::GROUP_DB);
     case syncer::GROUP_UI:
       return new syncer::UIModelWorker(
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}));
+          base::CreateSingleThreadTaskRunner({BrowserThread::UI}));
     case syncer::GROUP_PASSIVE:
       return new syncer::PassiveModelWorker();
     case syncer::GROUP_PASSWORD: {
diff --git a/chrome/browser/sync/glue/sync_start_util.cc b/chrome/browser/sync/glue/sync_start_util.cc
index 18790b7..b047c82 100644
--- a/chrome/browser/sync/glue/sync_start_util.cc
+++ b/chrome/browser/sync/glue/sync_start_util.cc
@@ -42,8 +42,8 @@
 
 void StartSyncProxy(const base::FilePath& profile,
                     syncer::ModelType type) {
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(&StartSyncOnUIThread, profile, type));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&StartSyncOnUIThread, profile, type));
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index bb1d775..12fbbbac 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -91,10 +91,9 @@
 void UpdateNetworkTime(const base::Time& network_time,
                        const base::TimeDelta& resolution,
                        const base::TimeDelta& latency) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time, resolution,
-                     latency, base::TimeTicks::Now()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time,
+                                resolution, latency, base::TimeTicks::Now()));
 }
 
 }  // anonymous namespace
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
index b4bd270..7c391446 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
@@ -89,14 +89,16 @@
     ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
     in_memory_env_ = leveldb_chrome::NewMemEnv("DriveBackendSyncTest");
 
-    io_task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
-        {content::BrowserThread::IO});
-    worker_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+    io_task_runner_ =
+        base::CreateSingleThreadTaskRunner({content::BrowserThread::IO});
+    worker_task_runner_ = base::CreateSequencedTaskRunner(
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
     file_task_runner_ = io_task_runner_;
     scoped_refptr<base::SequencedTaskRunner> drive_task_runner =
-        base::CreateSequencedTaskRunnerWithTraits(
-            {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+        base::CreateSequencedTaskRunner(
+            {base::ThreadPool(), base::MayBlock(),
+             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
     RegisterSyncableFileSystem();
     local_sync_service_ = LocalFileSyncService::CreateForTesting(
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index 6cf5e759..017ab43 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -196,12 +196,14 @@
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
       base::ThreadTaskRunnerHandle::Get();
   scoped_refptr<base::SequencedTaskRunner> worker_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   scoped_refptr<base::SequencedTaskRunner> drive_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
   Profile* profile = Profile::FromBrowserContext(context);
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
index ce5f446..99f55e88 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
@@ -45,8 +45,9 @@
 
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
         base::ThreadTaskRunnerHandle::Get();
-    worker_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+    worker_task_runner_ = base::CreateSequencedTaskRunner(
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
     sync_engine_.reset(new drive_backend::SyncEngine(
         ui_task_runner.get(), worker_task_runner_.get(),
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
index b281d0cc..6476d6d 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -70,10 +70,8 @@
     in_memory_env_ = leveldb_chrome::NewMemEnv("LocalFileSyncContextTest");
 
     ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
-    io_task_runner_ =
-        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
-    file_task_runner_ =
-        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
+    io_task_runner_ = base::CreateSingleThreadTaskRunner({BrowserThread::IO});
+    file_task_runner_ = base::CreateSingleThreadTaskRunner({BrowserThread::IO});
   }
 
   void TearDown() override { RevokeSyncableFileSystem(); }
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service.cc b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
index f90d70f..ef7230f 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
@@ -346,10 +346,8 @@
       sync_context_(new LocalFileSyncContext(
           profile_->GetPath(),
           env_override,
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})
-              .get(),
-          base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
-              .get())),
+          base::CreateSingleThreadTaskRunner({BrowserThread::UI}).get(),
+          base::CreateSingleThreadTaskRunner({BrowserThread::IO}).get())),
       local_change_processor_(nullptr) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   sync_context_->AddOriginChangeObserver(this);
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
index 12b5784..46abf010 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_service_unittest.cc
@@ -117,8 +117,9 @@
 
     file_system_.reset(new CannedSyncableFileSystem(
         GURL(kOrigin), in_memory_env_.get(),
-        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-        base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})));
+        base::CreateSingleThreadTaskRunner({BrowserThread::IO}),
+        base::CreateSingleThreadTaskRunner(
+            {base::ThreadPool(), base::MayBlock()})));
 
     local_service_ = LocalFileSyncService::CreateForTesting(
         &profile_, in_memory_env_.get());
@@ -300,8 +301,9 @@
   const char kOrigin2[] = "http://foo";
   CannedSyncableFileSystem file_system2(
       GURL(kOrigin2), in_memory_env_.get(),
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-      base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}),
+      base::CreateSingleThreadTaskRunner(
+          {base::ThreadPool(), base::MayBlock()}));
   file_system2.SetUp(CannedSyncableFileSystem::QUOTA_ENABLED);
 
   base::RunLoop run_loop;
diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
index 07a8fc8..7ec7ccf 100644
--- a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
+++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc
@@ -270,7 +270,7 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     // It is safe to pass Unretained(this) (see comments in OpenFileSystem()).
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(&SyncFileSystemBackend::InitializeSyncFileSystemService,
                        base::Unretained(this), origin_url, callback));
@@ -300,7 +300,7 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     // It is safe to pass Unretained(this) since |context| owns it.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(
             &SyncFileSystemBackend::DidInitializeSyncFileSystemService,
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
index a2cd49b..18e5da70 100644
--- a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
+++ b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
@@ -78,7 +78,7 @@
 void VerifyFileError(base::Closure callback,
                      base::File::Error error) {
   EXPECT_EQ(base::File::FILE_OK, error);
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback);
+  base::PostTask(FROM_HERE, {BrowserThread::UI}, callback);
 }
 
 }  // namespace
@@ -135,8 +135,9 @@
     in_memory_env_ = leveldb_chrome::NewMemEnv("SyncFileSystemServiceTest");
     file_system_.reset(new CannedSyncableFileSystem(
         GURL(kOrigin), in_memory_env_.get(),
-        base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}),
-        base::CreateSingleThreadTaskRunnerWithTraits({base::MayBlock()})));
+        base::CreateSingleThreadTaskRunner({BrowserThread::IO}),
+        base::CreateSingleThreadTaskRunner(
+            {base::ThreadPool(), base::MayBlock()})));
 
     std::unique_ptr<LocalFileSyncService> local_service =
         LocalFileSyncService::CreateForTesting(&profile_, in_memory_env_.get());
@@ -423,7 +424,7 @@
 
   // Start a local operation on the same file (to make it BUSY).
   base::RunLoop verify_file_error_run_loop;
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&CannedSyncableFileSystem::DoCreateFile,
                      base::Unretained(file_system_.get()), kFile,
diff --git a/chrome/browser/ui/android/ssl_client_certificate_request.cc b/chrome/browser/ui/android/ssl_client_certificate_request.cc
index 9efd3b0..aa22bcb 100644
--- a/chrome/browser/ui/android/ssl_client_certificate_request.cc
+++ b/chrome/browser/ui/android/ssl_client_certificate_request.cc
@@ -379,8 +379,8 @@
   if (content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
     NotifyClientCertificatesChanged();
   } else {
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
-                             base::BindOnce(&NotifyClientCertificatesChanged));
+    base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                   base::BindOnce(&NotifyClientCertificatesChanged));
   }
 }
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_icon.cc b/chrome/browser/ui/app_list/arc/arc_app_icon.cc
index ddbccc65..78c1638 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_icon.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_icon.cc
@@ -275,8 +275,9 @@
   if (path.empty())
     return;
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(
           &ArcAppIcon::ReadOnFileThread, scale_factor, path,
           prefs->MaybeGetIconPathForDefaultApp(mapped_app_id_, descriptor)),
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index bfc4f935..54f858d 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -319,8 +319,9 @@
   void OnImageDecoded(const SkBitmap& bitmap) override {
     // See host_ comments.
     DCHECK(host_);
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&ResizeRequest::ResizeAndEncodeIconAsyncronously, bitmap,
                        descriptor_.GetSizeInPixels()),
         base::BindOnce(&ArcAppListPrefs::OnIconResized, host_, app_id_,
@@ -373,8 +374,9 @@
     : profile_(profile),
       prefs_(profile->GetPrefs()),
       app_connection_holder_for_testing_(app_connection_holder_for_testing),
-      file_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      file_task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
       weak_ptr_factory_(this) {
   VLOG(1) << "ARC app list prefs created";
diff --git a/chrome/browser/ui/app_list/arc/arc_default_app_list.cc b/chrome/browser/ui/app_list/arc/arc_default_app_list.cc
index 5301c74..166ea15 100644
--- a/chrome/browser/ui/app_list/arc/arc_default_app_list.cc
+++ b/chrome/browser/ui/app_list/arc/arc_default_app_list.cc
@@ -175,8 +175,9 @@
 
   // Once ready OnAppsReady is called.
   for (const auto& source : sources) {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&ReadAppsFromFileThread, source),
         base::BindOnce(&ArcDefaultAppList::OnAppsRead,
                        weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.cc b/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.cc
index bf2ea04..5aae292 100644
--- a/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.cc
+++ b/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.cc
@@ -35,18 +35,21 @@
   }
 }
 
-bool ArcPackageSyncModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+ArcPackageSyncModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return arc::IsArcPlayStoreEnabledForProfile(profile_);
+  return arc::IsArcPlayStoreEnabledForProfile(profile_)
+             ? PreconditionState::kPreconditionsMet
+             : PreconditionState::kMustStopAndClearData;
 }
 
 void ArcPackageSyncModelTypeController::OnArcPlayStoreEnabledChanged(
     bool enabled) {
   DCHECK(CalledOnValidThread());
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 void ArcPackageSyncModelTypeController::OnArcInitialStart() {
   DCHECK(CalledOnValidThread());
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
diff --git a/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h b/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h
index 7b0f7f6..1c5afa1 100644
--- a/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h
+++ b/chrome/browser/ui/app_list/arc/arc_package_sync_model_type_controller.h
@@ -31,7 +31,7 @@
   ~ArcPackageSyncModelTypeController() override;
 
   // DataTypeController overrides.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
   // ArcSessionManager::Observer:
   void OnArcPlayStoreEnabledChanged(bool enabled) override;
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_icon.cc b/chrome/browser/ui/app_list/crostini/crostini_app_icon.cc
index 1f106e4..5c78384 100644
--- a/chrome/browser/ui/app_list/crostini/crostini_app_icon.cc
+++ b/chrome/browser/ui/app_list/crostini/crostini_app_icon.cc
@@ -216,8 +216,9 @@
       registry_service_->GetIconPath(app_id_, scale_factor);
   DCHECK(!path.empty());
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&CrostiniAppIcon::ReadOnFileThread, scale_factor, path),
       base::BindOnce(&CrostiniAppIcon::OnIconRead,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
index 1303d4d5..3e12796 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_launch_event_logger.cc
@@ -86,8 +86,8 @@
               kDayDuration,
               kQuarterHoursInADay)),
       weak_factory_(this) {
-  task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::TaskPriority::BEST_EFFORT,
+  task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider.cc
index 2656813..463bdd55 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_list_launch_metrics_provider.cc
@@ -198,8 +198,8 @@
   const base::FilePath& proto_filepath = profile_dir.value().AppendASCII(
       AppListLaunchMetricsProvider::kStateProtoFilename);
 
-  PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()},
+  PostTaskAndReplyWithResult(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
       base::BindOnce(&LoadStateFromDisk, proto_filepath),
       base::BindOnce(&AppListLaunchMetricsProvider::OnStateLoaded,
                      weak_factory_.GetWeakPtr(), proto_filepath));
@@ -220,9 +220,8 @@
     LogMetricsProviderError(MetricsProviderError::kNoStateProto);
 
     AppListLaunchRecorderStateProto new_proto = GenerateStateProto();
-    PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock()},
-        base::BindOnce(&SaveStateToDisk, proto_filepath, new_proto));
+    PostTask(FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+             base::BindOnce(&SaveStateToDisk, proto_filepath, new_proto));
 
     secret_ = GetSecretFromProto(new_proto);
     user_id_ = new_proto.recurrence_ranker_user_id();
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.cc
index 713736e..8515a9d 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.cc
@@ -117,8 +117,8 @@
   if (is_ephemeral_user)
     return;
 
-  task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+  task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
   // Loads the predictor from disk asynchronously.
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
index 18fc35c..ed4dd5b 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker.cc
@@ -167,8 +167,8 @@
       time_of_last_save_(Time::Now()),
       weak_factory_(this) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+  task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
   targets_ = std::make_unique<FrecencyStore>(config.target_limit(),
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc
index 4c6dd01f..f849c6f 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_delegate.cc
@@ -348,7 +348,7 @@
 
   // Hold on to the keep alive for some time to give the app a chance to show
   // the window.
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&ChromeAppDelegate::RelinquishKeepAliveAfterTimeout,
                      weak_factory_.GetWeakPtr()),
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
index 34692041..c214195 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -68,7 +68,7 @@
 
 // User is waiting for the screenshot-taken notification, hence USER_VISIBLE.
 constexpr base::TaskTraits kBlockingTaskTraits = {
-    base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+    base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
     base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
 
 ChromeScreenshotGrabber* g_chrome_screenshot_grabber_instance = nullptr;
@@ -117,9 +117,8 @@
     return;
   }
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&DecodeFileAndCopyToClipboard, png_data));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&DecodeFileAndCopyToClipboard, png_data));
 }
 
 void ReadFileAndCopyToClipboardDrive(
@@ -131,9 +130,8 @@
                << drive::FileErrorToString(error);
     return;
   }
-  base::PostTaskWithTraits(
-      FROM_HERE, kBlockingTaskTraits,
-      base::BindOnce(&ReadFileAndCopyToClipboardLocal, file_path));
+  base::PostTask(FROM_HERE, kBlockingTaskTraits,
+                 base::BindOnce(&ReadFileAndCopyToClipboardLocal, file_path));
 }
 
 // Delegate for a notification. This class has two roles: to implement callback
@@ -176,7 +174,7 @@
                                base::Bind(&ReadFileAndCopyToClipboardDrive));
           return;
         }
-        base::PostTaskWithTraits(
+        base::PostTask(
             FROM_HERE, kBlockingTaskTraits,
             base::BindOnce(&ReadFileAndCopyToClipboardLocal, screenshot_path_));
         break;
@@ -254,7 +252,7 @@
   } else {
     LOG(ERROR) << "Failed to ensure the existence of the specified directory "
                << "in Google Drive: " << error;
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, kBlockingTaskTraits,
         base::BindOnce(callback, ScreenshotFileResult::CHECK_DIR_FAILED,
                        base::FilePath()));
@@ -508,10 +506,10 @@
     return;
   }
 
-  base::PostTaskWithTraits(
-      FROM_HERE,
-      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::BindOnce(EnsureLocalDirectoryExists, path, callback));
+  base::PostTask(FROM_HERE,
+                 {base::ThreadPool(), base::MayBlock(),
+                  base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+                 base::BindOnce(EnsureLocalDirectoryExists, path, callback));
 }
 
 void ChromeScreenshotGrabber::OnScreenshotCompleted(
@@ -528,7 +526,7 @@
     return;
 
   if (result != ScreenshotResult::SUCCESS) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
             &ChromeScreenshotGrabber::OnReadScreenshotFileForPreviewCompleted,
@@ -546,7 +544,7 @@
     if (!file_system) {
       LOG(ERROR) << "Failed to get file system of current profile";
 
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE, {content::BrowserThread::UI},
           base::BindOnce(
               &ChromeScreenshotGrabber::OnReadScreenshotFileForPreviewCompleted,
@@ -560,7 +558,7 @@
             &ChromeScreenshotGrabber::ReadScreenshotFileForPreviewDrive,
             weak_factory_.GetWeakPtr(), screenshot_path));
   } else {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
             &ChromeScreenshotGrabber::ReadScreenshotFileForPreviewLocal,
@@ -573,7 +571,7 @@
     const base::FilePath& screenshot_cache_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE, kBlockingTaskTraits,
       base::BindOnce(&ReadFileToString, screenshot_cache_path),
       base::BindOnce(&ChromeScreenshotGrabber::DecodeScreenshotFileForPreview,
@@ -588,7 +586,7 @@
   if (error != drive::FILE_ERROR_OK) {
     LOG(ERROR) << "Failed to read the screenshot path on drive: "
                << drive::FileErrorToString(error);
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
             &ChromeScreenshotGrabber::OnReadScreenshotFileForPreviewCompleted,
@@ -596,7 +594,7 @@
             screenshot_path, gfx::Image()));
     return;
   }
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(
           &ChromeScreenshotGrabber::ReadScreenshotFileForPreviewLocal,
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index cae5ba4..dc188814 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -46,9 +46,9 @@
 
   explicit TabReloader(content::WebContents* web_contents)
       : web_contents_(web_contents) {
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             base::BindOnce(&TabReloader::ReloadImpl,
-                                            weak_ptr_factory_.GetWeakPtr()));
+    base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                   base::BindOnce(&TabReloader::ReloadImpl,
+                                  weak_ptr_factory_.GetWeakPtr()));
   }
 
   void ReloadImpl() {
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc
index 8927adf4..0c56570 100644
--- a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/content_settings/content_setting_image_model.h"
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -81,10 +82,9 @@
   EXPECT_FALSE(content_setting_image_model->is_visible());
   EXPECT_TRUE(content_setting_image_model->get_tooltip().empty());
 
-  net::CookieOptions options;
   GURL origin("http://google.com");
-  std::unique_ptr<net::CanonicalCookie> cookie(
-      net::CanonicalCookie::Create(origin, "A=B", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
+      origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
   ASSERT_TRUE(cookie);
   web_contents()->OnCookieChange(origin, origin, *cookie, false);
   content_setting_image_model->Update(web_contents());
diff --git a/chrome/browser/ui/libgtkui/app_indicator_icon.cc b/chrome/browser/ui/libgtkui/app_indicator_icon.cc
index b1720e9..43dd083 100644
--- a/chrome/browser/ui/libgtkui/app_indicator_icon.cc
+++ b/chrome/browser/ui/libgtkui/app_indicator_icon.cc
@@ -164,8 +164,9 @@
   if (icon_) {
     app_indicator_set_status(icon_, APP_INDICATOR_STATUS_PASSIVE);
     g_object_unref(icon_);
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&DeleteTempDirectory, temp_dir_));
   }
 }
@@ -187,19 +188,19 @@
   SkBitmap safe_bitmap = *image.bitmap();
 
   const base::TaskTraits kTraits = {
-      base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
 
   if (desktop_env_ == base::nix::DESKTOP_ENVIRONMENT_KDE4 ||
       desktop_env_ == base::nix::DESKTOP_ENVIRONMENT_KDE5) {
-    base::PostTaskWithTraitsAndReplyWithResult(
+    base::PostTaskAndReplyWithResult(
         FROM_HERE, kTraits,
         base::Bind(AppIndicatorIcon::WriteKDE4TempImageOnWorkerThread,
                    safe_bitmap, temp_dir_),
         base::Bind(&AppIndicatorIcon::SetImageFromFile,
                    weak_factory_.GetWeakPtr()));
   } else {
-    base::PostTaskWithTraitsAndReplyWithResult(
+    base::PostTaskAndReplyWithResult(
         FROM_HERE, kTraits,
         base::Bind(AppIndicatorIcon::WriteUnityTempImageOnWorkerThread,
                    safe_bitmap, icon_change_count_, id_),
@@ -334,8 +335,9 @@
   }
 
   if (temp_dir_ != params.parent_temp_dir) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&DeleteTempDirectory, temp_dir_));
     temp_dir_ = params.parent_temp_dir;
   }
diff --git a/chrome/browser/ui/libgtkui/print_dialog_gtk.cc b/chrome/browser/ui/libgtkui/print_dialog_gtk.cc
index d8b8d21..5b7d7f2 100644
--- a/chrome/browser/ui/libgtkui/print_dialog_gtk.cc
+++ b/chrome/browser/ui/libgtkui/print_dialog_gtk.cc
@@ -386,10 +386,9 @@
   }
 
   // No errors, continue printing.
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&PrintDialogGtk::SendDocumentToPrinter, this,
-                     document_name));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&PrintDialogGtk::SendDocumentToPrinter, this,
+                                document_name));
 }
 
 void PrintDialogGtk::AddRefToDialog() {
@@ -512,11 +511,12 @@
   if (print_job)
     g_object_unref(print_job);
 
-  base::PostTaskWithTraits(FROM_HERE,
-                           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-                            base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-                           base::BindOnce(base::IgnoreResult(&base::DeleteFile),
-                                          path_to_pdf_, false));
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+       base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+      base::BindOnce(base::IgnoreResult(&base::DeleteFile), path_to_pdf_,
+                     false));
   // Printing finished. Matches AddRef() in PrintDocument();
   Release();
 }
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc b/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
index a4c1d4d..949f15a7 100644
--- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
+++ b/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc
@@ -207,8 +207,9 @@
     base::nix::DesktopEnvironment desktop)
     : SelectFileDialogImpl(listener, std::move(policy)),
       desktop_(desktop),
-      pipe_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+      pipe_task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_BLOCKING,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
   DCHECK(desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 ||
          desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE4 ||
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc
index 115ed66..b5a3403 100644
--- a/chrome/browser/ui/login/login_handler.cc
+++ b/chrome/browser/ui/login/login_handler.cc
@@ -115,10 +115,9 @@
     // This may be called as the browser is closing a tab, so run the
     // interstitial logic on a fresh event loop iteration.
     if (interstitial_delegate_) {
-      base::PostTaskWithTraits(
-          FROM_HERE, {BrowserThread::UI},
-          base::BindOnce(&LoginInterstitialDelegate::DontProceed,
-                         interstitial_delegate_));
+      base::PostTask(FROM_HERE, {BrowserThread::UI},
+                     base::BindOnce(&LoginInterstitialDelegate::DontProceed,
+                                    interstitial_delegate_));
     }
   }
 }
@@ -161,7 +160,7 @@
   // To avoid reentrancy problems, this function must not call
   // |auth_required_callback_| synchronously. Defer MaybeSetUpLoginPrompt by an
   // event loop iteration.
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&LoginHandler::MaybeSetUpLoginPrompt,
                      weak_factory_.GetWeakPtr(), request_url, is_main_frame,
@@ -354,9 +353,9 @@
   if (interstitial_delegate_) {
     // This may be called as the browser is closing a tab, so run the
     // interstitial logic on a fresh event loop iteration.
-    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::BindOnce(&LoginInterstitialDelegate::Proceed,
-                                            interstitial_delegate_));
+    base::PostTask(FROM_HERE, {BrowserThread::UI},
+                   base::BindOnce(&LoginInterstitialDelegate::Proceed,
+                                  interstitial_delegate_));
   }
 }
 
diff --git a/chrome/browser/ui/media_router/media_router_file_dialog.cc b/chrome/browser/ui/media_router/media_router_file_dialog.cc
index 1bdad04..ebb0825fb 100644
--- a/chrome/browser/ui/media_router/media_router_file_dialog.cc
+++ b/chrome/browser/ui/media_router/media_router_file_dialog.cc
@@ -130,8 +130,8 @@
 MediaRouterFileDialog::MediaRouterFileDialog(
     MediaRouterFileDialogDelegate* delegate,
     std::unique_ptr<FileSystemDelegate> file_system_delegate)
-    : task_runner_(base::CreateTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
+    : task_runner_(base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                           base::TaskPriority::USER_VISIBLE})),
       file_system_delegate_(std::move(file_system_delegate)),
       delegate_(delegate) {}
 
diff --git a/chrome/browser/ui/passwords/google_password_manager_navigation_throttle.cc b/chrome/browser/ui/passwords/google_password_manager_navigation_throttle.cc
index ed0c13a..8beba5e 100644
--- a/chrome/browser/ui/passwords/google_password_manager_navigation_throttle.cc
+++ b/chrome/browser/ui/passwords/google_password_manager_navigation_throttle.cc
@@ -59,7 +59,7 @@
 void PostShowPasswordManagerAndCloseTab(
     content::NavigationHandle* navigation_handle,
     const base::Location& from_here = base::Location::Current()) {
-  base::PostTaskWithTraits(
+  base::PostTask(
       from_here, {content::BrowserThread::UI},
       base::BindOnce(
           [](std::unique_ptr<WebContentsDestroyedObserver> observer) {
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index de0cccd..ae2cc35 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -59,15 +59,12 @@
         .set_embedded_search_client_factory_for_testing(std::move(factory));
   }
 
-  content::BrowserContext* CreateBrowserContext() override {
-    TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileSyncServiceFactory::GetInstance(),
-        base::BindRepeating(
-            [](content::BrowserContext*) -> std::unique_ptr<KeyedService> {
-              return std::make_unique<syncer::TestSyncService>();
-            }));
-    return builder.Build().release();
+  TestingProfile::TestingFactories GetTestingFactories() const override {
+    return {{ProfileSyncServiceFactory::GetInstance(),
+             base::BindRepeating(
+                 [](content::BrowserContext*) -> std::unique_ptr<KeyedService> {
+                   return std::make_unique<syncer::TestSyncService>();
+                 })}};
   }
 
   // Configure the account to |sync_history| or not.
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 4a5455ff..8a447e3 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -182,10 +182,9 @@
     }
     // Asynchronous post to give a chance to the last window to completely
     // open and activate before trying to activate |profile_to_activate_|.
-    base::PostTaskWithTraits(
-        FROM_HERE, {BrowserThread::UI},
-        base::BindOnce(&ProfileLaunchObserver::ActivateProfile,
-                       base::Unretained(this)));
+    base::PostTask(FROM_HERE, {BrowserThread::UI},
+                   base::BindOnce(&ProfileLaunchObserver::ActivateProfile,
+                                  base::Unretained(this)));
     // Avoid posting more than once before ActivateProfile gets called.
     registrar_.RemoveAll();
     BrowserList::RemoveObserver(this);
@@ -686,11 +685,11 @@
     base::FilePath output_file(
         command_line.GetSwitchValuePath(switches::kDumpBrowserHistograms));
     if (!output_file.empty()) {
-      base::PostTaskWithTraits(
-          FROM_HERE,
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-           base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
-          base::BindOnce(&DumpBrowserHistograms, output_file));
+      base::PostTask(FROM_HERE,
+                     {base::ThreadPool(), base::MayBlock(),
+                      base::TaskPriority::BEST_EFFORT,
+                      base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+                     base::BindOnce(&DumpBrowserHistograms, output_file));
     }
     silent_launch = true;
   }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 59bca8cd..8829333 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -250,13 +250,13 @@
       (mode = GetLaunchModeFast()) == LM_TO_BE_DECIDED) {
     // The mode couldn't be determined with a fast path. Perform a more
     // expensive evaluation out of the critical startup path.
-    base::PostTaskWithTraits(FROM_HERE,
-                             {base::TaskPriority::BEST_EFFORT,
-                              base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-                             base::BindOnce([]() {
-                               base::UmaHistogramSparse(kHistogramName,
-                                                        GetLaunchModeSlow());
-                             }));
+    base::PostTask(FROM_HERE,
+                   {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
+                    base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+                   base::BindOnce([]() {
+                     base::UmaHistogramSparse(kHistogramName,
+                                              GetLaunchModeSlow());
+                   }));
   } else {
     base::UmaHistogramSparse(kHistogramName, mode);
   }
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.cc b/chrome/browser/ui/thumbnails/thumbnail_image.cc
index 35f3eeb..ae36bde 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_image.cc
@@ -75,9 +75,9 @@
 }
 
 void ThumbnailImage::AssignSkBitmap(SkBitmap bitmap) {
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::TaskPriority::USER_VISIBLE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&SkBitmapToJPEGData, std::move(bitmap)),
       base::BindOnce(&ThumbnailImage::AssignJPEGData,
@@ -98,9 +98,9 @@
 bool ThumbnailImage::ConvertJPEGDataToImageSkiaAndNotifyObservers() {
   if (!data_)
     return false;
-  return base::PostTaskWithTraitsAndReplyWithResult(
+  return base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::TaskPriority::USER_VISIBLE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&JPEGDataToImageSkia, data_),
       base::BindOnce(&ThumbnailImage::NotifyObservers,
diff --git a/chrome/browser/ui/toolbar/media_router_action_controller.cc b/chrome/browser/ui/toolbar/media_router_action_controller.cc
index 3cb20eb..48e3ac6 100644
--- a/chrome/browser/ui/toolbar/media_router_action_controller.cc
+++ b/chrome/browser/ui/toolbar/media_router_action_controller.cc
@@ -85,7 +85,7 @@
       observer.DeactivateIcon();
     // Call MaybeAddOrRemoveAction() asynchronously, so that the action icon
     // doesn't get hidden until we have a chance to show a context menu.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&MediaRouterActionController::MaybeAddOrRemoveAction,
                        weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/views/chrome_views_delegate_win.cc b/chrome/browser/ui/views/chrome_views_delegate_win.cc
index 4ecb7bf..8b8c12a 100644
--- a/chrome/browser/ui/views/chrome_views_delegate_win.cc
+++ b/chrome/browser/ui/views/chrome_views_delegate_win.cc
@@ -171,8 +171,10 @@
   if (monitor && !in_autohide_edges_callback_) {
     // TODO(robliao): Annotate this task with .WithCOM() once supported.
     // https://crbug.com/662122
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskPriority::USER_BLOCKING},
         base::BindOnce(&GetAppbarAutohideEdgesOnWorkerThread, monitor),
         base::BindOnce(&ChromeViewsDelegate::OnGotAppbarAutohideEdges,
                        weak_factory_.GetWeakPtr(), std::move(callback), monitor,
diff --git a/chrome/browser/ui/views/color_chooser_dialog.cc b/chrome/browser/ui/views/color_chooser_dialog.cc
index 1f568a2..6db650e 100644
--- a/chrome/browser/ui/views/color_chooser_dialog.cc
+++ b/chrome/browser/ui/views/color_chooser_dialog.cc
@@ -67,11 +67,10 @@
   cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
   bool success = !!ChooseColor(&cc);
   DisableOwner(cc.hwndOwner);
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&ColorChooserDialog::DidCloseDialog, this, success,
-                     skia::COLORREFToSkColor(cc.rgbResult),
-                     std::move(run_state)));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&ColorChooserDialog::DidCloseDialog, this,
+                                success, skia::COLORREFToSkColor(cc.rgbResult),
+                                std::move(run_state)));
 }
 
 void ColorChooserDialog::DidCloseDialog(bool chose_color,
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
index 1bf519b..82ce07dc 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
@@ -96,8 +96,8 @@
 }
 
 void RecordTimeFromDeviceSetupToInstallMetric() {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock()},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
       base::BindOnce(&chromeos::StartupUtils::GetTimeSinceOobeFlagFileCreation),
       base::BindOnce([](base::TimeDelta time_from_device_setup) {
         if (time_from_device_setup.is_zero())
@@ -143,8 +143,9 @@
   crostini::CrostiniManager::GetForProfile(profile)->SetInstallerViewStatus(
       true);
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
                      base::FilePath(crostini::kHomeDirectory)),
       base::BindOnce(
@@ -209,11 +210,10 @@
   // Delay starting the install process until we can check if there's enough
   // disk space.
   if (free_disk_space_ == kUninitializedDiskSpace) {
-    base::PostDelayedTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::BindOnce(&CrostiniInstallerView::PressAccept,
-                       weak_ptr_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMilliseconds(50));
+    base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+                          base::BindOnce(&CrostiniInstallerView::PressAccept,
+                                         weak_ptr_factory_.GetWeakPtr()),
+                          base::TimeDelta::FromMilliseconds(50));
     return false;
   }
 
@@ -298,7 +298,7 @@
 
     if (do_cleanup_) {
       // Remove anything that got installed
-      base::PostTaskWithTraits(
+      base::PostTask(
           FROM_HERE, {content::BrowserThread::UI},
           base::BindOnce(
               &crostini::CrostiniManager::RemoveCrostini,
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc
index 75b9c3f1..673cbb7e 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.cc
@@ -110,7 +110,7 @@
       base::ASCIIToUTF16(autoselect_source) != source.name) {
     return;
   }
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&DesktopMediaListController::AcceptSpecificSource,
                      weak_factory_.GetWeakPtr(), source.id));
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index 6fae6060..3cd82a7 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -498,8 +498,8 @@
 
   // Notify the |callback_| asynchronously because it may need to destroy
   // DesktopMediaPicker.
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(callback_, source));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(callback_, source));
   callback_.Reset();
 }
 
diff --git a/chrome/browser/ui/views/elevation_icon_setter.cc b/chrome/browser/ui/views/elevation_icon_setter.cc
index 2ff1f34b..ee361a58 100644
--- a/chrome/browser/ui/views/elevation_icon_setter.cc
+++ b/chrome/browser/ui/views/elevation_icon_setter.cc
@@ -53,8 +53,8 @@
     : button_(button) {
 #if defined(OS_WIN)
   base::PostTaskAndReplyWithResult(
-      base::CreateCOMSTATaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
+      base::CreateCOMSTATaskRunner({base::ThreadPool(), base::MayBlock(),
+                                    base::TaskPriority::USER_BLOCKING})
           .get(),
       FROM_HERE, base::BindOnce(&GetElevationIcon),
       base::BindOnce(&ElevationIconSetter::SetButtonIcon,
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc
index 111499f7..e7f241e 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.cc
+++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -150,8 +150,10 @@
                                           ->tab_strip_model()
                                           ->GetActiveWebContents()
                                           ->GetMainFrame();
-      base::PostTaskWithTraitsAndReplyWithResult(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReplyWithResult(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&FindURLMimeType, url),
           base::BindOnce(&OnFindURLMimeType, url, rfh->GetProcess()->GetID(),
                          rfh->GetRoutingID(),
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
index 35d0875..6bc0f85 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
@@ -43,7 +43,7 @@
   AddChildView(looking_for_sinks_view_);
 
   constexpr int kThrobberDurationInSeconds = 3;
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&CastDialogNoSinksView::ShowHelpIconView,
                      weak_factory_.GetWeakPtr()),
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
index 8edd34b..ca160fb 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -189,10 +189,9 @@
     // SinkPressed() invokes a refresh of the sink list, which deletes the
     // sink button. So we must call this after the button is done handling the
     // press event.
-    base::PostTaskWithTraits(
-        FROM_HERE, {content::BrowserThread::UI},
-        base::BindOnce(&CastDialogView::SinkPressed, weak_factory_.GetWeakPtr(),
-                       sender->tag()));
+    base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                   base::BindOnce(&CastDialogView::SinkPressed,
+                                  weak_factory_.GetWeakPtr(), sender->tag()));
   }
 }
 
@@ -465,11 +464,10 @@
 void CastDialogView::RecordSinkCountWithDelay() {
   // Record the number of sinks after three seconds. This is consistent with the
   // WebUI dialog.
-  base::PostDelayedTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&CastDialogView::RecordSinkCount,
-                     weak_factory_.GetWeakPtr()),
-      base::TimeDelta::FromSeconds(3));
+  base::PostDelayedTask(FROM_HERE, {content::BrowserThread::UI},
+                        base::BindOnce(&CastDialogView::RecordSinkCount,
+                                       weak_factory_.GetWeakPtr()),
+                        base::TimeDelta::FromSeconds(3));
 }
 
 void CastDialogView::RecordSinkCount() {
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_permission_view_browsertest.cc b/chrome/browser/ui/views/native_file_system/native_file_system_permission_view_browsertest.cc
index d7ff53e..1ba691a2 100644
--- a/chrome/browser/ui/views/native_file_system/native_file_system_permission_view_browsertest.cc
+++ b/chrome/browser/ui/views/native_file_system/native_file_system_permission_view_browsertest.cc
@@ -30,7 +30,10 @@
       NOTREACHED() << "Unimplemented test: " << name;
     }
     widget_ = NativeFileSystemPermissionView::ShowDialog(
-        kTestOrigin, path, is_directory,
+        url::Origin::Create(GURL("https://"
+                                 "totallynotgooglechromelabbutverylongurlthatdo"
+                                 "esnotfitononeline.github.io//")),
+        path, is_directory,
         base::BindLambdaForTesting([&](PermissionAction result) {
           callback_called_ = true;
           callback_result_ = result;
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index 605c62f3..eb3a907cc 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -120,9 +120,9 @@
     }
 
     // Re-enable updates by shelling out to setup.exe asynchronously.
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE,
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
          base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
         base::BindOnce(&google_update::ElevateIfNeededToReenableUpdates));
 #endif  // defined(OS_WIN)
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 b9d5c82..bdff403 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
@@ -951,10 +951,9 @@
   // The bubble closes automatically when the collected cookies dialog or the
   // certificate viewer opens. So delay handling of the link clicked to avoid
   // a crash in the base class which needs to complete the mouse event handling.
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&PageInfoBubbleView::HandleMoreInfoRequestAsync,
-                     weak_factory_.GetWeakPtr(), source->GetID()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&PageInfoBubbleView::HandleMoreInfoRequestAsync,
+                                weak_factory_.GetWeakPtr(), source->GetID()));
 }
 
 void PageInfoBubbleView::HandleMoreInfoRequestAsync(int view_id) {
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
index d57a0a3..9e32f44 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
@@ -65,7 +65,7 @@
   }
 
   void SetUpOnMainThread() override {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&SSLClientCertificateSelectorTest::SetUpOnIOThread,
                        base::Unretained(this)));
@@ -99,7 +99,7 @@
   // Have to release our reference to the auth handler during the test to allow
   // it to be destroyed while the Browser and its IO thread still exist.
   void TearDownOnMainThread() override {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&SSLClientCertificateSelectorTest::CleanUpOnIOThread,
                        base::Unretained(this)));
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index 648d293..8637fe3 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -203,27 +203,35 @@
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     if (path_ == chrome::kOemEulaURLPath) {
       // Load local OEM EULA from the disk.
-      base::PostTaskWithTraitsAndReply(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReply(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&ChromeOSTermsHandler::LoadOemEulaFileAsync, this),
           base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
     } else if (path_ == chrome::kArcTermsURLPath) {
       // Load ARC++ terms from the file.
-      base::PostTaskWithTraitsAndReply(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReply(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&ChromeOSTermsHandler::LoadArcTermsFileAsync, this),
           base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
     } else if (path_ == chrome::kArcPrivacyPolicyURLPath) {
       // Load ARC++ privacy policy from the file.
-      base::PostTaskWithTraitsAndReply(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReply(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&ChromeOSTermsHandler::LoadArcPrivacyPolicyFileAsync,
                          this),
           base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
     } else {
       // Load local ChromeOS terms from the file.
-      base::PostTaskWithTraitsAndReply(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReply(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&ChromeOSTermsHandler::LoadEulaFileAsync, this),
           base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
     }
@@ -383,8 +391,9 @@
       return;
     }
     // Load local Chrome OS credits from the disk.
-    base::PostTaskWithTraitsAndReply(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReply(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::Bind(&ChromeOSCreditsHandler::LoadCreditsFileAsync, this),
         base::Bind(&ChromeOSCreditsHandler::ResponseOnUIThread, this));
   }
@@ -450,8 +459,9 @@
       return;
     }
     // Load local Linux credits from the disk.
-    base::PostTaskWithTraitsAndReply(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReply(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::Bind(&LinuxCreditsHandler::LoadLinuxCreditsFileAsync, this),
         base::Bind(&LinuxCreditsHandler::ResponseOnUIThread, this));
   }
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
index 0eb7e9d..7cc2c36 100644
--- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -89,14 +89,15 @@
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
-  content::BrowserContext* CreateBrowserContext() override {
-    TestingProfile::Builder builder;
-    builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
-                              base::BindRepeating(&BuildTestSyncService));
-    builder.AddTestingFactory(WebHistoryServiceFactory::GetInstance(),
-                              base::BindRepeating(&BuildFakeWebHistoryService));
-    return builder.Build().release();
+  TestingProfile::TestingFactories GetTestingFactories() const override {
+    return {
+        {ProfileSyncServiceFactory::GetInstance(),
+         base::BindRepeating(&BuildTestSyncService)},
+        {WebHistoryServiceFactory::GetInstance(),
+         base::BindRepeating(&BuildFakeWebHistoryService)},
+    };
   }
+
   syncer::TestSyncService* sync_service() { return sync_service_; }
   history::WebHistoryService* web_history_service() {
     return web_history_service_;
diff --git a/chrome/browser/ui/webui/certificates_handler.cc b/chrome/browser/ui/webui/certificates_handler.cc
index 1ea5c24..90ee1b5f 100644
--- a/chrome/browser/ui/webui/certificates_handler.cc
+++ b/chrome/browser/ui/webui/certificates_handler.cc
@@ -224,8 +224,8 @@
   std::string* data = new std::string();
 
   // Post task to a background sequence to read file.
-  auto task_runner = base::CreateTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+  auto task_runner = base::CreateTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT});
   return tracker->PostTaskAndReply(
       task_runner.get(), FROM_HERE,
       base::BindOnce(&FileAccessProvider::DoRead, this, path, saved_errno,
@@ -243,8 +243,8 @@
   int* bytes_written = new int(0);
 
   // This task blocks shutdown because it saves critical user data.
-  auto task_runner = base::CreateTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+  auto task_runner = base::CreateTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
   return tracker->PostTaskAndReply(
       task_runner.get(), FROM_HERE,
diff --git a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
index de20b5ee..018bcc7 100644
--- a/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
@@ -428,8 +428,9 @@
     base::RefCountedString* trace_data) {
   std::string string_data;
   string_data.swap(trace_data->data());
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&BuildGraphicsModel, std::move(string_data),
                      std::move(tasks_info_), std::move(system_stat_colletor_),
                      tracing_time_min_, tracing_time_max_,
@@ -450,8 +451,9 @@
 }
 
 void ArcGraphicsTracingHandler::HandleReady(const base::ListValue* args) {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&MaybeLoadLastGraphicsModel,
                      GetLastTracingModelPath(Profile::FromWebUI(web_ui()))),
       base::BindOnce(&ArcGraphicsTracingHandler::OnGraphicsModelReady,
@@ -476,8 +478,9 @@
     return;
   }
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&LoadGraphicsModel,
                      std::move(args->GetList()[0].GetString())),
       base::BindOnce(&ArcGraphicsTracingHandler::OnGraphicsModelReady,
diff --git a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
index a2b95c0..6886692 100644
--- a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
@@ -40,7 +40,7 @@
   cryptohome_client->Pkcs11IsTpmTokenReady(
       GetCryptohomeBoolCallback("pkcs11-is-tpm-token-ready"));
 
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE, {BrowserThread::IO},
       base::Bind(&crypto::IsTPMTokenReady, base::Closure()),
       base::Bind(&CryptohomeWebUIHandler::DidGetNSSUtilInfoOnUIThread,
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index 5aa085a6..85d619db 100644
--- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -694,8 +694,10 @@
     // Propagate the amount of local free space in bytes.
     base::FilePath home_path;
     if (base::PathService::Get(base::DIR_HOME, &home_path)) {
-      base::PostTaskWithTraitsAndReplyWithResult(
-          FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::PostTaskAndReplyWithResult(
+          FROM_HERE,
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::USER_VISIBLE},
           base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace, home_path),
           base::BindOnce(&DriveInternalsWebUIHandler::OnGetFreeDiskSpace,
                          weak_ptr_factory_.GetWeakPtr()));
@@ -793,8 +795,10 @@
         "updateOtherServiceLogsUrl",
         base::Value(net::FilePathToFileURL(log_path.DirName()).spec()));
 
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskPriority::USER_VISIBLE},
         base::BindOnce(&GetServiceLogContents, log_path,
                        service_log_file_inode_, last_sent_line_number_),
         base::BindOnce(&DriveInternalsWebUIHandler::OnServiceLogRead,
@@ -852,8 +856,10 @@
 
     const base::FilePath root_path =
         drive::util::GetCacheRootPath(profile()).DirName();
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskPriority::USER_VISIBLE},
         base::BindOnce(&GetGCacheContents, root_path),
         base::BindOnce(&DriveInternalsWebUIHandler::OnGetGCacheContents,
                        weak_ptr_factory_.GetWeakPtr()));
@@ -983,8 +989,10 @@
         drive_internals_(std::move(drive_internals)) {}
 
   void Start() {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(),
+         base::TaskPriority::USER_VISIBLE},
         base::BindOnce(&LogsZipper::EnumerateLogFiles, logs_directory_,
                        zip_path_),
         base::BindOnce(&LogsZipper::ZipLogFiles, base::Unretained(this)));
@@ -1040,8 +1048,9 @@
   }
 
   void CleanUp() {
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(base::IgnoreResult(&base::DeleteFile), zip_path_,
                        false));
     download_notifier_.reset();
diff --git a/chrome/browser/ui/webui/chromeos/image_source.cc b/chrome/browser/ui/webui/chromeos/image_source.cc
index d459c036..cc554ee 100644
--- a/chrome/browser/ui/webui/chromeos/image_source.cc
+++ b/chrome/browser/ui/webui/chromeos/image_source.cc
@@ -41,8 +41,8 @@
 }  // namespace
 
 ImageSource::ImageSource() : weak_factory_(this) {
-  task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+  task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
@@ -64,8 +64,9 @@
 
   const base::FilePath asset_dir(chrome::kChromeOSAssetPath);
   const base::FilePath image_path = asset_dir.AppendASCII(path);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::Bind(&base::PathExists, image_path),
       base::Bind(&ImageSource::StartDataRequestAfterPathExists,
                  weak_factory_.GetWeakPtr(), image_path, got_data_callback));
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index ed23aaa3..6992e9c0 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -520,8 +520,9 @@
 }
 
 void EncryptionMigrationScreenHandler::CheckAvailableStorage() {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       free_disk_space_fetcher_,
       base::Bind(&EncryptionMigrationScreenHandler::OnGetAvailableStorage,
                  weak_ptr_factory_.GetWeakPtr()));
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 7ea9446..186c6ac 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -18,6 +18,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -367,15 +368,15 @@
 
   std::string gaps_cookie_value(kGAPSCookie);
   gaps_cookie_value += "=" + context.gaps_cookie;
+  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
+      GaiaUrls::GetInstance()->gaia_url(), gaps_cookie_value, base::Time::Now(),
+      base::nullopt /* server_time */));
+
   net::CookieOptions options;
   options.set_include_httponly();
   // Permit it to set a SameSite cookie if it wants to.
   options.set_same_site_cookie_context(
       net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
-  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-      GaiaUrls::GetInstance()->gaia_url(), gaps_cookie_value, base::Time::Now(),
-      options));
-
   partition->GetCookieManagerForBrowserProcess()->SetCanonicalCookie(
       *cc.get(), "https", options, std::move(callback));
 }
@@ -393,8 +394,9 @@
       &GaiaScreenHandler::LoadGaiaWithPartitionAndVersionAndConsent,
       weak_factory_.GetWeakPtr(), context, partition_name,
       base::Owned(version.release()), base::Owned(consent.release()));
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       std::move(get_version_and_consent), std::move(load_gaia));
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
index c3dbe6c..8ec89e8 100644
--- a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
+++ b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -426,8 +426,8 @@
     const UILanguageListResolvedCallback& callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock()},
+  base::PostTask(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
       base::BindOnce(&ResolveLanguageListInThreadPool,
                      base::Passed(&language_switch_result),
                      base::SequencedTaskRunnerHandle::Get(), callback));
@@ -581,9 +581,10 @@
   // thread.
   std::string (*get_application_locale)(const std::string&, bool) =
       &l10n_util::GetApplicationLocale;
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+      {base::ThreadPool(), base::MayBlock(),
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(get_application_locale, locale,
                      false /* set_icu_locale */),
       base::BindOnce(&GetKeyboardLayoutsForResolvedLocale, locale, callback));
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
index 479dee3..af57f370 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -66,10 +66,9 @@
       display::Screen::GetScreen()->GetPrimaryDisplay();
 
   if (primary_display.is_valid() && !TouchSupportAvailable(primary_display)) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {BrowserThread::UI},
-        base::BindOnce(&OobeDisplayChooser::MaybeMoveToTouchDisplay,
-                       weak_ptr_factory_.GetWeakPtr()));
+    base::PostTask(FROM_HERE, {BrowserThread::UI},
+                   base::BindOnce(&OobeDisplayChooser::MaybeMoveToTouchDisplay,
+                                  weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
index 901932a..5aeaa1a8 100644
--- a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
@@ -32,7 +32,6 @@
     {"OncTypeTether", IDS_NETWORK_TYPE_TETHER},
     {"OncTypeVPN", IDS_NETWORK_TYPE_VPN},
     {"OncTypeWiFi", IDS_NETWORK_TYPE_WIFI},
-    {"OncTypeWiMAX", IDS_NETWORK_TYPE_WIMAX},
     {"networkListItemConnected", IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED},
     {"networkListItemConnecting", IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING},
     {"networkListItemConnectingTo", IDS_NETWORK_LIST_CONNECTING_TO},
@@ -158,7 +157,6 @@
       {"OncWiFi-Security_WPA-PSK", IDS_ONC_WIFI_SECURITY_PSK},
       {"OncWiFi-Security_WEP-8021X", IDS_ONC_WIFI_SECURITY_EAP},
       {"OncWiFi-SignalStrength", IDS_ONC_WIFI_SIGNAL_STRENGTH},
-      {"OncWiMAX-EAP-Identity", IDS_ONC_WIMAX_EAP_IDENTITY},
       {"Oncipv4-Gateway", IDS_ONC_IPV4_GATEWAY},
       {"Oncipv4-IPAddress", IDS_ONC_IPV4_ADDRESS},
       {"Oncipv4-RoutingPrefix", IDS_ONC_IPV4_ROUTING_PREFIX},
diff --git a/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc b/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
index d84d732..0557695 100644
--- a/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
@@ -222,8 +222,9 @@
   }
 
   base::Value callback_id = list[0].Clone();
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, base::MayBlock(), base::BindOnce(&GetSysInfo),
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+      base::BindOnce(&GetSysInfo),
       base::BindOnce(&SysInternalsMessageHandler::ReplySysInfo,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback_id)));
 }
diff --git a/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc b/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc
index 8dee3fe..1d8157a7 100644
--- a/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc
+++ b/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc
@@ -47,8 +47,9 @@
   } else {
     file_path = file_path.Append(path);
   }
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&ReadFile, file_path, callback));
 }
 
diff --git a/chrome/browser/ui/webui/chromeos/video_source.cc b/chrome/browser/ui/webui/chromeos/video_source.cc
index 6144e57..7d9a300 100644
--- a/chrome/browser/ui/webui/chromeos/video_source.cc
+++ b/chrome/browser/ui/webui/chromeos/video_source.cc
@@ -55,8 +55,8 @@
 }  // namespace
 
 VideoSource::VideoSource() : weak_factory_(this) {
-  task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+  task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
@@ -77,8 +77,9 @@
 
   const base::FilePath asset_dir(chrome::kChromeOSAssetPath);
   const base::FilePath video_path = asset_dir.AppendASCII(path);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&base::PathExists, video_path),
       base::BindOnce(&VideoSource::StartDataRequestAfterPathExists,
                      weak_factory_.GetWeakPtr(), video_path,
diff --git a/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc b/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
index 0b218719..caf0202 100644
--- a/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
+++ b/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
@@ -495,17 +495,16 @@
 
 #if defined(GOOGLE_CHROME_BUILD)
   // The state of third-party features must be determined on the UI thread.
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(
           OnModuleDataFetched, std::move(on_conflicts_data_fetched_callback_),
           std::move(results), std::move(third_party_conflicts_manager_state_)));
 #else
   // The third-party features are always disabled on Chromium builds.
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(OnConflictsDataFetched,
-                     std::move(on_conflicts_data_fetched_callback_),
-                     std::move(results), kNonGoogleChromeBuild));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(OnConflictsDataFetched,
+                                std::move(on_conflicts_data_fetched_callback_),
+                                std::move(results), kNonGoogleChromeBuild));
 #endif
 }
diff --git a/chrome/browser/ui/webui/devtools_ui.cc b/chrome/browser/ui/webui/devtools_ui.cc
index 1fd9c57..972657d 100644
--- a/chrome/browser/ui/webui/devtools_ui.cc
+++ b/chrome/browser/ui/webui/devtools_ui.cc
@@ -379,7 +379,7 @@
 
   base::FilePath full_path = inspector_debug_dir.AppendASCII(path);
 
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
       {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
        base::TaskPriority::USER_VISIBLE},
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index fd278d7..cb5edfe 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -88,8 +88,6 @@
   }
   if (chromeos::NetworkTypePattern::Ethernet().MatchesType(type))
     return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_ETHERNET);
-  if (chromeos::NetworkTypePattern::Wimax().MatchesType(type))
-    return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIMAX);
   if (chromeos::NetworkTypePattern::Mobile().MatchesType(type))
     return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_MOBILE_DATA);
   if (chromeos::NetworkTypePattern::VPN().MatchesType(type))
diff --git a/chrome/browser/ui/webui/help/version_updater_win.cc b/chrome/browser/ui/webui/help/version_updater_win.cc
index 7eb104ff..a176e33 100644
--- a/chrome/browser/ui/webui/help/version_updater_win.cc
+++ b/chrome/browser/ui/webui/help/version_updater_win.cc
@@ -40,7 +40,7 @@
   if (new_version.empty()) {
     // Google Update says that no new version is available. Check to see if a
     // restart is needed for a previously-applied update to take effect.
-    base::PostTaskWithTraitsAndReplyWithResult(
+    base::PostTaskAndReplyWithResult(
         FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
         base::Bind(&upgrade_util::IsUpdatePendingRestart),
         base::Bind(&VersionUpdaterWin::OnPendingRestartCheck,
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc
index 30482e50..6ce8d49 100644
--- a/chrome/browser/ui/webui/memory_internals_ui.cc
+++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -205,7 +205,7 @@
     const base::ListValue* args) {
   // This is called on the UI thread, the child process iterator must run on
   // the IO thread, while the render process iterator must run on the UI thread.
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(&MemoryInternalsDOMHandler::GetChildProcessesOnIOThread,
                      weak_factory_.GetWeakPtr()));
@@ -292,10 +292,9 @@
     }
   }
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&MemoryInternalsDOMHandler::GetProfiledPids, dom_handler,
-                     std::move(result)));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&MemoryInternalsDOMHandler::GetProfiledPids,
+                                dom_handler, std::move(result)));
 }
 
 void MemoryInternalsDOMHandler::GetProfiledPids(
@@ -306,7 +305,7 @@
 
   // The supervisor hasn't started, so return an empty list.
   if (!supervisor->HasStarted()) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&MemoryInternalsDOMHandler::ReturnProcessListOnUIThread,
                        weak_factory_.GetWeakPtr(), std::move(children),
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc
index 89228f3..d6c184a 100644
--- a/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chrome/browser/ui/webui/nacl_ui.cc
@@ -364,8 +364,9 @@
 
   if (!pnacl_path_validated_) {
     std::string* version_string = new std::string;
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::Bind(&CheckPathAndVersion, version_string),
         base::Bind(&NaClDomHandler::DidCheckPathAndVersion,
                    weak_ptr_factory_.GetWeakPtr(),
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 5cc53f9c7..f55c36b1 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -381,7 +381,7 @@
     error += network_error;
 
   chromeos::onc::CertificateImporterImpl cert_importer(
-      base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}), nssdb);
+      base::CreateSingleThreadTaskRunner({BrowserThread::IO}), nssdb);
   auto certs =
       std::make_unique<chromeos::onc::OncParsedCertificates>(certificates);
   if (certs->has_error())
@@ -439,9 +439,9 @@
       web_ui()->GetWebContents()->GetBrowserContext(),
       true /* with_user_policies */, false /* with_device_data */,
       true /* is_pretty_print */);
-  base::PostTaskWithTraitsAndReply(
+  base::PostTaskAndReply(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
       base::BindOnce(DumpPolicyLogs, policies_path, json_policies),
       base::BindOnce(&NetInternalsMessageHandler::OnDumpPolicyLogsCompleted,
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc
index 1c86b4e93..5eb4ebf 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -1085,9 +1085,9 @@
   base::JSONWriter::WriteWithOptions(
       dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_policies);
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
       base::BindOnce(&DoWritePoliciesToJSONFile, path, json_policies));
 }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 9534da45..d4f3425 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -83,8 +83,9 @@
                              printer.GetProtocol() == chromeos::Printer::kIpps;
 
   // USER_VISIBLE because the result is displayed in the print preview dialog.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&GetSettingsOnBlockingPool, printer.id(), basic_info,
                      PrinterSemanticCapsAndDefaults::Papers(),
                      has_secure_protocol, nullptr),
@@ -147,8 +148,8 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // TODO(crbug.com/660898): Add default printers to ChromeOS.
 
-  base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::BindOnce(std::move(cb), ""));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(std::move(cb), ""));
 }
 
 void LocalPrinterHandlerChromeos::StartGetPrinters(
@@ -185,8 +186,8 @@
       printers_manager_->GetPrinter(printer_name);
   if (!printer) {
     // If the printer was removed, the lookup will fail.
-    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             base::BindOnce(std::move(cb), base::Value()));
+    base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                   base::BindOnce(std::move(cb), base::Value()));
     return;
   }
 
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
index 0074a2f8..a1f3fd3 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -31,14 +31,14 @@
 scoped_refptr<base::TaskRunner> CreatePrinterHandlerTaskRunner() {
   // USER_VISIBLE because the result is displayed in the print preview dialog.
   static constexpr base::TaskTraits kTraits = {
-      base::MayBlock(), base::TaskPriority::USER_VISIBLE};
+      base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE};
 
 #if defined(OS_WIN)
   // Windows drivers are likely not thread-safe.
-  return base::CreateSingleThreadTaskRunnerWithTraits(kTraits);
+  return base::CreateSingleThreadTaskRunner(kTraits);
 #elif defined(USE_CUPS)
   // CUPS is thread safe.
-  return base::CreateTaskRunnerWithTraits(kTraits);
+  return base::CreateTaskRunner(kTraits);
 #endif
 }
 
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
index 6147b07..00cf109 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -312,8 +312,9 @@
   // Handle the no prompting case. Like the dialog prompt, this function
   // returns and eventually FileSelected() gets called.
   if (!prompt_user) {
-    base::PostTaskWithTraitsAndReplyWithResult(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&base::GetUniquePath, path.Append(default_filename)),
         base::BindOnce(&PdfPrinterHandler::OnGotUniqueFileName,
                        weak_ptr_factory_.GetWeakPtr()));
@@ -330,16 +331,18 @@
   // Get default download directory. This will be used as a fallback if the
   // save directory does not exist.
   base::FilePath default_path = download_prefs->DownloadPath();
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&SelectSaveDirectory, path, default_path),
       base::BindOnce(&PdfPrinterHandler::OnDirectorySelected,
                      weak_ptr_factory_.GetWeakPtr(), default_filename));
 }
 
 void PdfPrinterHandler::PostPrintToPdfTask() {
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&PrintToPdfCallback, print_data_, print_to_pdf_path_,
                      std::move(pdf_file_saved_closure_)));
   print_to_pdf_path_.clear();
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
index fd564930..daefcc3 100644
--- a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
+++ b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
@@ -27,7 +27,7 @@
     scoped_refptr<storage::QuotaManager> quota_manager) {
   DCHECK(quota_manager.get());
   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&QuotaInternalsProxy::RequestInfo, this, quota_manager));
     return;
@@ -69,18 +69,17 @@
 
 QuotaInternalsProxy::~QuotaInternalsProxy() {}
 
-#define RELAY_TO_HANDLER(func, arg_t)                             \
-  void QuotaInternalsProxy::func(arg_t arg) {                     \
-    if (!handler_)                                                \
-      return;                                                     \
-    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {         \
-      base::PostTaskWithTraits(                                   \
-          FROM_HERE, {BrowserThread::UI},                         \
-          base::BindOnce(&QuotaInternalsProxy::func, this, arg)); \
-      return;                                                     \
-    }                                                             \
-                                                                  \
-    handler_->func(arg);                                          \
+#define RELAY_TO_HANDLER(func, arg_t)                                        \
+  void QuotaInternalsProxy::func(arg_t arg) {                                \
+    if (!handler_)                                                           \
+      return;                                                                \
+    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {                    \
+      base::PostTask(FROM_HERE, {BrowserThread::UI},                         \
+                     base::BindOnce(&QuotaInternalsProxy::func, this, arg)); \
+      return;                                                                \
+    }                                                                        \
+                                                                             \
+    handler_->func(arg);                                                     \
   }
 
 RELAY_TO_HANDLER(ReportAvailableSpace, int64_t)
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 517f2c4..7fb463a 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -604,8 +604,9 @@
   std::string callback_id;
   CHECK(args->GetString(0, &callback_id));
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::Bind(&GetVersionInfo),
       base::Bind(&AboutHandler::OnGetVersionInfoReady,
                  weak_factory_.GetWeakPtr(), callback_id));
@@ -622,8 +623,9 @@
   std::string callback_id;
   CHECK(args->GetString(0, &callback_id));
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::Bind(&FindRegulatoryLabelDir),
       base::Bind(&AboutHandler::OnRegulatoryLabelDirFound,
                  weak_factory_.GetWeakPtr(), callback_id));
@@ -801,8 +803,9 @@
     return;
   }
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::Bind(&ReadRegulatoryLabelText, label_dir_path),
       base::Bind(&AboutHandler::OnRegulatoryLabelTextRead,
                  weak_factory_.GetWeakPtr(), callback_id, label_dir_path));
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index b6021b75..3063950 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -945,8 +945,9 @@
   // VerifyPpdContents() in order to determine whether the file appears to be a
   // PPD file. The task's priority is USER_BLOCKING because the this task
   // updates the UI as a result of a direct user action.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&ReadFileToStringWithMaxSize, path, kPpdMaxLineLength),
       base::BindOnce(&CupsPrintersHandler::VerifyPpdContents,
                      weak_factory_.GetWeakPtr(), path));
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
index cf9b1c93..a7ecbef6 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -212,8 +212,9 @@
 
   int64_t* total_size = new int64_t(0);
   int64_t* available_size = new int64_t(0);
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::Bind(&GetSizeStatBlocking, downloads_path, total_size,
                  available_size),
       base::Bind(&StorageHandler::OnGetSizeStat, weak_ptr_factory_.GetWeakPtr(),
@@ -247,8 +248,9 @@
   const base::FilePath downloads_path =
       file_manager::util::GetDownloadsFolderForProfile(profile_);
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&base::ComputeDirectorySize, downloads_path),
       base::Bind(&StorageHandler::OnGetDownloadsSize,
                  weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 87b349ec..275af93 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -262,12 +262,9 @@
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
-  content::BrowserContext* CreateBrowserContext() override {
-    // Setup the profile.
-    std::unique_ptr<TestingProfile> profile =
-        IdentityTestEnvironmentProfileAdaptor::
-            CreateProfileForIdentityTestEnvironment();
-    return profile.release();
+  TestingProfile::TestingFactories GetTestingFactories() const override {
+    return IdentityTestEnvironmentProfileAdaptor::
+        GetIdentityTestEnvironmentFactories();
   }
 
   // Setup the expectations for calls made when displaying the config page.
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 ddff7e5..8edd200 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1403,8 +1403,6 @@
        IDS_SETTINGS_INTERNET_TOGGLE_TETHER_SUBTEXT},
       {"internetToggleWiFiA11yLabel",
        IDS_SETTINGS_INTERNET_TOGGLE_WIFI_ACCESSIBILITY_LABEL},
-      {"internetToggleWiMAXA11yLabel",
-       IDS_SETTINGS_INTERNET_TOGGLE_WIMAX_ACCESSIBILITY_LABEL},
       {"knownNetworksAll", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_ALL},
       {"knownNetworksButton", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_BUTTON},
       {"knownNetworksMessage", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MESSAGE},
diff --git a/chrome/browser/ui/webui/settings_utils_linux.cc b/chrome/browser/ui/webui/settings_utils_linux.cc
index 9eef356..19f554e 100644
--- a/chrome/browser/ui/webui/settings_utils_linux.cc
+++ b/chrome/browser/ui/webui/settings_utils_linux.cc
@@ -133,9 +133,9 @@
 
   if (launched)
     return;
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::BindOnce(&ShowLinuxProxyConfigUrl,
-                                          render_process_id, render_view_id));
+  base::PostTask(FROM_HERE, {BrowserThread::UI},
+                 base::BindOnce(&ShowLinuxProxyConfigUrl, render_process_id,
+                                render_view_id));
 }
 
 }  // namespace
@@ -143,8 +143,9 @@
 namespace settings_utils {
 
 void ShowNetworkProxySettings(content::WebContents* web_contents) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(&DetectAndStartProxyConfigUtil,
                      web_contents->GetRenderViewHost()->GetProcess()->GetID(),
                      web_contents->GetRenderViewHost()->GetRoutingID()));
diff --git a/chrome/browser/ui/webui/settings_utils_win.cc b/chrome/browser/ui/webui/settings_utils_win.cc
index 69db074..c5d1717a 100644
--- a/chrome/browser/ui/webui/settings_utils_win.cc
+++ b/chrome/browser/ui/webui/settings_utils_win.cc
@@ -109,9 +109,10 @@
         Profile::FromBrowserContext(web_contents->GetBrowserContext()),
         GURL("ms-settings:network-proxy"));
   } else {
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
-        base::BindOnce(&OpenConnectionDialogCallback));
+    base::PostTask(FROM_HERE,
+                   {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+                    base::MayBlock()},
+                   base::BindOnce(&OpenConnectionDialogCallback));
   }
 }
 
diff --git a/chrome/browser/ui/webui/test_data_source.cc b/chrome/browser/ui/webui/test_data_source.cc
index 3cc9b08b..c91ba44 100644
--- a/chrome/browser/ui/webui/test_data_source.cc
+++ b/chrome/browser/ui/webui/test_data_source.cc
@@ -33,8 +33,9 @@
     const std::string& path,
     const content::WebContents::Getter& wc_getter,
     const content::URLDataSource::GotDataCallback& callback) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&TestDataSource::ReadFile, base::Unretained(this), path,
                      callback));
 }
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc
index cf6acc95..cc006a1 100644
--- a/chrome/browser/ui/webui/theme_source.cc
+++ b/chrome/browser/ui/webui/theme_source.cc
@@ -233,7 +233,7 @@
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
     // Fetching image data in ResourceBundle should happen on the UI thread. See
     // crbug.com/449277
-    base::PostTaskWithTraitsAndReply(
+    base::PostTaskAndReply(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&ProcessResourceOnUiThread, resource_id, scale, data),
         base::BindOnce(callback, data));
diff --git a/chrome/browser/ui/webui/version_handler.cc b/chrome/browser/ui/webui/version_handler.cc
index 89080ba..8589c047 100644
--- a/chrome/browser/ui/webui/version_handler.cc
+++ b/chrome/browser/ui/webui/version_handler.cc
@@ -139,8 +139,9 @@
   // OnGotFilePaths.
   base::string16* exec_path_buffer = new base::string16;
   base::string16* profile_path_buffer = new base::string16;
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
       base::BindOnce(&GetFilePaths, Profile::FromWebUI(web_ui())->GetPath(),
                      base::Unretained(exec_path_buffer),
                      base::Unretained(profile_path_buffer)),
diff --git a/chrome/browser/ui/webui/version_handler_chromeos.cc b/chrome/browser/ui/webui/version_handler_chromeos.cc
index 0868952f..ead1af6 100644
--- a/chrome/browser/ui/webui/version_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/version_handler_chromeos.cc
@@ -19,19 +19,22 @@
   VersionHandler::HandleRequestVersionInfo(args);
 
   // Start the asynchronous load of the versions.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&chromeos::version_loader::GetVersion,
                  chromeos::version_loader::VERSION_FULL),
       base::Bind(&VersionHandlerChromeOS::OnVersion,
                  weak_factory_.GetWeakPtr()));
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&chromeos::version_loader::GetFirmware),
       base::Bind(&VersionHandlerChromeOS::OnOSFirmware,
                  weak_factory_.GetWeakPtr()));
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::Bind(&chromeos::version_loader::GetARCVersion),
       base::Bind(&VersionHandlerChromeOS::OnARCVersion,
                  weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/webui/version_handler_win.cc b/chrome/browser/ui/webui/version_handler_win.cc
index dd5ef639..4d97993 100644
--- a/chrome/browser/ui/webui/version_handler_win.cc
+++ b/chrome/browser/ui/webui/version_handler_win.cc
@@ -20,8 +20,9 @@
   VersionHandler::HandleRequestVersionInfo(args);
 
   // Start the asynchronous load of the versions.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&version_utils::win::GetFullWindowsVersion),
       base::BindOnce(&VersionHandlerWindows::OnVersion,
                      weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
index 3828ee252..ddcbd4b5 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -130,7 +130,7 @@
   if (__builtin_available(macOS 10.12.2, *)) {
     // Different profiles have different secrets. (No way to reset
     // browser_context(), so we have to create our own.)
-    auto browser_context = base::WrapUnique(CreateBrowserContext());
+    auto browser_context = CreateBrowserContext();
     auto web_contents = content::WebContentsTester::CreateTestWebContents(
         browser_context.get(), nullptr);
     ChromeAuthenticatorRequestDelegate delegate1(main_rfh(), kRelyingPartyID);
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 3971276..7e3c9918 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -182,7 +182,7 @@
 // Enable additional Crostini session status reporting for
 // managed devices only, i.e. reports of installed apps and kernel version.
 const base::Feature kCrostiniAdditionalEnterpriseReporting{
-    "CrostiniAdditionalEnterpriseReporting", base::FEATURE_DISABLED_BY_DEFAULT};
+    "CrostiniAdditionalEnterpriseReporting", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable advanced access controls for Crostini-related features
 // (e.g. restricting VM CLI tools access, restricting Crostini root access).
@@ -670,6 +670,11 @@
     "TreatUnsafeDownloadsAsActive", base::FEATURE_DISABLED_BY_DEFAULT};
 const char kTreatUnsafeDownloadsAsActiveParamName[] = "ExtensionList";
 
+// Enables or disables the intervention that unloads ad iframes with intensive
+// resource usage.
+const base::Feature kHeavyAdIntervention{"HeavyAdIntervention",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
+
 #if defined(OS_CHROMEOS)
 // Enables or disables usage time state notifier for supervised accounts on
 // Chrome OS.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index e66f4df3..1638549 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -434,6 +434,9 @@
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const char kTreatUnsafeDownloadsAsActiveParamName[];
 
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::Feature kHeavyAdIntervention;
+
 #if defined(OS_CHROMEOS)
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::Feature kUsageTimeStateNotifier;
diff --git a/chrome/test/android/test_trusted_web_activity/BUILD.gn b/chrome/test/android/test_trusted_web_activity/BUILD.gn
index 1201e70..36dac01b 100644
--- a/chrome/test/android/test_trusted_web_activity/BUILD.gn
+++ b/chrome/test/android/test_trusted_web_activity/BUILD.gn
@@ -14,6 +14,6 @@
     "src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java",
   ]
   deps = [
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java"
   ]
 }
diff --git a/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java b/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
index 5735160d..f660b53 100644
--- a/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
+++ b/chrome/test/android/test_trusted_web_activity/src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java
@@ -5,7 +5,8 @@
 package org.chromium.chrome.browser.browserservices;
 
 import android.app.Notification;
-import android.support.customtabs.trusted.TrustedWebActivityService;
+
+import androidx.browser.trusted.TrustedWebActivityService;
 
 /**
  * A TrustedWebActivityService to be used in TrustedWebActivityClientTest.
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc
index 7a3fd7a..4453824 100644
--- a/chrome/test/base/chrome_render_view_host_test_harness.cc
+++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -10,7 +10,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/signin/signin_error_controller_factory.h"
-#include "chrome/test/base/testing_profile.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/shell.h"
@@ -32,8 +31,13 @@
 #endif
 }
 
-content::BrowserContext*
-ChromeRenderViewHostTestHarness::CreateBrowserContext() {
+TestingProfile::TestingFactories
+ChromeRenderViewHostTestHarness::GetTestingFactories() const {
+  return {};
+}
+
+std::unique_ptr<TestingProfile>
+ChromeRenderViewHostTestHarness::CreateTestingProfile() {
   // Maintain the profile directory ourselves so that it isn't deleted along
   // with TestingProfile.  RenderViewHostTestHarness::TearDown() will destroy
   // the profile and also destroy the thread bundle to ensure that any tasks
@@ -47,7 +51,15 @@
   TestingProfile::Builder builder;
   builder.SetPath(temp_dir->GetPath());
 
+  for (auto& pair : GetTestingFactories())
+    builder.AddTestingFactory(pair.first, pair.second);
+
   temp_dirs_.push_back(std::move(temp_dir));
 
-  return builder.Build().release();
+  return builder.Build();
+}
+
+std::unique_ptr<content::BrowserContext>
+ChromeRenderViewHostTestHarness::CreateBrowserContext() {
+  return CreateTestingProfile();
 }
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.h b/chrome/test/base/chrome_render_view_host_test_harness.h
index ce8b35c2..a0c34cb 100644
--- a/chrome/test/base/chrome_render_view_host_test_harness.h
+++ b/chrome/test/base/chrome_render_view_host_test_harness.h
@@ -10,10 +10,9 @@
 
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
+#include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_renderer_host.h"
 
-class TestingProfile;
-
 // Wrapper around RenderViewHostTestHarness that uses a TestingProfile as
 // browser context instead of a TestBrowserContext.
 class ChromeRenderViewHostTestHarness
@@ -33,8 +32,15 @@
   // testing::Test
   void TearDown() override;
 
+  // Returns a list of factories to use when creating the TestingProfile.
+  // Can be overridden by sub-classes if needed.
+  virtual TestingProfile::TestingFactories GetTestingFactories() const;
+
+  // Creates a TestingProfile to use as the browser context.
+  std::unique_ptr<TestingProfile> CreateTestingProfile();
+
   // content::RenderViewHostTestHarness.
-  content::BrowserContext* CreateBrowserContext() override;
+  std::unique_ptr<content::BrowserContext> CreateBrowserContext() final;
 
  private:
   std::vector<std::unique_ptr<base::ScopedTempDir>> temp_dirs_;
diff --git a/chrome/test/data/autofill/captured_sites/cipd.yaml b/chrome/test/data/autofill/captured_sites/cipd.yaml
index f02d77f..6107136d 100644
--- a/chrome/test/data/autofill/captured_sites/cipd.yaml
+++ b/chrome/test/data/autofill/captured_sites/cipd.yaml
@@ -15,365 +15,7 @@
 description: captured sites test archives and recipes.
 install_mode: copy
 data:
-  - file: 1aauto
-  - file: 1aauto.test
-  - file: aarons
-  - file: aarons.test
-  - file: abercrombie
-  - file: abercrombie.test
-  - file: academy
-  - file: academy.test
-  - file: accesscorrections
-  - file: accesscorrections.test
-  - file: aeropostale
-  - file: aeropostale.test
-  - file: amazon
-  - file: amazon.test
-  - file: apmex
-  - file: apmex.test
-  - file: apple
-  - file: apple.test
-  - file: autoanything
-  - file: autoanything.test
-  - file: avon
-  - file: avon.test
-  - file: barnes_and_noble
-  - file: barnes_and_noble.test
-  - file: bath_and_body_works
-  - file: bath_and_body_works.test
-  - file: beachbody
-  - file: beachbody.test
-  - file: bed_bath_beyond
-  - file: bed_bath_beyond.test
-  - file: belk
-  - file: belk.test
-  - file: bestbuy
-  - file: bestbuy.test
-  - file: bodybuilding
-  - file: bodybuilding.test
-  - file: booking
-  - file: booking.test
-  - file: boostmobile
-  - file: boostmobile.test
-  - file: bradfordexchange
-  - file: bradfordexchange.test
-  - file: brandfactoryonline
-  - file: brandfactoryonline.test
-  - file: bricklink
-  - file: bricklink.test
-  - file: broadway
-  - file: broadway.test
-  - file: cabelas
-  - file: cabelas.test
-  - file: cafe_press
-  - file: cafe_press.test
-  - file: cargurus
-  - file: cargurus.test
-  - file: carid
-  - file: carid.test
-  - file: carmax
-  - file: carmax.test
-  - file: cars
-  - file: cars.test
-  - file: carsforsale
-  - file: carsforsale.test
-  - file: carters
-  - file: carters.test
-  - file: catch
-  - file: catch.test
-  - file: cdbaby
-  - file: cdbaby.test
-  - file: cdjapan
-  - file: cdjapan.test
-  - file: cduniverse
-  - file: cduniverse.test
-  - file: channelfireball
-  - file: channelfireball.test
-  - file: chewy
-  - file: chewy.test
-  - file: cinemark
-  - file: cinemark.test
-  - file: coach
-  - file: coach.test
-  - file: collage
-  - file: collage.test
-  - file: coolstuffinc
-  - file: coolstuffinc.test
-  - file: crate_and_barrel
-  - file: crate_and_barrel.test
-  - file: creditonebank
-  - file: creditonebank.test
-  - file: cricketwireless
-  - file: cricketwireless.test
-  - file: crutch_field
-  - file: crutch_field.test
-  - file: customink
-  - file: customink.test
-  - file: cvs
-  - file: cvs.test
-  - file: davidsbridal
-  - file: davidsbridal.test
-  - file: dell
-  - file: dell.test
-  - file: dickblick
-  - file: dickblick.test
-  - file: dicks_sporting_goods
-  - file: dicks_sporting_goods.test
-  - file: dish
-  - file: dish.test
-  - file: duluthtrading
-  - file: duluthtrading.test
-  - file: ebay
-  - file: ebay.test
-  - file: eddiebauer
-  - file: eddiebauer.test
-  - file: elementvape
-  - file: elementvape.test
-  - file: etsy
-  - file: etsy.test
-  - file: evo
-  - file: evo.test
-  - file: expedia
-  - file: expedia.test
-  - file: fanatics
-  - file: fanatics.test
-  - file: fansedge
-  - file: fansedge.test
-  - file: fender
-  - file: fender.test
-  - file: findmeagift
-  - file: findmeagift.test
-  - file: fingerhut
-  - file: fingerhut.test
-  - file: finish_line
-  - file: finish_line.test
-  - file: fromyouflowers
-  - file: fromyouflowers.test
-  - file: frys
-  - file: frys.test
-  - file: gamestop
-  - file: gamestop.test
-  - file: giftcardmall
-  - file: giftcardmall.test
-  - file: globalcashcard
-  - file: globalcashcard.test
-  - file: gnc
-  - file: gnc.test
-  - file: gofreecredit
-  - file: gofreecredit.test
-  - file: golookup
-  - file: golookup.test
-  - file: graze
-  - file: graze.test
-  - file: greendot
-  - file: greendot.test
-  - file: greendot_create_user
-  - file: greendot_create_user.test
-  - file: groupon
-  - file: groupon.test
-  - file: harbor_freight
-  - file: harbor_freight.test
-  - file: hobbylobby
-  - file: hobbylobby.test
-  - file: home_depot
-  - file: home_depot.test
-  - file: horizoncardservices
-  - file: horizoncardservices.test
-  - file: hotels
-  - file: hotels.test
-  - file: indigo
-  - file: indigo.test
-  - file: jet
-  - file: jet.test
-  - file: jetspizza
-  - file: jetspizza.test
-  - file: jetstar
-  - file: jetstar.test
-  - file: joann
-  - file: joann.test
-  - file: jostens
-  - file: jostens.test
-  - file: juno
-  - file: juno.test
-  - file: just_fab
-  - file: just_fab.test
-  - file: kohls
-  - file: kohls.test
-  - file: levi
-  - file: levi.test
-  - file: living_social
-  - file: living_social.test
-  - file: llbean
-  - file: llbean.test
-  - file: lowes
-  - file: lowes.test
-  - file: macys
-  - file: macys.test
-  - file: mango
-  - file: mango.test
-  - file: mapsofindia
-  - file: mapsofindia.test
-  - file: mercurypay
-  - file: mercurypay.test
-  - file: modcloth
-  - file: modcloth.test
-  - file: moma
-  - file: moma.test
-  - file: monoprice
-  - file: monoprice.test
-  - file: movietickets
-  - file: movietickets.test
-  - file: musicians_friend
-  - file: musicians_friend.test
-  - file: nba
-  - file: nba.test
-  - file: neiman_marcus
-  - file: neiman_marcus.test
-  - file: net_a_porter
-  - file: net_a_porter.test
-  - file: netfirstplatinum
-  - file: netfirstplatinum.test
-  - file: netspend
-  - file: netspend.test
-  - file: newegg
-  - file: newegg.test
-  - file: newlook
-  - file: newlook.test
-  - file: nflshop
-  - file: nflshop.test
-  - file: nhl
-  - file: nhl.test
-  - file: nordstrom
-  - file: nordstrom.test
-  - file: northerntool
-  - file: northerntool.test
-  - file: north_face
-  - file: north_face.test
-  - file: notonthehighstreet
-  - file: notonthehighstreet.test
-  - file: nyandcompany
-  - file: nyandcompany.test
-  - file: omahasteaks
-  - file: omahasteaks.test
-  - file: opticsplanet
-  - file: opticsplanet.test
-  - file: oshkosh
-  - file: oshkosh.test
-  - file: oup
-  - file: oup.test
-  - file: overstock
-  - file: overstock.test
-  - file: pac_sun
-  - file: pac_sun.test
-  - file: palmettostatearmory
-  - file: palmettostatearmory.test
-  - file: pandora
-  - file: pandora.test
-  - file: panerabread
-  - file: panerabread.test
-  - file: paparazziaccessories
-  - file: paparazziaccessories.test
-  - file: partycity
-  - file: partycity.test
-  - file: payless
-  - file: payless.test
-  - file: petco
-  - file: petco.test
-  - file: pets_mart
-  - file: pets_mart.test
-  - file: pier1
-  - file: pier1.test
-  - file: pizzahut_uk
-  - file: pizzahut_uk.test
-  - file: polar
-  - file: polar.test
-  - file: pottery_barn
-  - file: pottery_barn.test
-  - file: prima_games
-  - file: prima_games.test
-  - file: qvc
-  - file: qvc.test
-  - file: rakuten
-  - file: rakuten.test
-  - file: represent
-  - file: represent.test
-  - file: rock_auto
-  - file: rock_auto.test
-  - file: rue21.test
-  - file: safishing
-  - file: safishing.test
-  - file: sephora
-  - file: sephora.test
-  - file: sheetmusicplus
-  - file: sheetmusicplus.test
-  - file: sierra_trading_post
-  - file: sierra_trading_post.test
-  - file: speedycash
-  - file: speedycash.test
-  - file: sportsmansguide
-  - file: sportsmansguide.test
-  - file: star_city_games
-  - file: star_city_games.test
-  - file: sweet_water
-  - file: sweet_water.test
-  - file: talbots
-  - file: talbots.test
-  - file: tennis_warehouse
-  - file: tennis_warehouse.test
-  - file: therealreal
-  - file: therealreal.test
-  - file: threadless
-  - file: threadless.test
-  - file: ticket_master
-  - file: ticket_master.test
-  - file: ticketmaster_uk
-  - file: ticketmaster_uk.test
-  - file: tickets
-  - file: tickets.test
-  - file: tillys
-  - file: tillys.test
-  - file: timberland
-  - file: timberland.test
-  - file: torrid
-  - file: torrid.test
-  - file: tractorsupply
-  - file: tractorsupply.test
-  - file: tradepub
-  - file: tradepub.test
-  - file: tradesy
-  - file: tradesy.test
-  - file: uhaul
-  - file: uhaul.test
-  - file: vanillagift
-  - file: vanillagift.test
-  - file: verizonwireless
-  - file: verizonwireless.test
-  - file: victorias_secret
-  - file: victorias_secret.test
-  - file: vitacost
-  - file: vitacost.test
-  - file: walgreen
-  - file: walgreen.test
-  - file: walmart
-  - file: walmart.test
-  - file: walmart_ca
-  - file: walmart_ca.test
-  - file: walmartmoneycard
-  - file: walmartmoneycard.test
-  - file: wayfair
-  - file: wayfair.test
-  - file: west_elm
-  - file: west_elm.test
-  - file: wiley
-  - file: wiley.test
-  - file: williams_sonoma
-  - file: williams_sonoma.test
-  - file: worldmarket
-  - file: worldmarket.test
-  - file: zappos
-  - file: zappos.test
-  - file: zenni_optical
-  - file: zenni_optical.test
-  - file: zulily
-  - file: zulily.test
-
+  - dir: "."
+    exclude:
+      - .*\.yaml
+      - .*\.json
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
new file mode 100644
index 0000000..4b70455
--- /dev/null
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
@@ -0,0 +1,184 @@
+{
+  "tests": [
+    { "site_name": "amazon" },
+    { "site_name": "apmex" },
+    { "site_name": "apple" },
+    { "site_name": "autoanything" },
+    { "site_name": "avon" },
+    { "site_name": "bath_and_body_works" },
+    { "site_name": "beachbody" },
+    { "site_name": "bed_bath_beyond" },
+    { "site_name": "bestbuy" },
+    { "site_name": "bodybuilding" },
+    { "site_name": "booking" },
+    { "site_name": "boostmobile" },
+    { "site_name": "brandfactoryonline" },
+    { "site_name": "bricklink" },
+    { "site_name": "broadway" },
+    { "site_name": "cabelas" },
+    { "site_name": "cafe_press" },
+    { "site_name": "cargurus" },
+    { "site_name": "carid" },
+    { "site_name": "carmax" },
+    { "site_name": "cars" },
+    { "site_name": "carsforsale" },
+    { "site_name": "carters" },
+    { "site_name": "cdjapan" },
+    { "site_name": "cduniverse" },
+    { "site_name": "channelfireball" },
+    { "site_name": "chewy" },
+    { "site_name": "cinemark" },
+    { "site_name": "coolstuffinc" },
+    { "site_name": "crate_and_barrel" },
+    { "site_name": "creditonebank" },
+    { "site_name": "cricketwireless" },
+    { "site_name": "crutch_field" },
+    { "site_name": "davidsbridal" },
+    { "site_name": "dickblick" },
+    { "site_name": "dish" },
+    { "site_name": "eddiebauer" },
+    { "site_name": "etsy" },
+    { "site_name": "evo" },
+    { "site_name": "expedia" },
+    { "site_name": "fanatics" },
+    { "site_name": "fingerhut" },
+    { "site_name": "finish_line" },
+    { "site_name": "frys" },
+    { "site_name": "giftcardmall" },
+    { "site_name": "globalcashcard" },
+    { "site_name": "gnc" },
+    { "site_name": "gofreecredit" },
+    { "site_name": "golookup" },
+    { "site_name": "graze" },
+    { "site_name": "greendot" },
+    { "site_name": "greendot_create_user" },
+    { "site_name": "harbor_freight" },
+    { "site_name": "home_depot" },
+    { "site_name": "hotels" },
+    { "site_name": "indigo" },
+    { "site_name": "jet" },
+    { "site_name": "jetstar" },
+    { "site_name": "joann" },
+    { "site_name": "juno" },
+    { "site_name": "just_fab" },
+    { "site_name": "levi" },
+    { "site_name": "llbean" },
+    { "site_name": "lowes" },
+    { "site_name": "mapsofindia" },
+    { "site_name": "mercurypay" },
+    { "site_name": "modcloth" },
+    { "site_name": "movietickets" },
+    { "site_name": "musicians_friend" },
+    { "site_name": "net_a_porter" },
+    { "site_name": "netspend" },
+    { "site_name": "newlook" },
+    { "site_name": "northerntool" },
+    { "site_name": "notonthehighstreet" },
+    { "site_name": "nyandcompany" },
+    { "site_name": "opticsplanet" },
+    { "site_name": "oup" },
+    { "site_name": "overstock" },
+    { "site_name": "pac_sun" },
+    { "site_name": "paparazziaccessories" },
+    { "site_name": "pier1" },
+    { "site_name": "pizzahut_uk" },
+    { "site_name": "pottery_barn" },
+    { "site_name": "prima_games" },
+    { "site_name": "qvc" },
+    { "site_name": "rakuten" },
+    { "site_name": "rock_auto" },
+    { "site_name": "sheetmusicplus" },
+    { "site_name": "sierra_trading_post" },
+    { "site_name": "speedycash" },
+    { "site_name": "sportsmansguide" },
+    { "site_name": "sweet_water" },
+    { "site_name": "talbots" },
+    { "site_name": "tennis_warehouse" },
+    { "site_name": "therealreal" },
+    { "site_name": "threadless" },
+    { "site_name": "tickets" },
+    { "site_name": "timberland" },
+    { "site_name": "torrid" },
+    { "site_name": "tradepub" },
+    { "site_name": "uhaul" },
+    { "site_name": "vanillagift" },
+    { "site_name": "victorias_secret" },
+    { "site_name": "walgreen" },
+    { "site_name": "walmartmoneycard" },
+    { "site_name": "wayfair" },
+    { "site_name": "west_elm" },
+    { "site_name": "williams_sonoma" },
+    { "site_name": "zappos" },
+    { "site_name": "zulily" },
+    { "site_name": "nba", "expectation":"PASS" },
+    { "site_name": "nhl", "expectation":"PASS" },
+    { "site_name": "nflshop", "expectation":"PASS" },
+    { "site_name": "aarons", "expectation":"PASS" },
+    { "site_name": "aeropostale", "expectation":"PASS" },
+    { "site_name": "belk", "expectation":"PASS" },
+    { "site_name": "catch", "expectation":"PASS" },
+    { "site_name": "cdbaby", "expectation":"PASS" },
+    { "site_name": "coach", "expectation":"PASS" },
+    { "site_name": "customink", "expectation":"PASS" },
+    { "site_name": "dell", "expectation":"PASS" },
+    { "site_name": "fromyouflowers", "expectation":"PASS" },
+    { "site_name": "hobbylobby", "expectation":"PASS" },
+    { "site_name": "jostens", "expectation":"PASS" },
+    { "site_name": "moma", "expectation":"PASS" },
+    { "site_name": "monoprice", "expectation":"PASS" },
+    { "site_name": "palmettostatearmory", "expectation":"PASS" },
+    { "site_name": "pandora", "expectation":"PASS" },
+    { "site_name": "sephora", "expectation":"PASS" },
+    { "site_name": "ticketmaster_uk", "expectation":"PASS" },
+    { "site_name": "vitacost", "expectation":"PASS" },
+    { "site_name": "walmart", "expectation":"PASS" },
+    { "site_name": "1aauto", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "abercrombie", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "academy", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "accesscorrections", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "barnes_and_noble", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "bradfordexchange", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "collage", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "cvs", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "dicks_sporting_goods", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "duluthtrading", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "ebay", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "elementvape", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "fansedge", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "fender", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "findmeagift", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "gamestop", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "groupon", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "horizoncardservices", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "jetspizza", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "kohls", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "living_social", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "macys", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "mango", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "neiman_marcus", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "netfirstplatinum", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "newegg", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "nordstrom", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "north_face", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "omahasteaks", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "oshkosh", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "panerabread", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "partycity", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "payless", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "petco", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "pets_mart", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "polar", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "represent", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "safishing", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "star_city_games", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "ticket_master", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "tillys", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "tractorsupply", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "tradesy", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "verizonwireless", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "walmart_ca", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "wiley", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "worldmarket", "expectation":"PASS", "disabled":true, "bug_number":984664 },
+    { "site_name": "zenni_optical", "expectation":"PASS", "disabled":true, "bug_number":984664 }
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
index ae75c02..cbe6dcb 100644
--- a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
@@ -372,17 +372,6 @@
             TetheringState: "NotDetected"
           }
         }, {
-          Connectable: true,
-          ConnectionState: ConnectionStateType.CONNECTED,
-          GUID: 'stub_wimax_guid',
-          Name: 'wimax',
-          Priority: 0,
-          Source: 'User',
-          Type: NetworkType.WI_MAX,
-          WiMAX: {
-            SignalStrength: 40
-          }
-        }, {
           ConnectionState: ConnectionStateType.CONNECTED,
           GUID: 'stub_vpn1_guid',
           Name: 'vpn1',
@@ -500,7 +489,6 @@
         {State: 'Uninitialized', SIMPresent: true,
          SIMLockStatus: {LockEnabled: true, LockType: '', RetriesLeft: 3},
          Type: 'Cellular' },
-        {State: 'Disabled', Type: 'WiMAX'},
       ],
                result);
     }));
@@ -509,7 +497,6 @@
     // Connected or Connecting networks should be listed first, sorted by type.
     var expected = ['stub_ethernet_guid',
                     'stub_wifi1_guid',
-                    'stub_wimax_guid',
                     'stub_vpn1_guid',
                     'stub_vpn2_guid',
                     'stub_wifi2_guid'];
@@ -848,7 +835,6 @@
     // Connecting to wifi2 should set wifi1 to offline. Connected or Connecting
     // networks should be listed first, sorted by type.
     var expected = ['stub_ethernet_guid',
-                    'stub_wimax_guid',
                     'stub_vpn1_guid',
                     'stub_wifi2_guid',
                     'stub_wifi1_guid',
diff --git a/chrome/test/data/password/captured_sites/cipd.yaml b/chrome/test/data/password/captured_sites/cipd.yaml
index daaefea9a..92feba1 100644
--- a/chrome/test/data/password/captured_sites/cipd.yaml
+++ b/chrome/test/data/password/captured_sites/cipd.yaml
@@ -16,11 +16,7 @@
 description: captured sites test archives and recipes.
 install_mode: copy
 data:
-  - file: sign_in/amazon
-  - file: sign_in/amazon.test
-  - file: sign_in_fill/amazon
-  - file: sign_in_fill/amazon.test
-  - file: sign_up/tumblr
-  - file: sign_up/tumblr.test
-  - file: sign_up_fill/amazon
-  - file: sign_up_fill/amazon.test
\ No newline at end of file
+  - dir: capture_update_pass
+  - dir: sign_in_pass
+  - dir: sign_up_fill
+  - dir: sign_up_pass
diff --git a/chrome/test/data/password/captured_sites/testcases.json b/chrome/test/data/password/captured_sites/testcases.json
new file mode 100644
index 0000000..1615659
--- /dev/null
+++ b/chrome/test/data/password/captured_sites/testcases.json
@@ -0,0 +1,178 @@
+{
+  "tests": [
+    { "scenario_dir":"capture_update_pass", "site_name":"4shared" },
+    { "scenario_dir":"capture_update_pass", "site_name":"allegro" },
+    { "scenario_dir":"capture_update_pass", "site_name":"amazon", "disabled":true, "bug_number":984662 },
+    { "scenario_dir":"capture_update_pass", "site_name":"autodesk" },
+    { "scenario_dir":"capture_update_pass", "site_name":"clever", "disabled":true, "bug_number":984662 },
+    { "scenario_dir":"capture_update_pass", "site_name":"github" },
+    { "scenario_dir":"capture_update_pass", "site_name":"go_daddy", "disabled":true, "bug_number":984662 },
+    { "scenario_dir":"capture_update_pass", "site_name":"grammarly" },
+    { "scenario_dir":"capture_update_pass", "site_name":"indeed" },
+    { "scenario_dir":"capture_update_pass", "site_name":"librus" },
+    { "scenario_dir":"capture_update_pass", "site_name":"mit" },
+    { "scenario_dir":"capture_update_pass", "site_name":"naukri" },
+    { "scenario_dir":"capture_update_pass", "site_name":"nexon" },
+    { "scenario_dir":"capture_update_pass", "site_name":"paypal" },
+    { "scenario_dir":"capture_update_pass", "site_name":"rakuten" },
+    { "scenario_dir":"capture_update_pass", "site_name":"readtheory" },
+    { "scenario_dir":"capture_update_pass", "site_name":"roblox" },
+    { "scenario_dir":"capture_update_pass", "site_name":"southwest" },
+    { "scenario_dir":"capture_update_pass", "site_name":"steam" },
+    { "scenario_dir":"capture_update_pass", "site_name":"the_sims_resource" },
+    { "scenario_dir":"capture_update_pass", "site_name":"united" },
+    { "scenario_dir":"capture_update_pass", "site_name":"wargaming", "disabled":true, "bug_number":984662 },
+    { "scenario_dir":"capture_update_pass", "site_name":"yahoo" },
+    { "scenario_dir":"sign_in_pass", "site_name":"4shared" },
+    { "scenario_dir":"sign_in_pass", "site_name":"airbnb" },
+    { "scenario_dir":"sign_in_pass", "site_name":"allegro" },
+    { "scenario_dir":"sign_in_pass", "site_name":"amazon" },
+    { "scenario_dir":"sign_in_pass", "site_name":"autodesk" },
+    { "scenario_dir":"sign_in_pass", "site_name":"clever" },
+    { "scenario_dir":"sign_in_pass", "site_name":"cryptopia" },
+    { "scenario_dir":"sign_in_pass", "site_name":"dreambox" },
+    { "scenario_dir":"sign_in_pass", "site_name":"ebay" },
+    { "scenario_dir":"sign_in_pass", "site_name":"etsy" },
+    { "scenario_dir":"sign_in_pass", "site_name":"forgeofempires" },
+    { "scenario_dir":"sign_in_pass", "site_name":"freelancer" },
+    { "scenario_dir":"sign_in_pass", "site_name":"garena" },
+    { "scenario_dir":"sign_in_pass", "site_name":"gearbest" },
+    { "scenario_dir":"sign_in_pass", "site_name":"github" },
+    { "scenario_dir":"sign_in_pass", "site_name":"go_daddy" },
+    { "scenario_dir":"sign_in_pass", "site_name":"grammarly" },
+    { "scenario_dir":"sign_in_pass", "site_name":"groupon" },
+    { "scenario_dir":"sign_in_pass", "site_name":"hrblock" },
+    { "scenario_dir":"sign_in_pass", "site_name":"indeed" },
+    { "scenario_dir":"sign_in_pass", "site_name":"instagram" },
+    { "scenario_dir":"sign_in_pass", "site_name":"kakao" },
+    { "scenario_dir":"sign_in_pass", "site_name":"librus" },
+    { "scenario_dir":"sign_in_pass", "site_name":"marriott" },
+    { "scenario_dir":"sign_in_pass", "site_name":"mit" },
+    { "scenario_dir":"sign_in_pass", "site_name":"naukri" },
+    { "scenario_dir":"sign_in_pass", "site_name":"nexon" },
+    { "scenario_dir":"sign_in_pass", "site_name":"nitro_type" },
+    { "scenario_dir":"sign_in_pass", "site_name":"ok_ru" },
+    { "scenario_dir":"sign_in_pass", "site_name":"paypal" },
+    { "scenario_dir":"sign_in_pass", "site_name":"pinterest" },
+    { "scenario_dir":"sign_in_pass", "site_name":"quia" },
+    { "scenario_dir":"sign_in_pass", "site_name":"quizlet", "locally":"FAIL" },
+    { "scenario_dir":"sign_in_pass", "site_name":"rakuten" },
+    { "scenario_dir":"sign_in_pass", "site_name":"readtheory" },
+    { "scenario_dir":"sign_in_pass", "site_name":"rediff" },
+    { "scenario_dir":"sign_in_pass", "site_name":"roblox" },
+    { "scenario_dir":"sign_in_pass", "site_name":"southwest" },
+    { "scenario_dir":"sign_in_pass", "site_name":"steam" },
+    { "scenario_dir":"sign_in_pass", "site_name":"successfactors" },
+    { "scenario_dir":"sign_in_pass", "site_name":"the_sims_resource" },
+    { "scenario_dir":"sign_in_pass", "site_name":"united" },
+    { "scenario_dir":"sign_in_pass", "site_name":"vodafone" },
+    { "scenario_dir":"sign_in_pass", "site_name":"walmart" },
+    { "scenario_dir":"sign_in_pass", "site_name":"wp_pl" },
+    { "scenario_dir":"sign_in_pass", "site_name":"yahoo" },
+    { "scenario_dir":"sign_in_pass", "site_name":"zoho" },
+    { "scenario_dir":"sign_up_fill", "site_name":"4shared", "disabled":true, "bug_number":984662, "locally":"PASS" },
+    { "scenario_dir":"sign_up_fill", "site_name":"aliexpress" },
+    { "scenario_dir":"sign_up_fill", "site_name":"allegro" },
+    { "scenario_dir":"sign_up_fill", "site_name":"amazon" },
+    { "scenario_dir":"sign_up_fill", "site_name":"aol" },
+    { "scenario_dir":"sign_up_fill", "site_name":"autodesk" },
+    { "scenario_dir":"sign_up_fill", "site_name":"battle_net" },
+    { "scenario_dir":"sign_up_fill", "site_name":"bet_365" },
+    { "scenario_dir":"sign_up_fill", "site_name":"clever" },
+    { "scenario_dir":"sign_up_fill", "site_name":"cryptopia", "disabled":true, "bug_number":984662, "locally":"PASS" },
+    { "scenario_dir":"sign_up_fill", "site_name":"daum" },
+    { "scenario_dir":"sign_up_fill", "site_name":"discord_app" },
+    { "scenario_dir":"sign_up_fill", "site_name":"dreambox", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_fill", "site_name":"ea" },
+    { "scenario_dir":"sign_up_fill", "site_name":"ebay" },
+    { "scenario_dir":"sign_up_fill", "site_name":"edmodo" },
+    { "scenario_dir":"sign_up_fill", "site_name":"elvenar", "disabled":true, "bug_number":984662, "locally":"PASS" },
+    { "scenario_dir":"sign_up_fill", "site_name":"epic_games" },
+    { "scenario_dir":"sign_up_fill", "site_name":"forgeofempires", "disabled":true, "bug_number":984662, "locally":"PASS" },
+    { "scenario_dir":"sign_up_fill", "site_name":"freelancer" },
+    { "scenario_dir":"sign_up_fill", "site_name":"garena" },
+    { "scenario_dir":"sign_up_fill", "site_name":"go_daddy" },
+    { "scenario_dir":"sign_up_fill", "site_name":"grammarly" },
+    { "scenario_dir":"sign_up_fill", "site_name":"groupon" },
+    { "scenario_dir":"sign_up_fill", "site_name":"hrblock" },
+    { "scenario_dir":"sign_up_fill", "site_name":"indeed" },
+    { "scenario_dir":"sign_up_fill", "site_name":"instagram" },
+    { "scenario_dir":"sign_up_fill", "site_name":"librus" },
+    { "scenario_dir":"sign_up_fill", "site_name":"moby_max" },
+    { "scenario_dir":"sign_up_fill", "site_name":"naukri" },
+    { "scenario_dir":"sign_up_fill", "site_name":"naver" },
+    { "scenario_dir":"sign_up_fill", "site_name":"olx" },
+    { "scenario_dir":"sign_up_fill", "site_name":"orange" },
+    { "scenario_dir":"sign_up_fill", "site_name":"paypal" },
+    { "scenario_dir":"sign_up_fill", "site_name":"pch" },
+    { "scenario_dir":"sign_up_fill", "site_name":"rakuten" },
+    { "scenario_dir":"sign_up_fill", "site_name":"readtheory" },
+    { "scenario_dir":"sign_up_fill", "site_name":"roblox" },
+    { "scenario_dir":"sign_up_fill", "site_name":"southwest" },
+    { "scenario_dir":"sign_up_fill", "site_name":"successfactors" },
+    { "scenario_dir":"sign_up_fill", "site_name":"telekom" },
+    { "scenario_dir":"sign_up_fill", "site_name":"the_sims_resource" },
+    { "scenario_dir":"sign_up_fill", "site_name":"typing" },
+    { "scenario_dir":"sign_up_fill", "site_name":"upwork" },
+    { "scenario_dir":"sign_up_fill", "site_name":"usps" },
+    { "scenario_dir":"sign_up_fill", "site_name":"vodafone", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_fill", "site_name":"walmart" },
+    { "scenario_dir":"sign_up_fill", "site_name":"wargaming" },
+    { "scenario_dir":"sign_up_fill", "site_name":"xiaomi", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_fill", "site_name":"yahoo" },
+    { "scenario_dir":"sign_up_fill", "site_name":"zoho" },
+    { "scenario_dir":"sign_up_pass", "site_name":"4shared" },
+    { "scenario_dir":"sign_up_pass", "site_name":"adobe" },
+    { "scenario_dir":"sign_up_pass", "site_name":"airbnb" },
+    { "scenario_dir":"sign_up_pass", "site_name":"amazon" },
+    { "scenario_dir":"sign_up_pass", "site_name":"aol" },
+    { "scenario_dir":"sign_up_pass", "site_name":"autodesk", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"battle_net" },
+    { "scenario_dir":"sign_up_pass", "site_name":"booking" },
+    { "scenario_dir":"sign_up_pass", "site_name":"clever" },
+    { "scenario_dir":"sign_up_pass", "site_name":"cryptopia" },
+    { "scenario_dir":"sign_up_pass", "site_name":"discord_app" },
+    { "scenario_dir":"sign_up_pass", "site_name":"ea" },
+    { "scenario_dir":"sign_up_pass", "site_name":"ebay" },
+    { "scenario_dir":"sign_up_pass", "site_name":"edmodo" },
+    { "scenario_dir":"sign_up_pass", "site_name":"elvenar" },
+    { "scenario_dir":"sign_up_pass", "site_name":"epic_games" },
+    { "scenario_dir":"sign_up_pass", "site_name":"etsy" },
+    { "scenario_dir":"sign_up_pass", "site_name":"forgeofempires" },
+    { "scenario_dir":"sign_up_pass", "site_name":"freelancer" },
+    { "scenario_dir":"sign_up_pass", "site_name":"garena" },
+    { "scenario_dir":"sign_up_pass", "site_name":"gearbest" },
+    { "scenario_dir":"sign_up_pass", "site_name":"grammarly" },
+    { "scenario_dir":"sign_up_pass", "site_name":"groupon" },
+    { "scenario_dir":"sign_up_pass", "site_name":"hrblock" },
+    { "scenario_dir":"sign_up_pass", "site_name":"indeed" },
+    { "scenario_dir":"sign_up_pass", "site_name":"instagram" },
+    { "scenario_dir":"sign_up_pass", "site_name":"librus" },
+    { "scenario_dir":"sign_up_pass", "site_name":"marriott" },
+    { "scenario_dir":"sign_up_pass", "site_name":"nitro_type" },
+    { "scenario_dir":"sign_up_pass", "site_name":"orange" },
+    { "scenario_dir":"sign_up_pass", "site_name":"paypal", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"pch" },
+    { "scenario_dir":"sign_up_pass", "site_name":"pinterest", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"quia" },
+    { "scenario_dir":"sign_up_pass", "site_name":"quizlet" },
+    { "scenario_dir":"sign_up_pass", "site_name":"rakuten" },
+    { "scenario_dir":"sign_up_pass", "site_name":"readtheory" },
+    { "scenario_dir":"sign_up_pass", "site_name":"rediff" },
+    { "scenario_dir":"sign_up_pass", "site_name":"roblox" },
+    { "scenario_dir":"sign_up_pass", "site_name":"southwest" },
+    { "scenario_dir":"sign_up_pass", "site_name":"starbucks" },
+    { "scenario_dir":"sign_up_pass", "site_name":"successfactors" },
+    { "scenario_dir":"sign_up_pass", "site_name":"telekom" },
+    { "scenario_dir":"sign_up_pass", "site_name":"typing" },
+    { "scenario_dir":"sign_up_pass", "site_name":"united", "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"upwork" },
+    { "scenario_dir":"sign_up_pass", "site_name":"usps", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"vodafone", "disabled":true, "bug_number":984662, "locally":"FAIL" },
+    { "scenario_dir":"sign_up_pass", "site_name":"walmart" },
+    { "scenario_dir":"sign_up_pass", "site_name":"xiaomi" },
+    { "scenario_dir":"sign_up_pass", "site_name":"yahoo" },
+    { "scenario_dir":"sign_up_pass", "site_name":"zearn" },
+    { "scenario_dir":"sign_up_pass", "site_name":"zoho" }
+  ]
+}
diff --git a/chrome/test/data/webui/chromeos/cr_onc_strings.js b/chrome/test/data/webui/chromeos/cr_onc_strings.js
index 38b5c566..17dff59c 100644
--- a/chrome/test/data/webui/chromeos/cr_onc_strings.js
+++ b/chrome/test/data/webui/chromeos/cr_onc_strings.js
@@ -77,7 +77,6 @@
     'OncWiFi-Security_WPA-PSK': 'OncWiFi-Security_WPA-PSK',
     'OncWiFi-Security_WEP-8021X': 'OncWiFi-Security_WEP-8021X',
     'OncWiFi-SignalStrength': 'OncWiFi-SignalStrength',
-    'OncWiMAX-EAP-Identity': 'OncWiMAX-EAP-Identity',
     'Oncipv4-Gateway': 'Oncipv4-Gateway',
     'Oncipv4-IPAddress': 'Oncipv4-IPAddress',
     'Oncipv4-RoutingPrefix': 'Oncipv4-RoutingPrefix',
diff --git a/chrome/test/data/webui/chromeos/fake_networking_private.js b/chrome/test/data/webui/chromeos/fake_networking_private.js
index 4b31424c..8c2b459 100644
--- a/chrome/test/data/webui/chromeos/fake_networking_private.js
+++ b/chrome/test/data/webui/chromeos/fake_networking_private.js
@@ -38,7 +38,6 @@
         Cellular: {Type: 'Cellular', State: ''},
         Tether: {Type: 'Tether', State: ''},
         VPN: {Type: 'VPN', State: ''},
-        WiMAX: {Type: 'WiMAX', State: ''},
       };
 
       this.networkStates_ = [
diff --git a/chrome/test/data/webui/chromeos/networking_private_constants.js b/chrome/test/data/webui/chromeos/networking_private_constants.js
index 2d3fe0d..d40b1d81 100644
--- a/chrome/test/data/webui/chromeos/networking_private_constants.js
+++ b/chrome/test/data/webui/chromeos/networking_private_constants.js
@@ -73,7 +73,6 @@
   VPN: 'VPN',
   WIRELESS: 'Wireless',
   WI_FI: 'WiFi',
-  WI_MAX: 'WiMAX',
 };
 
 /**
diff --git a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
index cafa762..334dd99d 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
@@ -49,7 +49,6 @@
       OncTypeTether: 'OncTypeTether',
       OncTypeVPN: 'OncTypeVPN',
       OncTypeWiFi: 'OncTypeWiFi',
-      OncTypeWiMAX: 'OncTypeWiMAX',
       networkListItemConnected: 'networkListItemConnected',
       networkListItemConnecting: 'networkListItemConnecting',
       networkListItemConnectingTo: 'networkListItemConnectingTo',
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
index 6e721e32..d1e8d41 100644
--- a/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/internet_page_tests.js
@@ -37,7 +37,6 @@
       OncTypeTether: 'OncTypeTether',
       OncTypeVPN: 'OncTypeVPN',
       OncTypeWiFi: 'OncTypeWiFi',
-      OncTypeWiMAX: 'OncTypeWiMAX',
       networkListItemConnected: 'networkListItemConnected',
       networkListItemConnecting: 'networkListItemConnecting',
       networkListItemConnectingTo: 'networkListItemConnectingTo',
@@ -109,7 +108,6 @@
       assertEquals(1, ethernet.networkStateList.length);
       assertEquals(null, networkSummary_.$$('#Cellular'));
       assertEquals(null, networkSummary_.$$('#VPN'));
-      assertEquals(null, networkSummary_.$$('#WiMAX'));
       assertEquals(null, networkSummary_.$$('#WiFi'));
     });
 
diff --git a/chrome/test/mini_installer/chrome_helper.py b/chrome/test/mini_installer/chrome_helper.py
index d6e2974..4af2e78 100644
--- a/chrome/test/mini_installer/chrome_helper.py
+++ b/chrome/test/mini_installer/chrome_helper.py
@@ -12,13 +12,40 @@
 import win32process
 
 
+def get_process_name(p):
+  """A wrapper to return a psutil.Process name."""
+  # Process.name was a property prior to version 2.0.
+  if psutil.version_info[0] < 2:
+    return p.name
+  # But it's a function since 2.0.
+  return p.name()
+
+
+def get_process_exe(p):
+  """A wrapper to return a psutil.Process exe."""
+  # Process.exe was a property prior to version 2.0.
+  if psutil.version_info[0] < 2:
+    return p.exe
+  # But it's a function since 2.0.
+  return p.exe()
+
+
+def get_process_ppid(p):
+  """A wrapper to return a psutil.Process ppid."""
+  # Process.ppid was a property prior to version 2.0.
+  if psutil.version_info[0] < 2:
+    return p.ppid
+  # But it's a function since 2.0.
+  return p.ppid()
+
+
 def GetProcessIDAndPathPairs():
   """Returns a list of 2-tuples of (process id, process path).
   """
   process_id_and_path_pairs = []
   for process in psutil.process_iter():
     try:
-      process_id_and_path_pairs.append((process.pid, process.exe))
+      process_id_and_path_pairs.append((process.pid, get_process_exe(process)))
     except psutil.Error:
       # It's normal that some processes are not accessible.
       pass
@@ -49,11 +76,12 @@
     chrome_processes = dict()
     for process in psutil.process_iter():
       try:
-        if process.exe == chrome_path:
+        if get_process_exe(process) == chrome_path:
           chrome_processes[process.pid] = process
-          logging.info('Found chrome process %s' % process.exe)
-        elif process.name == os.path.basename(chrome_path):
-          raise Exception('Found other chrome process %s' % process.exe)
+          logging.info('Found chrome process %s' % get_process_exe(process))
+        elif get_process_name(process) == os.path.basename(chrome_path):
+          raise Exception(
+              'Found other chrome process %s' % get_process_exe(process))
       except psutil.Error:
         pass
     return chrome_processes
@@ -64,7 +92,7 @@
     # Find the one whose parent isn't a chrome.exe process.
     for process in chrome_processes.itervalues():
       try:
-        if process.ppid not in chrome_processes:
+        if get_process_ppid(process) not in chrome_processes:
           return process
       except psutil.Error:
         pass
@@ -79,8 +107,8 @@
       process = next(chrome_processes.itervalues())
     if process.is_running():
       logging.info(
-        'Waiting on PID %s for %s %s processes to exit' %
-        (process.pid, len(chrome_processes), process.exe))
+        'Waiting on %s for %s %s processes to exit' %
+        (str(process), len(chrome_processes), get_process_exe(process)))
       process.wait()
     # Check for stragglers and keep waiting until all are gone.
     chrome_processes = GetChromeProcesses(chrome_path)
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 2d9c5e5..20c3d84 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -494,8 +494,8 @@
 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
 
 #if defined(OS_ANDROID)
-  crash_reporter_runner_ = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+  crash_reporter_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
   crash_reporter_runner_->PostTask(
       FROM_HERE,
@@ -506,8 +506,7 @@
   url_request_context_factory_->InitializeOnUIThread(nullptr);
 
   cast_browser_process_->SetConnectivityChecker(ConnectivityChecker::Create(
-      base::CreateSingleThreadTaskRunnerWithTraits(
-          {content::BrowserThread::IO}),
+      base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}),
       url_request_context_factory_->GetSystemGetter()));
 
   cast_browser_process_->SetBrowserContext(
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index c6ba53b..608bc400 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -315,8 +315,7 @@
       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
                           base::Unretained(this)),
       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
-      base::CreateSingleThreadTaskRunnerWithTraits(
-          {content::BrowserThread::UI}),
+      base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}),
       GetMediaTaskRunner(), content::GetSystemConnector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #else
@@ -325,8 +324,7 @@
       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
                           base::Unretained(this)),
       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
-      base::CreateSingleThreadTaskRunnerWithTraits(
-          {content::BrowserThread::UI}),
+      base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}),
       GetMediaTaskRunner(), content::GetSystemConnector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #endif  // defined(USE_ALSA)
@@ -396,7 +394,7 @@
     content::RenderProcessHost* host) {
   // Forcibly trigger I/O-thread URLRequestContext initialization before
   // getting HostResolver.
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE, {content::BrowserThread::IO},
       base::Bind(
           &net::URLRequestContextGetter::GetURLRequestContext,
@@ -488,12 +486,11 @@
       ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
                site_instance->GetId());
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::IO},
-      base::BindOnce(&extensions::InfoMap::RegisterExtensionProcess,
-                     extension_system->info_map(), extension->id(),
-                     site_instance->GetProcess()->GetID(),
-                     site_instance->GetId()));
+  base::PostTask(FROM_HERE, {content::BrowserThread::IO},
+                 base::BindOnce(&extensions::InfoMap::RegisterExtensionProcess,
+                                extension_system->info_map(), extension->id(),
+                                site_instance->GetProcess()->GetID(),
+                                site_instance->GetId()));
 #endif
 }
 
@@ -674,7 +671,7 @@
   std::string session_id =
       CastNavigationUIData::GetSessionIdForWebContents(web_contents);
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(
           &CastContentBrowserClient::SelectClientCertificateOnIOThread,
diff --git a/chromecast/browser/cast_extension_message_filter.cc b/chromecast/browser/cast_extension_message_filter.cc
index bd191bb..2b71c6f0 100644
--- a/chromecast/browser/cast_extension_message_filter.cc
+++ b/chromecast/browser/cast_extension_message_filter.cc
@@ -120,8 +120,8 @@
   }
 
   // This blocks tab loading. Priority is inherited from the calling context.
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock()},
+  base::PostTask(
+      FROM_HERE, {base::ThreadPool(), base::MayBlock()},
       base::BindOnce(&CastExtensionMessageFilter::OnGetExtMessageBundleAsync,
                      this, paths_to_load, extension_id, default_locale,
                      reply_msg));
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc
index 7de18e4..d1cd9990 100644
--- a/chromecast/browser/extensions/cast_extension_system.cc
+++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -130,10 +130,9 @@
       LOG(WARNING) << warning.message;
   }
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&CastExtensionSystem::PostLoadExtension,
-                     base::Unretained(this), extension));
+  base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+                 base::BindOnce(&CastExtensionSystem::PostLoadExtension,
+                                base::Unretained(this), extension));
 
   return extension.get();
 }
@@ -246,12 +245,11 @@
 void CastExtensionSystem::RegisterExtensionWithRequestContexts(
     const Extension* extension,
     const base::Closure& callback) {
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&InfoMap::AddExtension, info_map(),
-                     base::RetainedRef(extension), base::Time::Now(), false,
-                     false),
-      callback);
+  base::PostTaskAndReply(FROM_HERE, {BrowserThread::IO},
+                         base::BindOnce(&InfoMap::AddExtension, info_map(),
+                                        base::RetainedRef(extension),
+                                        base::Time::Now(), false, false),
+                         callback);
 }
 
 void CastExtensionSystem::UnregisterExtensionWithRequestContexts(
diff --git a/chromecast/browser/extensions/cast_extensions_browser_client.cc b/chromecast/browser/extensions/cast_extensions_browser_client.cc
index 7cfc748d..48d9dfaf 100644
--- a/chromecast/browser/extensions/cast_extensions_browser_client.cc
+++ b/chromecast/browser/extensions/cast_extensions_browser_client.cc
@@ -227,7 +227,7 @@
     const std::string& event_name,
     std::unique_ptr<base::ListValue> args) {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    base::PostTaskWithTraits(
+    base::PostTask(
         FROM_HERE, {BrowserThread::UI},
         base::BindOnce(&CastExtensionsBrowserClient::BroadcastEventToRenderers,
                        base::Unretained(this), histogram_value, event_name,
diff --git a/chromecast/browser/metrics/external_metrics.cc b/chromecast/browser/metrics/external_metrics.cc
index 52ae036..4f11233 100644
--- a/chromecast/browser/metrics/external_metrics.cc
+++ b/chromecast/browser/metrics/external_metrics.cc
@@ -57,8 +57,8 @@
 scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner() {
   // Note that CollectEvents accesses a global singleton, and thus
   // scheduling with CONTINUE_ON_SHUTDOWN might not be safe.
-  return base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+  return base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
@@ -103,7 +103,7 @@
 }
 
 void ExternalMetrics::RecordCrash(const std::string& crash_kind) {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&CastStabilityMetricsProvider::LogExternalCrash,
                      base::Unretained(stability_provider_), crash_kind));
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index f78e84fe..a3b3de5 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -86,8 +86,7 @@
 
   scoped_refptr<base::SingleThreadTaskRunner>
       GetNetworkTaskRunner() const override {
-    return base::CreateSingleThreadTaskRunnerWithTraits(
-        {content::BrowserThread::IO});
+    return base::CreateSingleThreadTaskRunner({content::BrowserThread::IO});
   }
 
  private:
@@ -127,8 +126,7 @@
 
   scoped_refptr<base::SingleThreadTaskRunner>
       GetNetworkTaskRunner() const override {
-    return base::CreateSingleThreadTaskRunnerWithTraits(
-        {content::BrowserThread::IO});
+    return base::CreateSingleThreadTaskRunner({content::BrowserThread::IO});
   }
 
  private:
@@ -166,8 +164,7 @@
   pref_proxy_config_tracker_impl_ =
       std::make_unique<PrefProxyConfigTrackerImpl>(
           CastBrowserProcess::GetInstance()->pref_service(),
-          base::CreateSingleThreadTaskRunnerWithTraits(
-              {content::BrowserThread::IO}));
+          base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}));
 
   proxy_config_service_ =
       pref_proxy_config_tracker_impl_->CreateTrackingProxyConfigService(
@@ -263,10 +260,10 @@
       switches::kEnableLocalFileAccesses)) {
     set_protocol = job_factory->SetProtocolHandler(
         url::kFileScheme,
-        std::make_unique<net::FileProtocolHandler>(
-            base::CreateTaskRunnerWithTraits(
-                {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-                 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
+        std::make_unique<net::FileProtocolHandler>(base::CreateTaskRunner(
+            {base::ThreadPool(), base::MayBlock(),
+             base::TaskPriority::BEST_EFFORT,
+             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
     DCHECK(set_protocol);
   }
 
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc b/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
index 3807c267..91eaf7e8 100644
--- a/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
+++ b/chromecast/device/bluetooth/le/le_scan_manager_impl_test.cc
@@ -49,8 +49,9 @@
 class LeScanManagerTest : public ::testing::Test {
  protected:
   LeScanManagerTest()
-      : io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
-            {base::TaskPriority::BEST_EFFORT, base::MayBlock()})),
+      : io_task_runner_(base::CreateSingleThreadTaskRunner(
+            {base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
+             base::MayBlock()})),
         le_scan_manager_(&le_scanner_) {
     le_scan_manager_.Initialize(io_task_runner_);
     le_scan_manager_.AddObserver(&mock_observer_);
diff --git a/chromeos/dbus/shill/fake_shill_manager_client.cc b/chromeos/dbus/shill/fake_shill_manager_client.cc
index 5b3699a..c9aee20 100644
--- a/chromeos/dbus/shill/fake_shill_manager_client.cc
+++ b/chromeos/dbus/shill/fake_shill_manager_client.cc
@@ -102,11 +102,9 @@
     return 1;
   if (technology == shill::kTypeWifi)
     return 2;
-  if (technology == shill::kTypeWimax)
-    return 3;
   if (technology == shill::kTypeCellular)
-    return 4;
-  return 5;
+    return 3;
+  return 4;
 }
 
 int GetSecurityOrder(const base::Value& dict) {
@@ -826,24 +824,6 @@
     }
   }
 
-  // Wimax
-  const std::string kWimaxPath = "/service/wimax1";
-  state = GetInitialStateForType(shill::kTypeWimax, &enabled);
-  if (state != kTechnologyUnavailable) {
-    AddTechnology(shill::kTypeWimax, enabled);
-    devices->AddDevice("/device/wimax1", shill::kTypeWimax,
-                       "stub_wimax_device1");
-
-    services->AddService(kWimaxPath, "wimax1_guid", "wimax1" /* name */,
-                         shill::kTypeWimax, state, add_to_visible);
-    services->SetServiceProperty(kWimaxPath, shill::kConnectableProperty,
-                                 base::Value(true));
-    base::Value strength_value(80);
-    services->SetServiceProperty(kWimaxPath, shill::kSignalStrengthProperty,
-                                 strength_value);
-    profiles->AddService(shared_profile, kWimaxPath);
-  }
-
   // Cellular
   state = GetInitialStateForType(shill::kTypeCellular, &enabled);
   VLOG(1) << "Cellular state: " << state << " Enabled: " << enabled;
@@ -1257,8 +1237,7 @@
     type_arg = shill::kTypeEthernet;
 
   if (type_arg != shill::kTypeEthernet && type_arg != shill::kTypeWifi &&
-      type_arg != shill::kTypeCellular && type_arg != shill::kTypeWimax &&
-      type_arg != shill::kTypeVPN) {
+      type_arg != shill::kTypeCellular && type_arg != shill::kTypeVPN) {
     LOG(WARNING) << "Unrecognized Shill network type: " << type_arg;
     return false;
   }
diff --git a/chromeos/network/network_connect.cc b/chromeos/network/network_connect.cc
index 487f78f..4a43bda6 100644
--- a/chromeos/network/network_connect.cc
+++ b/chromeos/network/network_connect.cc
@@ -120,11 +120,6 @@
     return;
   }
 
-  if (network->type() == shill::kTypeWimax) {
-    delegate_->ShowNetworkConfigure(network_id);
-    return;
-  }
-
   if (network->type() == shill::kTypeVPN) {
     // Third-party VPNs handle configuration UI themselves.
     if (network->GetVpnProviderType() != shill::kProviderThirdPartyVpn)
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index d0a1f94..4149d3f 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -237,10 +237,8 @@
     return false;
   }
 
-  // By convention, all visible WiFi and WiMAX networks have a
-  // SignalStrength > 0.
-  if ((type() == shill::kTypeWifi || type() == shill::kTypeWimax) &&
-      visible() && signal_strength_ <= 0) {
+  // By convention, all visible WiFi networks have a SignalStrength > 0.
+  if (type() == shill::kTypeWifi && visible() && signal_strength_ <= 0) {
     signal_strength_ = 1;
   }
 
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index 6ff32a8..80f45ba 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -1989,15 +1989,6 @@
   if (type.MatchesType(shill::kTypeWifi))
     return shill::kTypeWifi;
 
-  if (type.Equals(NetworkTypePattern::Wimax()))
-    return shill::kTypeWimax;
-
-  // Prefer WiMAX over Cellular only if it's available.
-  if (type.MatchesType(shill::kTypeWimax) &&
-      shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
-    return shill::kTypeWimax;
-  }
-
   if (type.MatchesType(shill::kTypeCellular))
     return shill::kTypeCellular;
 
@@ -2015,8 +2006,6 @@
     technologies.emplace_back(shill::kTypeEthernet);
   if (type.MatchesType(shill::kTypeWifi))
     technologies.emplace_back(shill::kTypeWifi);
-  if (type.MatchesType(shill::kTypeWimax))
-    technologies.emplace_back(shill::kTypeWimax);
   if (type.MatchesType(shill::kTypeCellular))
     technologies.emplace_back(shill::kTypeCellular);
   if (type.MatchesType(shill::kTypeBluetooth))
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index e88f4c96..65ea58f 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -766,37 +766,40 @@
 }
 
 TEST_F(NetworkStateHandlerTest, TechnologyState) {
-  manager_test_->RemoveTechnology(shill::kTypeWimax);
+  manager_test_->RemoveTechnology(shill::kTypeWifi);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
-      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
+      network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
 
-  manager_test_->AddTechnology(shill::kTypeWimax, false);
+  manager_test_->AddTechnology(shill::kTypeWifi, false);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_AVAILABLE,
-      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
+      network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
 
-  manager_test_->SetTechnologyInitializing(shill::kTypeWimax, true);
+  manager_test_->SetTechnologyInitializing(shill::kTypeWifi, true);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
-      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
+      network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
 
-  manager_test_->SetTechnologyInitializing(shill::kTypeWimax, false);
+  manager_test_->SetTechnologyInitializing(shill::kTypeWifi, false);
   network_state_handler_->SetTechnologyEnabled(
-      NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
+      NetworkTypePattern::WiFi(), true, network_handler::ErrorCallback());
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_ENABLED,
-      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
+      network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
 
-  manager_test_->RemoveTechnology(shill::kTypeWimax);
+  manager_test_->RemoveTechnology(shill::kTypeWifi);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
-      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
+      network_state_handler_->GetTechnologyState(NetworkTypePattern::WiFi()));
+
+  // Restore wifi technology
+  manager_test_->AddTechnology(shill::kTypeWifi, true);
 }
 
 TEST_F(NetworkStateHandlerTest, TetherTechnologyState) {
diff --git a/chromeos/network/network_state_test_helper.cc b/chromeos/network/network_state_test_helper.cc
index 50034ce5..a302256 100644
--- a/chromeos/network/network_state_test_helper.cc
+++ b/chromeos/network/network_state_test_helper.cc
@@ -184,12 +184,6 @@
       network->wifi = std::move(wifi);
       break;
     }
-    case network_config::mojom::NetworkType::kWiMAX: {
-      auto wimax = network_config::mojom::WiMAXStateProperties::New();
-      wimax->signal_strength = signal_strength;
-      network->wimax = std::move(wimax);
-      break;
-    }
   }
   return network;
 }
diff --git a/chromeos/network/network_type_pattern.cc b/chromeos/network/network_type_pattern.cc
index 4f42f0d..9e2262e 100644
--- a/chromeos/network/network_type_pattern.cc
+++ b/chromeos/network/network_type_pattern.cc
@@ -25,12 +25,11 @@
   kNetworkTypeNone = 0,
   kNetworkTypeEthernet = 1 << 0,
   kNetworkTypeWifi = 1 << 1,
-  kNetworkTypeWimax = 1 << 2,
-  kNetworkTypeCellular = 1 << 3,
-  kNetworkTypeVPN = 1 << 4,
-  kNetworkTypeEthernetEap = 1 << 5,
-  kNetworkTypeBluetooth = 1 << 6,
-  kNetworkTypeTether = 1 << 7
+  kNetworkTypeCellular = 1 << 2,
+  kNetworkTypeVPN = 1 << 3,
+  kNetworkTypeEthernetEap = 1 << 4,
+  kNetworkTypeBluetooth = 1 << 5,
+  kNetworkTypeTether = 1 << 6
 };
 
 struct ShillToBitFlagEntry {
@@ -39,7 +38,6 @@
 } shill_type_to_flag[] = {{shill::kTypeEthernet, kNetworkTypeEthernet},
                           {shill::kTypeEthernetEap, kNetworkTypeEthernetEap},
                           {shill::kTypeWifi, kNetworkTypeWifi},
-                          {shill::kTypeWimax, kNetworkTypeWimax},
                           {shill::kTypeCellular, kNetworkTypeCellular},
                           {shill::kTypeVPN, kNetworkTypeVPN},
                           {shill::kTypeBluetooth, kNetworkTypeBluetooth},
@@ -63,20 +61,19 @@
 
 // static
 NetworkTypePattern NetworkTypePattern::Wireless() {
-  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeWimax |
-                            kNetworkTypeCellular | kNetworkTypeTether);
-}
-
-// static
-NetworkTypePattern NetworkTypePattern::Mobile() {
-  return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeWimax |
+  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeCellular |
                             kNetworkTypeTether);
 }
 
 // static
+NetworkTypePattern NetworkTypePattern::Mobile() {
+  return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeTether);
+}
+
+// static
 NetworkTypePattern NetworkTypePattern::Physical() {
-  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeWimax |
-                            kNetworkTypeCellular | kNetworkTypeEthernet);
+  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeCellular |
+                            kNetworkTypeEthernet);
 }
 
 // static
@@ -110,11 +107,6 @@
 }
 
 // static
-NetworkTypePattern NetworkTypePattern::Wimax() {
-  return NetworkTypePattern(kNetworkTypeWimax);
-}
-
-// static
 NetworkTypePattern NetworkTypePattern::Tether() {
   return NetworkTypePattern(kNetworkTypeTether);
 }
diff --git a/chromeos/network/network_type_pattern.h b/chromeos/network/network_type_pattern.h
index 6479a89..13d8da6c 100644
--- a/chromeos/network/network_type_pattern.h
+++ b/chromeos/network/network_type_pattern.h
@@ -23,7 +23,7 @@
   // Matches wireless (WiFi, Cellular, etc.) networks
   static NetworkTypePattern Wireless();
 
-  // Matches Cellular, WiMAX, or Tether networks.
+  // Matches Cellular or Tether networks.
   static NetworkTypePattern Mobile();
 
   // Matches Physical networks (i.e. excludes Tether and VPN).
@@ -41,7 +41,6 @@
   static NetworkTypePattern WiFi();
   static NetworkTypePattern Cellular();
   static NetworkTypePattern VPN();
-  static NetworkTypePattern Wimax();
 
   static NetworkTypePattern Tether();
 
diff --git a/chromeos/network/network_type_pattern_unittest.cc b/chromeos/network/network_type_pattern_unittest.cc
index 3ed6ce14..294f52cb 100644
--- a/chromeos/network/network_type_pattern_unittest.cc
+++ b/chromeos/network/network_type_pattern_unittest.cc
@@ -21,7 +21,6 @@
         mobile_(NetworkTypePattern::Mobile()),
         physical_(NetworkTypePattern::Physical()),
         non_virtual_(NetworkTypePattern::NonVirtual()),
-        wimax_(NetworkTypePattern::Wimax()),
         wireless_(NetworkTypePattern::Wireless()),
         tether_(NetworkTypePattern::Tether()),
         vpn_(NetworkTypePattern::VPN()),
@@ -41,7 +40,6 @@
   const NetworkTypePattern mobile_;
   const NetworkTypePattern physical_;
   const NetworkTypePattern non_virtual_;
-  const NetworkTypePattern wimax_;
   const NetworkTypePattern wireless_;
   const NetworkTypePattern tether_;
   const NetworkTypePattern vpn_;
@@ -51,18 +49,16 @@
 }  // namespace
 
 TEST_F(NetworkTypePatternTest, MatchesType) {
-  // Mobile contains Cellular, Wimax, and Tether.
+  // Mobile contains Cellular and Tether.
   EXPECT_TRUE(mobile_.MatchesType(shill::kTypeCellular));
-  EXPECT_TRUE(mobile_.MatchesType(shill::kTypeWimax));
   EXPECT_TRUE(mobile_.MatchesType(kTypeTether));
   EXPECT_FALSE(mobile_.MatchesType(shill::kTypeWifi));
   EXPECT_FALSE(mobile_.MatchesType(shill::kTypeEthernet));
   EXPECT_FALSE(mobile_.MatchesType(shill::kTypeVPN));
 
-  // Wireless contains Wifi, Cellular, Wimax, and Tether.
+  // Wireless contains Wifi, Cellular and Tether.
   EXPECT_TRUE(wireless_.MatchesType(shill::kTypeWifi));
   EXPECT_TRUE(wireless_.MatchesType(shill::kTypeCellular));
-  EXPECT_TRUE(wireless_.MatchesType(shill::kTypeWimax));
   EXPECT_TRUE(wireless_.MatchesType(kTypeTether));
   EXPECT_FALSE(wireless_.MatchesType(shill::kTypeEthernet));
   EXPECT_FALSE(wireless_.MatchesType(shill::kTypeVPN));
@@ -71,7 +67,6 @@
   EXPECT_TRUE(physical_.MatchesType(shill::kTypeCellular));
   EXPECT_TRUE(physical_.MatchesType(shill::kTypeWifi));
   EXPECT_TRUE(physical_.MatchesType(shill::kTypeEthernet));
-  EXPECT_TRUE(physical_.MatchesType(shill::kTypeWimax));
   EXPECT_FALSE(physical_.MatchesType(kTypeTether));
   EXPECT_FALSE(physical_.MatchesType(shill::kTypeVPN));
 
@@ -79,12 +74,8 @@
   EXPECT_TRUE(non_virtual_.MatchesType(shill::kTypeCellular));
   EXPECT_TRUE(non_virtual_.MatchesType(shill::kTypeWifi));
   EXPECT_TRUE(non_virtual_.MatchesType(shill::kTypeEthernet));
-  EXPECT_TRUE(non_virtual_.MatchesType(shill::kTypeWimax));
   EXPECT_TRUE(non_virtual_.MatchesType(kTypeTether));
   EXPECT_FALSE(non_virtual_.MatchesType(shill::kTypeVPN));
-
-  EXPECT_TRUE(wimax_.MatchesType(shill::kTypeWimax));
-  EXPECT_FALSE(wimax_.MatchesType(kTypeTether));
 }
 
 TEST_F(NetworkTypePatternTest, MatchesPattern) {
@@ -125,10 +116,10 @@
   EXPECT_TRUE(cellular_.Equals(primitive_cellular));
   EXPECT_TRUE(primitive_cellular.Equals(cellular_));
 
-  const NetworkTypePattern primitive_wimax =
-      NetworkTypePattern::Primitive(shill::kTypeWimax);
-  EXPECT_TRUE(wimax_.Equals(primitive_wimax));
-  EXPECT_TRUE(primitive_wimax.Equals(wimax_));
+  const NetworkTypePattern primitive_wifi =
+      NetworkTypePattern::Primitive(shill::kTypeWifi);
+  EXPECT_TRUE(wifi_.Equals(primitive_wifi));
+  EXPECT_TRUE(primitive_wifi.Equals(wifi_));
 }
 
 TEST_F(NetworkTypePatternTest, Or) {
@@ -145,7 +136,6 @@
   EXPECT_EQ(non_virtual_.ToDebugString(), "PatternNonVirtual");
   EXPECT_EQ(ethernet_.ToDebugString(), shill::kTypeEthernet);
   EXPECT_EQ(cellular_.ToDebugString(), shill::kTypeCellular);
-  EXPECT_EQ(wimax_.ToDebugString(), shill::kTypeWimax);
   EXPECT_EQ(tether_.ToDebugString(), kTypeTether);
   EXPECT_EQ(wifi_.ToDebugString(), shill::kTypeWifi);
   EXPECT_EQ(vpn_.ToDebugString(), shill::kTypeVPN);
diff --git a/chromeos/network/network_util.h b/chromeos/network/network_util.h
index 7146c18..e36ed20 100644
--- a/chromeos/network/network_util.h
+++ b/chromeos/network/network_util.h
@@ -132,7 +132,7 @@
     int limit);
 
 // Returns the Shill type corresponding to ONC |type| or an empty string if
-// there is no match. Only valid for ethernet, wifi, wimax, cellular, and vpn.
+// there is no match. Only valid for ethernet, wifi, cellular, and vpn.
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 std::string TranslateONCTypeToShill(const std::string& type);
 
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc
index 7d820f30..58576d8e 100644
--- a/chromeos/network/onc/onc_signature.cc
+++ b/chromeos/network/onc/onc_signature.cc
@@ -243,16 +243,6 @@
     {::onc::wifi::kTetheringState, &kStringSignature},
     {NULL}};
 
-const OncFieldSignature wimax_fields[] = {
-    {::onc::kRecommended, &kRecommendedSignature},
-    {::onc::wimax::kAutoConnect, &kBoolSignature},
-    {::onc::wimax::kEAP, &kEAPSignature},
-    {NULL}};
-
-const OncFieldSignature wimax_with_state_fields[] = {
-    {::onc::wimax::kSignalStrength, &kIntegerSignature},
-    {NULL}};
-
 const OncFieldSignature cellular_payment_portal_fields[] = {
     {::onc::cellular_payment_portal::kMethod, &kStringSignature},
     {::onc::cellular_payment_portal::kPostData, &kStringSignature},
@@ -343,7 +333,6 @@
     {::onc::network_config::kType, &kStringSignature},
     {::onc::network_config::kVPN, &kVPNSignature},
     {::onc::network_config::kWiFi, &kWiFiSignature},
-    {::onc::network_config::kWimax, &kWiMAXSignature},
     {NULL}};
 
 const OncFieldSignature network_with_state_fields[] = {
@@ -358,7 +347,6 @@
     {::onc::network_config::kSource, &kStringSignature},
     {::onc::network_config::kTether, &kTetherWithStateSignature},
     {::onc::network_config::kWiFi, &kWiFiWithStateSignature},
-    {::onc::network_config::kWimax, &kWiMAXWithStateSignature},
     {NULL}};
 
 const OncFieldSignature global_network_configuration_fields[] = {
@@ -440,8 +428,6 @@
     base::Value::Type::DICTIONARY, proxy_settings_fields, NULL};
 const OncValueSignature kWiFiSignature = {base::Value::Type::DICTIONARY,
                                           wifi_fields, NULL};
-const OncValueSignature kWiMAXSignature = {base::Value::Type::DICTIONARY,
-                                           wimax_fields, NULL};
 const OncValueSignature kCertificateSignature = {base::Value::Type::DICTIONARY,
                                                  certificate_fields, NULL};
 const OncValueSignature kNetworkConfigurationSignature = {
@@ -467,9 +453,6 @@
 const OncValueSignature kTetherWithStateSignature = {
     base::Value::Type::DICTIONARY, tether_with_state_fields, NULL,
     &kTetherSignature};
-const OncValueSignature kWiMAXWithStateSignature = {
-    base::Value::Type::DICTIONARY, wimax_with_state_fields, NULL,
-    &kWiMAXSignature};
 const OncValueSignature kCellularSignature = {base::Value::Type::DICTIONARY,
                                               cellular_fields, NULL};
 const OncValueSignature kCellularWithStateSignature = {
diff --git a/chromeos/network/onc/onc_signature.h b/chromeos/network/onc/onc_signature.h
index 031d219..c900920 100644
--- a/chromeos/network/onc/onc_signature.h
+++ b/chromeos/network/onc/onc_signature.h
@@ -78,8 +78,6 @@
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kWiFiSignature;
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
-extern const OncValueSignature kWiMAXSignature;
-COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kCertificateSignature;
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kNetworkConfigurationSignature;
@@ -98,8 +96,6 @@
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kWiFiWithStateSignature;
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
-extern const OncValueSignature kWiMAXWithStateSignature;
-COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kCellularSignature;
 COMPONENT_EXPORT(CHROMEOS_NETWORK)
 extern const OncValueSignature kCellularWithStateSignature;
diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc
index ce7d850a..39b16d5 100644
--- a/chromeos/network/onc/onc_translation_tables.cc
+++ b/chromeos/network/onc/onc_translation_tables.cc
@@ -151,13 +151,6 @@
     {::onc::wifi::kTetheringState, shill::kTetheringProperty},
     {nullptr}};
 
-const FieldTranslationEntry wimax_fields[] = {
-    {::onc::wimax::kAutoConnect, shill::kAutoConnectProperty},
-    // This dictionary is converted during translation, see onc_translator_*.
-    // { ::onc::wimax::kEAP, shill::kEap*},
-    {::onc::wimax::kSignalStrength, shill::kSignalStrengthProperty},
-    {nullptr}};
-
 const FieldTranslationEntry cellular_apn_fields[] = {
     {::onc::cellular_apn::kAccessPointName, shill::kApnProperty},
     {::onc::cellular_apn::kName, shill::kApnNameProperty},
@@ -274,8 +267,6 @@
     {&kTetherWithStateSignature, tether_fields},
     {&kWiFiSignature, wifi_fields},
     {&kWiFiWithStateSignature, wifi_fields},
-    {&kWiMAXSignature, wimax_fields},
-    {&kWiMAXWithStateSignature, wimax_fields},
     {&kCellularApnSignature, cellular_apn_fields},
     {&kCellularFoundNetworkSignature, cellular_found_network_fields},
     {&kCellularPaymentPortalSignature, cellular_payment_portal_fields},
@@ -314,7 +305,8 @@
     // kTypeEthernetEap is set in onc_translator_onc_to_shill.cc.
     //  { ::onc::network_type::kEthernet, shill::kTypeEthernetEap },
     {::onc::network_type::kWiFi, shill::kTypeWifi},
-    {::onc::network_type::kWimax, shill::kTypeWimax},
+    // wimax entries are ignored in onc_translator_onc_to_shill.cc.
+    // {::onc::network_type::kWimax, shill::kTypeWimax},
     {::onc::network_type::kCellular, shill::kTypeCellular},
     {::onc::network_type::kVPN, shill::kTypeVPN},
     {::onc::network_type::kTether, kTypeTether},
diff --git a/chromeos/network/onc/onc_translator_onc_to_shill.cc b/chromeos/network/onc/onc_translator_onc_to_shill.cc
index 50a2266..c503ee3 100644
--- a/chromeos/network/onc/onc_translator_onc_to_shill.cc
+++ b/chromeos/network/onc/onc_translator_onc_to_shill.cc
@@ -299,7 +299,6 @@
 }
 
 void LocalTranslator::TranslateEAP() {
-  // Note: EAP.Outer may be empty for WiMAX configurations.
   std::string outer;
   onc_object_->GetStringWithoutPathExpansion(::onc::eap::kOuter, &outer);
   if (!outer.empty())
@@ -361,6 +360,11 @@
   onc_object_->GetStringWithoutPathExpansion(::onc::network_config::kType,
                                              &type);
 
+  if (type == ::onc::network_type::kWimaxDeprecated) {
+    NET_LOG(ERROR) << "WiMAX ONC configuration is no longer supported.";
+    return;
+  }
+
   // Note; The Ethernet type might be overridden to EthernetEap in
   // TranslateEthernet if Ethernet specific properties are provided.
   TranslateWithTableAndSet(type, kNetworkTypeTable, shill::kTypeProperty);
@@ -495,7 +499,10 @@
 
     const OncFieldSignature* field_signature =
         GetFieldSignature(signature, it.key());
-
+    if (!field_signature) {
+      NET_LOG(ERROR) << "Unexpected or deprecated ONC key: " << it.key();
+      continue;
+    }
     TranslateONCHierarchy(*field_signature->value_signature, *inner_object,
                           shill_dictionary);
   }
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc
index cf5d5dfa..32d293c 100644
--- a/chromeos/network/onc/onc_translator_shill_to_onc.cc
+++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -114,7 +114,6 @@
   void TranslateThirdPartyVPN();
   void TranslateVPN();
   void TranslateWiFiWithState();
-  void TranslateWiMAXWithState();
   void TranslateCellularWithState();
   void TranslateCellularDevice();
   void TranslateNetworkWithState();
@@ -200,8 +199,6 @@
     TranslateThirdPartyVPN();
   } else if (onc_signature_ == &kWiFiWithStateSignature) {
     TranslateWiFiWithState();
-  } else if (onc_signature_ == &kWiMAXWithStateSignature) {
-    TranslateWiMAXWithState();
   } else if (onc_signature_ == &kCellularWithStateSignature) {
     if (field_translation_table_ == kCellularDeviceTable)
       TranslateCellularDevice();
@@ -403,11 +400,6 @@
   TranslateAndAddNestedObject(::onc::wifi::kEAP);
 }
 
-void ShillToONCTranslator::TranslateWiMAXWithState() {
-  CopyPropertiesAccordingToSignature();
-  TranslateAndAddNestedObject(::onc::wimax::kEAP);
-}
-
 void ShillToONCTranslator::TranslateCellularWithState() {
   CopyPropertiesAccordingToSignature();
   TranslateWithTableAndSet(shill::kActivationStateProperty,
diff --git a/chromeos/network/onc/onc_translator_unittest.cc b/chromeos/network/onc/onc_translator_unittest.cc
index 3202a2c4..1fcf4fcc 100644
--- a/chromeos/network/onc/onc_translator_unittest.cc
+++ b/chromeos/network/onc/onc_translator_unittest.cc
@@ -70,6 +70,8 @@
         std::make_pair("vpn_ipsec_clientcert_pkcs11.onc",
                        "shill_vpn_ipsec_clientcert_pkcs11.json"),
         std::make_pair("cellular.onc", "shill_cellular.json"),
+        // WiMAX is deprecated, but we need to ensure older ONC configurations
+        // are handled gracefully.
         std::make_pair("wimax.onc", "shill_wimax.json"),
         std::make_pair("third_party_vpn.onc", "shill_third_party_vpn.json"),
         std::make_pair("arc_vpn.onc", "shill_arc_vpn.json"),
@@ -143,8 +145,6 @@
                        "translation_of_shill_wifi_proxy_pac.onc"),
         std::make_pair("shill_cellular_with_state.json",
                        "translation_of_shill_cellular_with_state.onc"),
-        std::make_pair("shill_wimax_with_state.json",
-                       "translation_of_shill_wimax_with_state.onc"),
         std::make_pair("shill_output_third_party_vpn.json",
                        "third_party_vpn.onc"),
         std::make_pair(
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 907057b4..1046c18 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -1065,8 +1065,6 @@
     return NetworkTypePattern::VPN();
   if (type == ::onc::network_type::kWiFi)
     return NetworkTypePattern::WiFi();
-  if (type == ::onc::network_type::kWimax)
-    return NetworkTypePattern::Wimax();
   if (type == ::onc::network_type::kWireless)
     return NetworkTypePattern::Wireless();
   NOTREACHED() << "Unrecognized ONC type: " << type;
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc
index 4663f0a6..3dd6f07 100644
--- a/chromeos/network/onc/onc_validator.cc
+++ b/chromeos/network/onc/onc_validator.cc
@@ -622,10 +622,17 @@
 bool Validator::ValidateNetworkConfiguration(base::DictionaryValue* result) {
   using namespace ::onc::network_config;
 
+  const std::string* onc_type = result->FindStringKey(kType);
+  if (onc_type && *onc_type == ::onc::network_type::kWimaxDeprecated) {
+    AddValidationIssue(/*is_error=*/false, "WiMax is deprecated");
+    return true;
+  }
+
   const char* const kValidTypes[] = {
       ::onc::network_type::kEthernet, ::onc::network_type::kVPN,
       ::onc::network_type::kWiFi,     ::onc::network_type::kCellular,
-      ::onc::network_type::kWimax,    ::onc::network_type::kTether};
+      ::onc::network_type::kTether,
+  };
   const std::vector<const char*> valid_types(toVector(kValidTypes));
   const char* const kValidIPConfigTypes[] = {kIPConfigTypeDHCP,
                                              kIPConfigTypeStatic};
@@ -676,9 +683,9 @@
     } else if (type == ::onc::network_type::kCellular) {
       all_required_exist &=
           RequireField(*result, ::onc::network_config::kCellular);
-    } else if (type == ::onc::network_type::kWimax) {
+    } else if (type == ::onc::network_type::kWimaxDeprecated) {
       all_required_exist &=
-          RequireField(*result, ::onc::network_config::kWimax);
+          RequireField(*result, ::onc::network_config::kWimaxDeprecated);
     } else if (type == ::onc::network_type::kVPN) {
       all_required_exist &= RequireField(*result, ::onc::network_config::kVPN);
     } else if (type == ::onc::network_type::kTether) {
@@ -1006,7 +1013,7 @@
 
   // Ensure the list contains only legitimate network type identifiers.
   const char* const kValidNetworkTypeValues[] = {kCellular, kEthernet, kWiFi,
-                                                 kWimax, kTether};
+                                                 kWimaxDeprecated, kTether};
   const std::vector<const char*> valid_network_type_values(
       toVector(kValidNetworkTypeValues));
   if (!ListFieldContainsValidValues(*result, kDisableNetworkTypes,
diff --git a/chromeos/network/onc/onc_validator_unittest.cc b/chromeos/network/onc/onc_validator_unittest.cc
index 76d03f71..7ac37b1 100644
--- a/chromeos/network/onc/onc_validator_unittest.cc
+++ b/chromeos/network/onc/onc_validator_unittest.cc
@@ -224,9 +224,6 @@
         OncParams("translation_of_shill_cellular_with_state.onc",
                   &kNetworkWithStateSignature,
                   false),
-        OncParams("translation_of_shill_wimax_with_state.onc",
-                  &kNetworkWithStateSignature,
-                  false),
         OncParams("valid_openvpn_with_cert_pems.onc",
                   &kNetworkConfigurationSignature,
                   false),
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc
index 78b5fce8..9c655462 100644
--- a/chromeos/network/shill_property_handler_unittest.cc
+++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -258,7 +258,6 @@
     return (type == shill::kTypeEthernet ||
             type == shill::kTypeEthernetEap ||
             type == shill::kTypeWifi ||
-            type == shill::kTypeWimax ||
             type == shill::kTypeBluetooth ||
             type == shill::kTypeCellular ||
             type == shill::kTypeVPN);
diff --git a/chromeos/network/shill_property_util.h b/chromeos/network/shill_property_util.h
index 6c89cb4..0e41464 100644
--- a/chromeos/network/shill_property_util.h
+++ b/chromeos/network/shill_property_util.h
@@ -62,8 +62,8 @@
 
 // Copy configuration properties required by Shill to identify a network in the
 // format that Shill expects on writes.
-// Only WiFi, VPN, Ethernet and EthernetEAP are supported. Wimax and Cellular
-// are not supported.
+// Only WiFi, VPN, Ethernet and EthernetEAP are supported. Cellular is not
+// supported.
 // If |properties_read_from_shill| is true, it is assumed that
 // |service_properties| has the format that Shill exposes on reads, as opposed
 // to property dictionaries which are sent to Shill. Returns true only if all
@@ -76,8 +76,7 @@
 // |old_properties|, returns true if they are identical. |new_properties| must
 // have the form that Shill expects on writes. |old_properties| must have the
 // form that Shill exposes on reads. See also CopyIdentifyingProperties. Only
-// WiFi, VPN, Ethernet and EthernetEAP are supported. Wimax and Cellular are not
-// supported.
+// WiFi, VPN, Ethernet and EthernetEAP are supported. Cellular is not supported.
 bool DoIdentifyingPropertiesMatch(
     const base::DictionaryValue& new_properties,
     const base::DictionaryValue& old_properties);
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc
index fdecabb..c9e09d3 100644
--- a/chromeos/services/network_config/cros_network_config.cc
+++ b/chromeos/services/network_config/cros_network_config.cc
@@ -46,8 +46,6 @@
     return mojom::NetworkType::kVPN;
   if (type.Equals(NetworkTypePattern::WiFi()))
     return mojom::NetworkType::kWiFi;
-  if (type.Equals(NetworkTypePattern::Wimax()))
-    return mojom::NetworkType::kWiMAX;
   NOTREACHED() << "Unsupported network type: " << type.ToDebugString();
   return mojom::NetworkType::kAll;  // Unsupported
 }
@@ -79,8 +77,6 @@
       return NetworkTypePattern::Wireless();
     case mojom::NetworkType::kWiFi:
       return NetworkTypePattern::WiFi();
-    case mojom::NetworkType::kWiMAX:
-      return NetworkTypePattern::Wimax();
   }
   NOTREACHED();
   return NetworkTypePattern::Default();
@@ -257,12 +253,6 @@
       result->wifi = std::move(wifi);
       break;
     }
-    case mojom::NetworkType::kWiMAX: {
-      auto wimax = mojom::WiMAXStateProperties::New();
-      wimax->signal_strength = network->signal_strength();
-      result->wimax = std::move(wimax);
-      break;
-    }
     case mojom::NetworkType::kAll:
     case mojom::NetworkType::kMobile:
     case mojom::NetworkType::kWireless:
@@ -1220,8 +1210,6 @@
       result->wifi = std::move(wifi);
       break;
     }
-    case mojom::NetworkType::kWiMAX:
-      break;
     case mojom::NetworkType::kAll:
     case mojom::NetworkType::kMobile:
     case mojom::NetworkType::kWireless:
@@ -1237,7 +1225,6 @@
     case mojom::NetworkType::kCellular:
     case mojom::NetworkType::kTether:
     case mojom::NetworkType::kWiFi:
-    case mojom::NetworkType::kWiMAX:
       return true;
     case mojom::NetworkType::kAll:
     case mojom::NetworkType::kEthernet:
diff --git a/chromeos/services/network_config/public/cpp/cros_network_config_util.cc b/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
index e8bcfeb52..d731be0 100644
--- a/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
+++ b/chromeos/services/network_config/public/cpp/cros_network_config_util.cc
@@ -15,19 +15,16 @@
       return true;
     case mojom::NetworkType::kMobile:
       return network_type == mojom::NetworkType::kCellular ||
-             network_type == mojom::NetworkType::kTether ||
-             network_type == mojom::NetworkType::kWiMAX;
+             network_type == mojom::NetworkType::kTether;
     case mojom::NetworkType::kWireless:
       return network_type == mojom::NetworkType::kCellular ||
              network_type == mojom::NetworkType::kTether ||
-             network_type == mojom::NetworkType::kWiFi ||
-             network_type == mojom::NetworkType::kWiMAX;
+             network_type == mojom::NetworkType::kWiFi;
     case mojom::NetworkType::kCellular:
     case mojom::NetworkType::kEthernet:
     case mojom::NetworkType::kTether:
     case mojom::NetworkType::kVPN:
     case mojom::NetworkType::kWiFi:
-    case mojom::NetworkType::kWiMAX:
       return network_type == match_type;
   }
   NOTREACHED();
@@ -65,8 +62,6 @@
       return 0;
     case mojom::NetworkType::kWiFi:
       return network->wifi->signal_strength;
-    case mojom::NetworkType::kWiMAX:
-      return network->wimax->signal_strength;
     case mojom::NetworkType::kAll:
     case mojom::NetworkType::kMobile:
     case mojom::NetworkType::kWireless:
diff --git a/chromeos/services/network_config/public/mojom/cros_network_config.mojom b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
index 30254cc..69497174 100644
--- a/chromeos/services/network_config/public/mojom/cros_network_config.mojom
+++ b/chromeos/services/network_config/public/mojom/cros_network_config.mojom
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // This API is used for configuring network connections (Cellular, Ethernet,
-// VPN, WiFi, WiMAX, or Tether). See the Open Network Configuration
+// VPN, WiFi, or Tether). See the Open Network Configuration
 // (ONC) documentation for detailed descriptions of properties:
 // components/onc/docs/onc_spec.md.
 
@@ -54,14 +54,13 @@
   kAll,
   kCellular,
   kEthernet,
-  // Mobile includes Cellular, Tether, and WiMAX.
+  // Mobile includes Cellular, and Tether.
   kMobile,
   kTether,
   kVPN,
-  // Wireles includes Cellular, Tether, WiFi, and WiMAX.
+  // Wireles includes Cellular, Tether, and WiFi.
   kWireless,
   kWiFi,
-  kWiMAX,
 };
 
 // The ONC source for the network configuration, i.e. whether it is stored in
@@ -203,10 +202,6 @@
   string ssid;
 };
 
-struct WiMAXStateProperties {
-  int32 signal_strength;
-};
-
 struct NetworkStateProperties {
   CaptivePortalProvider? captive_portal_provider;
   CellularStateProperties? cellular;
@@ -235,7 +230,6 @@
   NetworkType type;
   VPNStateProperties? vpn;
   WiFiStateProperties? wifi;
-  WiMAXStateProperties? wimax;
 };
 
 struct DeviceStateProperties {
diff --git a/chromeos/test/data/network/invalid_settings_with_repairs.json b/chromeos/test/data/network/invalid_settings_with_repairs.json
index 7a15ba9..a3c19bfc 100644
--- a/chromeos/test/data/network/invalid_settings_with_repairs.json
+++ b/chromeos/test/data/network/invalid_settings_with_repairs.json
@@ -1,6 +1,6 @@
 {
     "global-disabled-technologies": {
-         "DisableNetworkTypes": ["WiMAX"]
+         "DisableNetworkTypes": ["Cellular"]
     },
     "duplicate-network-guid": {
           "NetworkConfigurations": [
diff --git a/chromeos/test/data/network/managed_toplevel_with_disabled_technologies.onc b/chromeos/test/data/network/managed_toplevel_with_disabled_technologies.onc
index bf2a2b6..ed5a446 100644
--- a/chromeos/test/data/network/managed_toplevel_with_disabled_technologies.onc
+++ b/chromeos/test/data/network/managed_toplevel_with_disabled_technologies.onc
@@ -1,7 +1,7 @@
 {
   "GlobalNetworkConfiguration":{
     "AllowOnlyPolicyNetworksToAutoconnect": true,
-    "DisableNetworkTypes": ["Cellular", "Ethernet", "WiFi", "WiMAX"]
+    "DisableNetworkTypes": ["Cellular", "Ethernet", "WiFi"]
   },
   "NetworkConfigurations":[
     {
diff --git a/chromeos/test/data/network/shill_wimax.json b/chromeos/test/data/network/shill_wimax.json
index b4c950fb..2c63c08 100644
--- a/chromeos/test/data/network/shill_wimax.json
+++ b/chromeos/test/data/network/shill_wimax.json
@@ -1,9 +1,2 @@
 {
-   "AutoConnect": true,
-   "EAP.EAP": "TLS",
-   "EAP.Identity": "${LOGIN_ID}@my.domain.com",
-   "EAP.UseSystemCAs": true,
-   "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
-   "SaveCredentials": true,
-   "Type": "wimax"
 }
diff --git a/chromeos/test/data/network/shill_wimax_with_state.json b/chromeos/test/data/network/shill_wimax_with_state.json
deleted file mode 100644
index 475a2dc..0000000
--- a/chromeos/test/data/network/shill_wimax_with_state.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-   "AutoConnect": true,
-   "Connectable": true,
-   "Name": "SomeWiMAX",
-   "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
-   "Profile": "/profile/someuser",
-   "State": "idle",
-   "Strength": 10,
-   "Type": "wimax"
-}
diff --git a/chromeos/test/data/network/translation_of_shill_wimax_with_state.onc b/chromeos/test/data/network/translation_of_shill_wimax_with_state.onc
deleted file mode 100644
index c8a83f6c..0000000
--- a/chromeos/test/data/network/translation_of_shill_wimax_with_state.onc
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-    "Connectable": true,
-    "ConnectionState": "NotConnected",
-    "GUID": "{77db0089-0bc8-4358-929c-123xcv}",
-    "Type": "WiMAX",
-    "Name": "SomeWiMAX",
-    "WiMAX": {
-        "AutoConnect": true,
-        "SignalStrength": 10
-    },
-    "Source":"User"
-}
diff --git a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
index e652147..e10ace0 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
+++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.cc
@@ -74,9 +74,11 @@
   return false;
 }
 
-bool AutofillWalletDataTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+AutofillWalletDataTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return currently_enabled_;
+  return currently_enabled_ ? PreconditionState::kPreconditionsMet
+                            : PreconditionState::kMustStopAndClearData;
 }
 
 void AutofillWalletDataTypeController::OnUserPrefChanged() {
@@ -87,7 +89,7 @@
     return;  // No change to sync state.
   currently_enabled_ = new_enabled;
 
-  sync_service()->ReadyForStartChanged(type());
+  sync_service()->DataTypePreconditionChanged(type());
 }
 
 bool AutofillWalletDataTypeController::IsEnabled() {
diff --git a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
index 4412d51f..aab8cc2 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
+++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h
@@ -44,7 +44,7 @@
 
   // AsyncDirectoryTypeController implementation.
   bool StartModels() override;
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
  private:
   // Callback for changes to the autofill pref.
diff --git a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
index b6cdd60..1730dc5 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
+++ b/components/autofill/core/browser/payments/autofill_wallet_data_type_controller_unittest.cc
@@ -191,10 +191,12 @@
   EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, last_type_);
 
   EXPECT_CALL(sync_service_,
-              ReadyForStartChanged(syncer::AUTOFILL_WALLET_METADATA));
+              DataTypePreconditionChanged(syncer::AUTOFILL_WALLET_METADATA));
   autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, false);
   autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, true);
-  EXPECT_FALSE(autofill_wallet_dtc_->ReadyForStart());
+  EXPECT_EQ(
+      syncer::DataTypeController::PreconditionState::kMustStopAndClearData,
+      autofill_wallet_dtc_->GetPreconditionState());
   base::RunLoop().RunUntilIdle();
 }
 
@@ -213,10 +215,12 @@
   EXPECT_EQ(syncer::AUTOFILL_WALLET_METADATA, last_type_);
 
   EXPECT_CALL(sync_service_,
-              ReadyForStartChanged(syncer::AUTOFILL_WALLET_METADATA));
+              DataTypePreconditionChanged(syncer::AUTOFILL_WALLET_METADATA));
   autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, true);
   autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, false);
-  EXPECT_FALSE(autofill_wallet_dtc_->ReadyForStart());
+  EXPECT_EQ(
+      syncer::DataTypeController::PreconditionState::kMustStopAndClearData,
+      autofill_wallet_dtc_->GetPreconditionState());
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
index c907e80..787a9e34 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
+++ b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc
@@ -72,22 +72,25 @@
   ModelTypeController::Stop(shutdown_reason, std::move(callback));
 }
 
-bool AutofillWalletModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+AutofillWalletModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
   // Not being in a persistent error state implies not being in a web signout
   // state.
   // TODO(https://crbug.com/819729): Add integration tests for web signout and
   // other persistent auth errors.
-  return pref_service_->GetBoolean(
-             autofill::prefs::kAutofillWalletImportEnabled) &&
-         pref_service_->GetBoolean(
-             autofill::prefs::kAutofillCreditCardEnabled) &&
-         !sync_service_->GetAuthError().IsPersistentError();
+  bool preconditions_met =
+      pref_service_->GetBoolean(
+          autofill::prefs::kAutofillWalletImportEnabled) &&
+      pref_service_->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled) &&
+      !sync_service_->GetAuthError().IsPersistentError();
+  return preconditions_met ? PreconditionState::kPreconditionsMet
+                           : PreconditionState::kMustStopAndClearData;
 }
 
 void AutofillWalletModelTypeController::OnUserPrefChanged() {
   DCHECK(CalledOnValidThread());
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 void AutofillWalletModelTypeController::SubscribeToPrefChanges() {
@@ -105,7 +108,7 @@
 void AutofillWalletModelTypeController::OnStateChanged(
     syncer::SyncService* sync) {
   DCHECK(CalledOnValidThread());
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 }  // namespace browser_sync
diff --git a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
index cee6054e..6cc8adda 100644
--- a/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
+++ b/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h
@@ -43,7 +43,7 @@
   // DataTypeController overrides.
   void Stop(syncer::ShutdownReason shutdown_reason,
             StopCallback callback) override;
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
   // syncer::SyncServiceObserver implementation.
   void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc b/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
index 8385d72..eeda7a58 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
+++ b/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.cc
@@ -20,8 +20,7 @@
     : ModelTypeController(syncer::AUTOFILL_PROFILE,
                           std::move(delegate_on_disk)),
       pref_service_(pref_service),
-      sync_service_(sync_service),
-      currently_enabled_(IsEnabled()) {
+      sync_service_(sync_service) {
   pref_registrar_.Init(pref_service_);
   pref_registrar_.Add(
       autofill::prefs::kAutofillProfileEnabled,
@@ -33,27 +32,18 @@
 AutofillProfileModelTypeController::~AutofillProfileModelTypeController() =
     default;
 
-bool AutofillProfileModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+AutofillProfileModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return currently_enabled_;
+  // Require the user-visible pref to be enabled to sync Autofill Profile data.
+  return autofill::prefs::IsProfileAutofillEnabled(pref_service_)
+             ? PreconditionState::kPreconditionsMet
+             : PreconditionState::kMustStopAndClearData;
 }
 
 void AutofillProfileModelTypeController::OnUserPrefChanged() {
   DCHECK(CalledOnValidThread());
-
-  bool new_enabled = IsEnabled();
-  if (currently_enabled_ == new_enabled)
-    return;
-  currently_enabled_ = new_enabled;
-
-  sync_service_->ReadyForStartChanged(type());
-}
-
-bool AutofillProfileModelTypeController::IsEnabled() {
-  DCHECK(CalledOnValidThread());
-
-  // Require the user-visible pref to be enabled to sync Autofill Profile data.
-  return autofill::prefs::IsProfileAutofillEnabled(pref_service_);
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 }  // namespace browser_sync
diff --git a/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h b/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
index 38aafd7..ed684b9 100644
--- a/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
+++ b/components/autofill/core/browser/webdata/autofill_profile_model_type_controller.h
@@ -30,25 +30,18 @@
   ~AutofillProfileModelTypeController() override;
 
   // DataTypeController overrides.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
  private:
   // Callback for changes to the autofill pref.
   void OnUserPrefChanged();
 
-  // Returns true if the pref is set such that autofill sync should be enabled.
-  bool IsEnabled();
-
   PrefService* const pref_service_;
   syncer::SyncService* const sync_service_;
 
   // Registrar for listening to prefs::kAutofillProfileEnabled.
   PrefChangeRegistrar pref_registrar_;
 
-  // Stores whether we're currently syncing autofill data. This is the last
-  // value computed by IsEnabled.
-  bool currently_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AutofillProfileModelTypeController);
 };
 
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index 8551fec..b5a6fdf9 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -490,6 +490,8 @@
       return "Leak detection finished with result";
     case STRING_LEAK_DETECTION_SIGNED_OUT_ERROR:
       return "Leak detection failed: signed out";
+    case STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR:
+      return "Leak detection failed: can't get a token";
     case SavePasswordProgressLogger::
         STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE:
       return "Uploading password requirements vote for using lowercase letters";
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h
index 46a5f59..c8f80bd 100644
--- a/components/autofill/core/common/save_password_progress_logger.h
+++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -181,6 +181,7 @@
     STRING_SHOW_ONBOARDING,
     STRING_LEAK_DETECTION_FINISHED,
     STRING_LEAK_DETECTION_SIGNED_OUT_ERROR,
+    STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR,
     STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE,
     STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE,
     STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS,
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index 04b9fa3..72a2d52a 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -546,7 +546,6 @@
   if (script_domain_ != url.host()) {
     StopPeriodicScriptChecks();
     script_domain_ = url.host();
-    pending_get_scripts_ = true;
     DVLOG(2) << "GetScripts for " << script_domain_;
     GetService()->GetScriptsForUrl(
         url, *trigger_context_,
@@ -614,7 +613,6 @@
   if (url.host() != script_domain_)
     return;
 
-  pending_get_scripts_ = false;
   if (!result) {
     DVLOG(1) << "Failed to get assistant scripts for " << script_domain_;
     OnFatalError(l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR),
@@ -630,12 +628,6 @@
                  Metrics::DropOutReason::GET_SCRIPTS_UNPARSABLE);
     return;
   }
-  ProcessSupportsScriptResponse(response_proto);
-  GetOrCheckScripts();
-}
-
-void Controller::ProcessSupportsScriptResponse(
-    const SupportsScriptResponseProto& response_proto) {
   if (response_proto.has_client_settings())
     settings_.UpdateFromProto(response_proto.client_settings());
 
@@ -676,47 +668,8 @@
     }
     OnNoRunnableScriptsForPage();
   }
+
   script_tracker()->SetScripts(std::move(scripts));
-}
-
-void Controller::UpdateScriptsFromBundle(
-    const std::string& script_bundle_bytes) {
-  if (script_bundle_bytes.empty())
-    return;
-
-  ScriptBundleProto proto;
-  if (!proto.ParseFromString(script_bundle_bytes)) {
-    DVLOG(3) << __func__ << " Ignored unparseable script bundle";
-    return;
-  }
-
-  // If the bundle isn't meant for the current domain, ignore it.
-  std::string current_domain = GetCurrentURL().host();
-  if (current_domain != proto.domain()) {
-    DVLOG(3) << __func__ << " Ignored script bundle for incorrect domain";
-    return;
-  }
-  ScriptTracker* tracker = script_tracker();
-
-  // Update the set of scripts available for the domain and their preconditions.
-  // Do nothing if the set of scripts is already known.
-  if (script_domain_ == current_domain && !pending_get_scripts_)
-    return;
-
-  script_domain_ = current_domain;
-  ProcessSupportsScriptResponse(proto.supports_scripts());
-
-  // Store initial script actions.
-  for (ScriptActionsProto& actions_proto : *proto.mutable_script_actions()) {
-    auto response_ptr = std::make_unique<ActionsResponseProto>();
-    response_ptr->Swap(actions_proto.mutable_actions());
-    if (!tracker->SetScriptActions(actions_proto.script_path(),
-                                   std::move(response_ptr))) {
-      DVLOG(3) << __func__ << " Ignored actions for unknown script "
-               << actions_proto.script_path();
-    }
-  }
-
   GetOrCheckScripts();
 }
 
@@ -870,12 +823,9 @@
 }
 
 void Controller::Track(std::unique_ptr<TriggerContext> trigger_context,
-                       const std::string& script_bundle_bytes,
                        base::OnceCallback<void()> on_first_check_done) {
   tracking_ = true;
 
-  UpdateScriptsFromBundle(script_bundle_bytes);
-
   if (state_ == AutofillAssistantState::INACTIVE) {
     trigger_context_ = std::move(trigger_context);
     InitFromParameters();
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index e02423c..a6a32bc 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -69,12 +69,7 @@
   //
   // If non-null |on_first_check_done| is called once the result of the first
   // check of script availability are in - whether they're positive or negative.
-  //
-  // If |script_bundle_bytes| is specified, matches the current domain, and no
-  // scripts have been retrieved yet for the current domain, its data will be
-  // used to skip sending RPCs.
   void Track(std::unique_ptr<TriggerContext> trigger_context,
-             const std::string& script_bundle_bytes,
              base::OnceCallback<void()> on_first_check_done);
 
   // Called when autofill assistant should start.
@@ -197,15 +192,6 @@
 
   void OnGetScripts(const GURL& url, bool result, const std::string& response);
 
-  // Updates state from the given |SupportsScriptResponseProto|.
-  void ProcessSupportsScriptResponse(
-      const SupportsScriptResponseProto& response);
-
-  // If possible, updates the set of scripts from the given bundle, which should
-  // by a serialized ScriptBundleProto. The bundle is ignored if it is empty or
-  // refers to another domain than the current one.
-  void UpdateScriptsFromBundle(const std::string& script_bundle_bytes);
-
   // Execute |script_path| and, if execution succeeds, enter |end_state| and
   // call |on_success|.
   void ExecuteScript(const std::string& script_path,
@@ -296,15 +282,8 @@
   GURL deeplink_url_;
 
   // Domain of the last URL the controller requested scripts from.
-  //
-  // As long as |pending_get_scripts_| is true, the set of scripts for that
-  // domain isn't know. Once |pending_get_scripts_| is false, the set of scripts
-  // in the tracker is the one for that domain.
   std::string script_domain_;
 
-  // If true a RPC to fetch the scripts for |script_domain_| is in progress.
-  bool pending_get_scripts_ = false;
-
   // Whether a task for periodic checks is scheduled.
   bool periodic_script_check_scheduled_ = false;
 
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc
index d82afee..fbedd27b 100644
--- a/components/autofill_assistant/browser/controller_unittest.cc
+++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -1011,7 +1011,7 @@
   // Start tracking at example.com, with one script matching
   SetLastCommittedUrl(GURL("http://example.com/"));
 
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
 
@@ -1059,7 +1059,7 @@
   // Start tracking at example.com, with one script matching
   SetLastCommittedUrl(GURL("http://example.com/"));
 
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
 
   EXPECT_TRUE(controller_->PerformUserAction(0));
@@ -1084,7 +1084,7 @@
   // Start tracking at example.com, with one script matching
   SetLastCommittedUrl(GURL("http://example.com/"));
 
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
 
   EXPECT_FALSE(controller_->NeedsUI());
@@ -1115,7 +1115,7 @@
   // Start tracking at example.com, with one script matching
   SetLastCommittedUrl(GURL("http://example.com/"));
 
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
 
   EXPECT_FALSE(controller_->NeedsUI());
@@ -1145,7 +1145,7 @@
   // Start tracking at example.com, with one script matching
   SetLastCommittedUrl(GURL("http://example.com/"));
 
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
 
@@ -1177,7 +1177,7 @@
 
   SetLastCommittedUrl(GURL("http://example.com/"));
   bool first_check_done = false;
-  controller_->Track(TriggerContext::CreateEmpty(), "",
+  controller_->Track(TriggerContext::CreateEmpty(),
                      base::BindOnce(
                          [](Controller* controller, bool* is_done) {
                            // User actions must have been set when this is
@@ -1205,7 +1205,7 @@
   base::MockCallback<base::OnceCallback<void()>> callback;
 
   EXPECT_CALL(callback, Run());
-  controller_->Track(TriggerContext::CreateEmpty(), "", callback.Get());
+  controller_->Track(TriggerContext::CreateEmpty(), callback.Get());
   EXPECT_EQ(AutofillAssistantState::STOPPED, controller_->GetState());
 }
 
@@ -1222,7 +1222,7 @@
   base::MockCallback<base::OnceCallback<void()>> callback;
 
   EXPECT_CALL(callback, Run());
-  controller_->Track(TriggerContext::CreateEmpty(), "", callback.Get());
+  controller_->Track(TriggerContext::CreateEmpty(), callback.Get());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
 }
 
@@ -1240,7 +1240,7 @@
   base::MockCallback<base::OnceCallback<void()>> callback;
 
   EXPECT_CALL(callback, Run());
-  controller_->Track(TriggerContext::CreateEmpty(), "", callback.Get());
+  controller_->Track(TriggerContext::CreateEmpty(), callback.Get());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
 }
 
@@ -1250,12 +1250,12 @@
   SetNextScriptResponse(script_response);
 
   SetLastCommittedUrl(GURL("http://example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
 
   base::MockCallback<base::OnceCallback<void()>> callback;
   EXPECT_CALL(callback, Run());
-  controller_->Track(TriggerContext::CreateEmpty(), "", callback.Get());
+  controller_->Track(TriggerContext::CreateEmpty(), callback.Get());
 }
 
 TEST_F(ControllerTest, TrackThenAutostart) {
@@ -1267,7 +1267,7 @@
   SetNextScriptResponse(script_response);
 
   SetLastCommittedUrl(GURL("http://example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
   EXPECT_THAT(controller_->GetUserActions(), SizeIs(1));
 
@@ -1298,162 +1298,6 @@
                                    AutofillAssistantState::TRACKING));
 }
 
-TEST_F(ControllerTest, TrackWithScriptBundle) {
-  ScriptBundleProto bundle;
-  bundle.set_domain("a.example.com");
-  AddRunnableScript(bundle.mutable_supports_scripts(), "script1");
-  AddRunnableScript(bundle.mutable_supports_scripts(), "script2");
-  auto* script1 = bundle.add_script_actions();
-  script1->set_script_path("script1");
-  script1->mutable_actions()->add_actions()->mutable_tell()->set_message(
-      "script1 was here");
-
-  std::string bundle_str;
-  bundle.SerializeToString(&bundle_str);
-
-  // Get the script list from the bundle.
-  SetLastCommittedUrl(GURL("http://a.example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), bundle_str,
-                     base::DoNothing());
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-
-  // Execute script1 from the bundle, but report its result.
-  ASSERT_THAT(controller_->GetUserActions(), SizeIs(2));
-  ASSERT_EQ("script1", controller_->GetUserActions()[0].chip().text);
-
-  EXPECT_CALL(*mock_service_, OnGetNextActions(_, _, _, _, _))
-      .WillOnce(RunOnceCallback<4>(true, ""));
-
-  EXPECT_TRUE(controller_->PerformUserAction(0));
-
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-  EXPECT_EQ("script1 was here", controller_->GetStatusMessage());
-
-  // Execute script2 from the server response.
-  ActionsResponseProto script2;
-  script2.add_actions()->mutable_tell()->set_message("script2 was here");
-  SetupActionsForScript("script2", script2);
-  EXPECT_CALL(*mock_service_, OnGetNextActions(_, _, _, _, _))
-      .WillOnce(RunOnceCallback<4>(true, ""));
-
-  ASSERT_THAT(controller_->GetUserActions(), SizeIs(2));
-  ASSERT_EQ("script2", controller_->GetUserActions()[1].chip().text);
-  EXPECT_TRUE(controller_->PerformUserAction(1));
-
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-  EXPECT_EQ("script2 was here", controller_->GetStatusMessage());
-}
-
-TEST_F(ControllerTest, TrackWithScriptBundleWrongDomain) {
-  ScriptBundleProto bundle;
-  bundle.set_domain("a.example.com");
-  AddRunnableScript(bundle.mutable_supports_scripts(), "domain a");
-  std::string bundle_str;
-  bundle.SerializeToString(&bundle_str);
-
-  SupportsScriptResponseProto script_response;
-  AddRunnableScript(&script_response, "domain b");
-  SetNextScriptResponse(script_response);
-
-  // Controller is on domain b, so the bundle is ignored and the scripts
-  // retrieved from the server.
-  SetLastCommittedUrl(GURL("http://b.example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), bundle_str,
-                     base::DoNothing());
-
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-  ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
-  EXPECT_EQ("domain b", controller_->GetUserActions()[0].chip().text);
-}
-
-TEST_F(ControllerTest, TrackWithScriptBundleAfterSupportsScripts) {
-  ScriptBundleProto bundle;
-  bundle.set_domain("a.example.com");
-  AddRunnableScript(bundle.mutable_supports_scripts(), "script1");
-  auto* script1 = bundle.add_script_actions();
-  script1->set_script_path("script1");
-  script1->mutable_actions()->add_actions()->mutable_tell()->set_message(
-      "script1 was here");
-
-  std::string bundle_str;
-  bundle.SerializeToString(&bundle_str);
-
-  SupportsScriptResponseProto server_script_response;
-  AddRunnableScript(&server_script_response, "script1");
-  AddRunnableScript(&server_script_response, "script2");
-  SetNextScriptResponse(server_script_response);
-
-  // Get the script list from the server
-  SetLastCommittedUrl(GURL("http://a.example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
-
-  // Provide a bundle
-  controller_->Track(TriggerContext::CreateEmpty(), bundle_str,
-                     base::DoNothing());
-
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-
-  // The response from the RPC won; we have 2 scripts instead of just one.
-  ASSERT_THAT(controller_->GetUserActions(), SizeIs(2));
-
-  // Execute script1 from the server. We can't use script1 actions from the
-  // bundle, since they might not correspond to the preconditions returned by
-  // the server.
-  ASSERT_EQ("script1", controller_->GetUserActions()[0].chip().text);
-
-  EXPECT_CALL(*mock_service_, OnGetActions("script1", _, _, _, _, _));
-  EXPECT_TRUE(controller_->PerformUserAction(0));
-}
-
-TEST_F(ControllerTest, TrackWithScriptBundleDuringSupportsScripts) {
-  // Ask for the the script list from the server. The GetScripts RPC hangs for
-  // now.
-  Service::ResponseCallback get_actions_callback_capture;
-  EXPECT_CALL(*mock_service_, OnGetScriptsForUrl(_, _, _))
-      .WillOnce(
-          Invoke([&get_actions_callback_capture](
-                     const GURL& url, const TriggerContext& trigger_context,
-                     Service::ResponseCallback& callback) {
-            get_actions_callback_capture = std::move(callback);
-          }));
-  SetLastCommittedUrl(GURL("http://a.example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
-
-  // Provide a bundle, which sets the scripts supported for the website.
-  ScriptBundleProto bundle;
-  bundle.set_domain("a.example.com");
-  AddRunnableScript(bundle.mutable_supports_scripts(), "script1");
-  auto* script1 = bundle.add_script_actions();
-  script1->set_script_path("script1");
-  script1->mutable_actions()->add_actions()->mutable_tell()->set_message(
-      "script1 was here");
-  std::string bundle_str;
-  bundle.SerializeToString(&bundle_str);
-  controller_->Track(TriggerContext::CreateEmpty(), bundle_str,
-                     base::DoNothing());
-  EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
-  EXPECT_THAT(controller_->GetUserActions(), SizeIs(1));
-
-  // The server responds, which overrides the scripts supported for the website.
-  // We now have definitions for two scripts.
-  SupportsScriptResponseProto server_script_response;
-  AddRunnableScript(&server_script_response, "script1");
-  AddRunnableScript(&server_script_response, "script2");
-  std::string server_script_response_str;
-  server_script_response.SerializeToString(&server_script_response_str);
-  std::move(get_actions_callback_capture).Run(true, server_script_response_str);
-
-  EXPECT_THAT(controller_->GetUserActions(), SizeIs(2));
-
-  // The initial set of actions for script1 must be fetched from the RPC. The
-  // ones in the bundle must have been discarded when the set of scripts was
-  // updated.
-  ASSERT_EQ("script1", controller_->GetUserActions()[0].chip().text);
-
-  EXPECT_CALL(*mock_service_, OnGetActions("script1", _, _, _, _, _));
-  EXPECT_TRUE(controller_->PerformUserAction(0));
-}
-
 TEST_F(ControllerTest, UnexpectedNavigationDuringPromptAction_Tracking) {
   SupportsScriptResponseProto script_response;
   AddRunnableScript(&script_response, "runnable");
@@ -1470,7 +1314,7 @@
   SetupActionsForScript("runnable", runnable_script);
 
   SetLastCommittedUrl(GURL("http://example.com/"));
-  controller_->Track(TriggerContext::CreateEmpty(), "", base::DoNothing());
+  controller_->Track(TriggerContext::CreateEmpty(), base::DoNothing());
   EXPECT_EQ(AutofillAssistantState::TRACKING, controller_->GetState());
   ASSERT_THAT(controller_->GetUserActions(), SizeIs(1));
   EXPECT_EQ(controller_->GetUserActions()[0].chip().text, "runnable");
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc
index f823e24..8f336e239 100644
--- a/components/autofill_assistant/browser/protocol_utils.cc
+++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -170,8 +170,8 @@
 }
 
 // static
-void ProtocolUtils::ParseActions(ActionDelegate* delegate,
-                                 const ActionsResponseProto& response_proto,
+bool ProtocolUtils::ParseActions(ActionDelegate* delegate,
+                                 const std::string& response,
                                  std::string* return_global_payload,
                                  std::string* return_script_payload,
                                  std::vector<std::unique_ptr<Action>>* actions,
@@ -180,6 +180,12 @@
   DCHECK(actions);
   DCHECK(scripts);
 
+  ActionsResponseProto response_proto;
+  if (!response_proto.ParseFromString(response)) {
+    LOG(ERROR) << "Failed to parse assistant actions response.";
+    return false;
+  }
+
   if (return_global_payload) {
     *return_global_payload = response_proto.global_payload();
   }
@@ -317,6 +323,8 @@
        response_proto.update_script_list().scripts()) {
     ProtocolUtils::AddScript(script_proto, scripts);
   }
+
+  return true;
 }
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/protocol_utils.h b/components/autofill_assistant/browser/protocol_utils.h
index 458e936..14e460d 100644
--- a/components/autofill_assistant/browser/protocol_utils.h
+++ b/components/autofill_assistant/browser/protocol_utils.h
@@ -62,9 +62,9 @@
   // are returned through |scripts| and used to update the list of cached
   // scripts. The bool |should_update_scripts| makes clear the destinction
   // between an empty list of |scripts| or the scripts field not even set in the
-  // proto.
-  static void ParseActions(ActionDelegate* delegate,
-                           const ActionsResponseProto& response,
+  // proto. Return false if parse failed, otherwise return true.
+  static bool ParseActions(ActionDelegate* delegate,
+                           const std::string& response,
                            std::string* return_global_payload,
                            std::string* return_script_payload,
                            std::vector<std::unique_ptr<Action>>* actions,
diff --git a/components/autofill_assistant/browser/protocol_utils_unittest.cc b/components/autofill_assistant/browser/protocol_utils_unittest.cc
index 9ce82836..741be933 100644
--- a/components/autofill_assistant/browser/protocol_utils_unittest.cc
+++ b/components/autofill_assistant/browser/protocol_utils_unittest.cc
@@ -233,6 +233,15 @@
   EXPECT_THAT(scripts, IsEmpty());
 }
 
+TEST(ProtocolUtilsTest, ParseActionsParseError) {
+  bool unused;
+  std::vector<std::unique_ptr<Action>> unused_actions;
+  std::vector<std::unique_ptr<Script>> unused_scripts;
+  EXPECT_FALSE(ProtocolUtils::ParseActions(nullptr, "invalid", nullptr, nullptr,
+                                           &unused_actions, &unused_scripts,
+                                           &unused));
+}
+
 TEST(ProtocolUtilsTest, ParseActionsValid) {
   ActionsResponseProto proto;
   proto.set_global_payload("global_payload");
@@ -240,14 +249,18 @@
   proto.add_actions()->mutable_tell();
   proto.add_actions()->mutable_click();
 
+  std::string proto_str;
+  proto.SerializeToString(&proto_str);
+
   std::string global_payload;
   std::string script_payload;
   bool should_update_scripts = true;
   std::vector<std::unique_ptr<Action>> actions;
   std::vector<std::unique_ptr<Script>> scripts;
 
-  ProtocolUtils::ParseActions(nullptr, proto, &global_payload, &script_payload,
-                              &actions, &scripts, &should_update_scripts);
+  EXPECT_TRUE(ProtocolUtils::ParseActions(nullptr, proto_str, &global_payload,
+                                          &script_payload, &actions, &scripts,
+                                          &should_update_scripts));
   EXPECT_EQ("global_payload", global_payload);
   EXPECT_EQ("script_payload", script_payload);
   EXPECT_THAT(actions, SizeIs(2));
@@ -259,13 +272,17 @@
   ActionsResponseProto proto;
   proto.mutable_update_script_list();
 
+  std::string proto_str;
+  proto.SerializeToString(&proto_str);
+
   bool should_update_scripts = false;
   std::vector<std::unique_ptr<Script>> scripts;
   std::vector<std::unique_ptr<Action>> unused_actions;
 
-  ProtocolUtils::ParseActions(nullptr, proto, /* global_payload= */ nullptr,
-                              /* script_payload */ nullptr, &unused_actions,
-                              &scripts, &should_update_scripts);
+  EXPECT_TRUE(ProtocolUtils::ParseActions(
+      nullptr, proto_str, /* global_payload= */ nullptr,
+      /* script_payload */ nullptr, &unused_actions, &scripts,
+      &should_update_scripts));
   EXPECT_TRUE(should_update_scripts);
   EXPECT_TRUE(scripts.empty());
 }
@@ -281,13 +298,17 @@
   // One invalid script.
   script_list->add_scripts();
 
+  std::string proto_str;
+  proto.SerializeToString(&proto_str);
+
   bool should_update_scripts = false;
   std::vector<std::unique_ptr<Script>> scripts;
   std::vector<std::unique_ptr<Action>> unused_actions;
 
-  ProtocolUtils::ParseActions(nullptr, proto, /* global_payload= */ nullptr,
-                              /* script_payload= */ nullptr, &unused_actions,
-                              &scripts, &should_update_scripts);
+  EXPECT_TRUE(ProtocolUtils::ParseActions(
+      nullptr, proto_str, /* global_payload= */ nullptr,
+      /* script_payload= */ nullptr, &unused_actions, &scripts,
+      &should_update_scripts));
   EXPECT_TRUE(should_update_scripts);
   EXPECT_THAT(scripts, SizeIs(1));
   EXPECT_THAT("a", Eq(scripts[0]->handle.path));
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index f60eafd..dd6bed7 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -99,12 +99,6 @@
   callback_ = std::move(callback);
   DCHECK(delegate_->GetService());
 
-  if (initial_actions_) {
-    OnGetActionsProto(true, *initial_actions_);
-    initial_actions_.reset();
-    return;
-  }
-
   DVLOG(2) << "GetActions for " << delegate_->GetCurrentURL().host();
   delegate_->GetService()->GetActions(
       script_path_, delegate_->GetDeeplinkURL(),
@@ -547,19 +541,10 @@
 }
 
 void ScriptExecutor::OnGetActions(bool result, const std::string& response) {
-  ActionsResponseProto response_proto;
-  if (result && !response_proto.ParseFromString(response)) {
-    DVLOG(1) << "Failed to parse assistant actions response.";
-    result = false;
-  }
-  OnGetActionsProto(result, response_proto);
-}
-
-void ScriptExecutor::OnGetActionsProto(bool success,
-                                       const ActionsResponseProto& response) {
-  DVLOG(2) << __func__ << " success=" << success;
+  bool success = result && ProcessNextActionResponse(response);
+  DVLOG(2) << __func__ << " result=" << result;
   if (should_stop_script_) {
-    // The last action forced the script to stop. Sending the success of the
+    // The last action forced the script to stop. Sending the result of the
     // action is considered best effort in this situation. Report a successful
     // run to the caller no matter what, so we don't confuse users with an error
     // message.
@@ -572,7 +557,6 @@
     return;
   }
 
-  ProcessNextActionResponse(response);
   if (!actions_.empty()) {
     ProcessNextAction();
     return;
@@ -581,22 +565,24 @@
   RunCallback(true);
 }
 
-void ScriptExecutor::ProcessNextActionResponse(
-    const ActionsResponseProto& response) {
+bool ScriptExecutor::ProcessNextActionResponse(const std::string& response) {
   processed_actions_.clear();
   actions_.clear();
-  inhibit_result_report_ = response.inhibit_result_report();
 
   bool should_update_scripts = false;
   std::vector<std::unique_ptr<Script>> scripts;
-  ProtocolUtils::ParseActions(this, response, &last_global_payload_,
-                              &last_script_payload_, &actions_, &scripts,
-                              &should_update_scripts);
+  bool parse_result = ProtocolUtils::ParseActions(
+      this, response, &last_global_payload_, &last_script_payload_, &actions_,
+      &scripts, &should_update_scripts);
+  if (!parse_result) {
+    return false;
+  }
 
   ReportPayloadsToListener();
   if (should_update_scripts) {
     ReportScriptsUpdateToListener(std::move(scripts));
   }
+  return true;
 }
 
 void ScriptExecutor::ReportPayloadsToListener() {
@@ -642,7 +628,7 @@
   if (actions_.size() <= processed_actions_.size()) {
     DCHECK_EQ(actions_.size(), processed_actions_.size());
     DVLOG(2) << __func__ << ", get more actions";
-    GetNextActions(true);
+    GetNextActions();
     return;
   }
 
@@ -672,11 +658,7 @@
                                        base::TimeTicks::Now()));
 }
 
-void ScriptExecutor::GetNextActions(bool success) {
-  if (inhibit_result_report_) {
-    RunCallback(success);
-    return;
-  }
+void ScriptExecutor::GetNextActions() {
   delegate_->GetService()->GetNextActions(
       MergedTriggerContext(
           {delegate_->GetTriggerContext(), additional_context_.get()}),
@@ -708,7 +690,7 @@
     DVLOG(1) << "Action failed: " << processed_action.status()
              << ", get more actions";
     // Report error immediately, interrupting action processing.
-    GetNextActions(false);
+    GetNextActions();
     return;
   }
   ProcessNextAction();
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index caaed0f..1d99ec4 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -93,12 +93,6 @@
     friend std::ostream& operator<<(std::ostream& out, const Result& result);
   };
 
-  // Optionally provides the initial set of actions to execute. If unset, the
-  // script executor fetches the actions from the service.
-  void SetActions(std::unique_ptr<ActionsResponseProto> initial_actions) {
-    initial_actions_ = std::move(initial_actions);
-  }
-
   using RunScriptCallback = base::OnceCallback<void(const Result&)>;
   void Run(RunScriptCallback callback);
 
@@ -313,8 +307,7 @@
   };
 
   void OnGetActions(bool result, const std::string& response);
-  void OnGetActionsProto(bool result, const ActionsResponseProto& response);
-  void ProcessNextActionResponse(const ActionsResponseProto& response);
+  bool ProcessNextActionResponse(const std::string& response);
   void ReportPayloadsToListener();
   void ReportScriptsUpdateToListener(
       std::vector<std::unique_ptr<Script>> scripts);
@@ -322,7 +315,7 @@
   void RunCallbackWithResult(const Result& result);
   void ProcessNextAction();
   void ProcessAction(Action* action);
-  void GetNextActions(bool success);
+  void GetNextActions();
   void OnProcessedAction(base::TimeTicks start_time,
                          std::unique_ptr<ProcessedActionProto> action);
   void CheckElementMatches(const Selector& selector,
@@ -409,13 +402,6 @@
   };
   CurrentActionData current_action_data_;
 
-  // If set, get the initial set of actions from this proto instead of querying
-  // them from the backend.
-  std::unique_ptr<ActionsResponseProto> initial_actions_;
-
-  // If true, don't report the result to the caller.
-  bool inhibit_result_report_ = false;
-
   base::WeakPtrFactory<ScriptExecutor> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(ScriptExecutor);
 };
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 883c28b..1a791ae 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -1369,37 +1369,6 @@
   EXPECT_EQ(NAVIGATION_ERROR, processed_actions_capture[1].status());
 }
 
-TEST_F(ScriptExecutorTest, InhibitResultReportSuccessfulAction) {
-  ActionsResponseProto actions_response;
-  actions_response.add_actions()->mutable_tell()->set_message("will suceed");
-  actions_response.set_inhibit_result_report(true);
-
-  EXPECT_CALL(mock_service_, OnGetActions(_, _, _, _, _, _))
-      .WillOnce(RunOnceCallback<5>(true, Serialize(actions_response)));
-
-  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _)).Times(0);
-  EXPECT_CALL(executor_callback_,
-              Run(Field(&ScriptExecutor::Result::success, true)));
-  executor_->Run(executor_callback_.Get());
-}
-
-TEST_F(ScriptExecutorTest, InhibitResultReportFailedAction) {
-  ActionsResponseProto actions_response;
-  actions_response.add_actions()
-      ->mutable_click()
-      ->mutable_element_to_click()
-      ->add_selectors("will fail");
-  actions_response.set_inhibit_result_report(true);
-
-  EXPECT_CALL(mock_service_, OnGetActions(_, _, _, _, _, _))
-      .WillOnce(RunOnceCallback<5>(true, Serialize(actions_response)));
-
-  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _)).Times(0);
-  EXPECT_CALL(executor_callback_,
-              Run(Field(&ScriptExecutor::Result::success, false)));
-  executor_->Run(executor_callback_.Get());
-}
-
 TEST_F(ScriptExecutorTest, InterceptUserActions) {
   ActionsResponseProto actions_response;
   actions_response.add_actions()
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc
index 14c8357..2bfc8423 100644
--- a/components/autofill_assistant/browser/script_tracker.cc
+++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -77,23 +77,6 @@
     }
   }
   SortScripts(&interrupts_);
-
-  // If there were script actions defined, clear them. If we have a new set of
-  // script definition, scripts with the same path might now have different
-  // precondition, so we can't keep them.
-  script_actions_.clear();
-}
-
-bool ScriptTracker::SetScriptActions(
-    const std::string& script_path,
-    std::unique_ptr<ActionsResponseProto> actions) {
-  for (auto& script_pair : available_scripts_) {
-    if (script_pair.first->handle.path == script_path) {
-      script_actions_.emplace(std::make_pair(script_path, std::move(actions)));
-      return true;
-    }
-  }
-  return false;
 }
 
 void ScriptTracker::CheckScripts() {
@@ -148,18 +131,6 @@
       script_path, std::move(context), last_global_payload_,
       last_script_payload_,
       /* listener= */ this, &scripts_state_, &interrupts_, delegate_);
-
-  // Set the initial set of actions, the first time a script is run.
-  auto actions_iter = script_actions_.find(script_path);
-  if (actions_iter != script_actions_.end()) {
-    // TODO(b/138278201): Consider keeping the set of actions for another run of
-    // the script. This means not transferring ownership, but also guaranteeing
-    // that the content of script_actions_ doesn't change while a script is
-    // running.
-    executor_->SetActions(std::move(actions_iter->second));
-    script_actions_.erase(actions_iter);
-  }
-
   ScriptExecutor::RunScriptCallback run_script_callback = base::BindOnce(
       &ScriptTracker::OnScriptRun, weak_ptr_factory_.GetWeakPtr(), script_path,
       std::move(callback));
diff --git a/components/autofill_assistant/browser/script_tracker.h b/components/autofill_assistant/browser/script_tracker.h
index 77696f8f..373540b 100644
--- a/components/autofill_assistant/browser/script_tracker.h
+++ b/components/autofill_assistant/browser/script_tracker.h
@@ -97,16 +97,6 @@
   // script running at a time.
   bool running() const { return executor_ != nullptr; }
 
-  // Sets a hardcoded set of initial actions for the given script.
-  //
-  // Actions specified here are only valid for the current set of scripts, set
-  // with SetScripts(). Calling SetScripts() clears them.
-  //
-  // If this returns false, the script actions was ignored, as there's was no
-  // definitions passed in the last call to SetScripts().
-  bool SetScriptActions(const std::string& script_path,
-                        std::unique_ptr<ActionsResponseProto> actions);
-
   // Returns a dictionary describing the current execution context, which
   // is intended to be serialized as JSON string. The execution context is
   // useful when analyzing feedback forms and for debugging in general.
@@ -186,9 +176,6 @@
   // only occurse when |scripts_update| is not nullptr.
   std::unique_ptr<std::vector<std::unique_ptr<Script>>> scripts_update_;
 
-  // Known initial script actions, passed to the tracker.
-  std::map<std::string, std::unique_ptr<ActionsResponseProto>> script_actions_;
-
   base::WeakPtrFactory<ScriptTracker> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ScriptTracker);
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index aaf192a..02a02666 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -362,10 +362,6 @@
   // Should stop processing as soon as an action fails.
   repeated ActionProto actions = 3;
 
-  // If true, don't report the result to the server. Setting this to false
-  // implies that the given set of actions is complete.
-  optional bool inhibit_result_report = 6;
-
   // List of scripts to update.
   //
   // The client is expected to update the cache of scripts with this new
@@ -1630,25 +1626,3 @@
   // Message to show in the popup.
   optional string message = 1;
 }
-
-// A set of script definition that can be provided by the caller, when using
-// direct actions, to avoid having to send RPCs to get the data.
-//
-// These definitions are only valid for the given domain. They'll be ignored if
-// data has already been retrieved from the server.
-message ScriptBundleProto {
-  // The domain to which SupportsScriptResponseProto applies. This avoids
-  // having to send the SupportsScript RPC.
-  optional string domain = 1;
-  optional SupportsScriptResponseProto supports_scripts = 2;
-
-  // Optional definition for scripts defined in supports_scripts. This avoids
-  // having to send the GetActions RPC to get the initial set of actions.
-  repeated ScriptActionsProto script_actions = 3;
-}
-
-// Definition of an action.
-message ScriptActionsProto {
-  optional string script_path = 1;
-  optional ActionsResponseProto actions = 2;
-}
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
index 46380ee7..f65ba64 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
@@ -98,14 +98,16 @@
             return GcmNetworkManager.RESULT_FAILURE;
         }
 
+        final TaskParameters taskParams =
+                BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
+
         Long deadlineTime =
                 BackgroundTaskSchedulerGcmNetworkManager.getDeadlineTimeFromTaskParams(params);
         if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+            BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(taskParams.getTaskId());
             return GcmNetworkManager.RESULT_FAILURE;
         }
 
-        final TaskParameters taskParams =
-                BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
         final Waiter waiter = new Waiter(Waiter.MAX_TIMEOUT_SECONDS);
 
         final AtomicBoolean taskNeedsBackgroundProcessing = new AtomicBoolean();
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
index f54aa98..1cf0dce 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
@@ -84,6 +84,7 @@
         Long deadlineTime =
                 BackgroundTaskSchedulerJobService.getDeadlineTimeFromJobParameters(params);
         if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+            BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(params.getJobId());
             return false;
         }
 
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
index 853180b..f1a64d5 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImpl.java
@@ -45,6 +45,10 @@
             boolean success = mSchedulerDelegate.schedule(context, taskInfo);
             BackgroundTaskSchedulerUma.getInstance().reportTaskScheduled(
                     taskInfo.getTaskId(), success);
+            if (!taskInfo.isPeriodic()) {
+                BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+                        taskInfo.getTaskId(), taskInfo.getOneOffInfo().expiresAfterWindowEndTime());
+            }
             if (success) {
                 BackgroundTaskSchedulerPrefs.addScheduledTask(taskInfo);
             }
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index 11024d9..955bad8 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -139,6 +139,22 @@
         }
     }
 
+    /** Reports metrics for task scheduling with the expiration feature activated. */
+    public void reportTaskCreatedAndExpirationState(int taskId, boolean expires) {
+        if (expires) {
+            cacheEvent("Android.BackgroundTaskScheduler.TaskCreated.WithExpiration",
+                    toUmaEnumValueFromTaskId(taskId));
+        } else {
+            cacheEvent("Android.BackgroundTaskScheduler.TaskCreated.WithoutExpiration",
+                    toUmaEnumValueFromTaskId(taskId));
+        }
+    }
+
+    /** Reports metrics for not starting a task because of expiration. */
+    public void reportTaskExpired(int taskId) {
+        cacheEvent("Android.BackgroundTaskScheduler.TaskExpired", toUmaEnumValueFromTaskId(taskId));
+    }
+
     /** Reports metrics for task canceling. */
     public void reportTaskCanceled(int taskId) {
         cacheEvent(
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
index fb9ed42..5126237 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskInfo.java
@@ -68,9 +68,14 @@
 
         @Override
         public String toString() {
-            return "{windowStartTimeMs: " + mWindowStartTimeMs
-                    + ", windowEndTimeMs: " + mWindowEndTimeMs
-                    + "} - expires at window_end_time: " + mExpiresAfterWindowEndTime;
+            StringBuilder sb = new StringBuilder("{");
+            if (hasWindowStartTimeConstraint()) {
+                sb.append("windowStartTimeMs: ").append(mWindowStartTimeMs).append(", ");
+            }
+            sb.append("windowEndTimeMs: ").append(mWindowEndTimeMs).append(", ");
+            sb.append("expiresAfterWindowEndTime (+flex): ").append(mExpiresAfterWindowEndTime);
+            sb.append("}");
+            return sb.toString();
         }
     }
 
@@ -82,11 +87,14 @@
         private final long mIntervalMs;
         private final long mFlexMs;
         private final boolean mHasFlex;
+        private final boolean mExpiresAfterWindowEndTime;
 
-        private PeriodicInfo(long intervalMs, long flexMs, boolean hasFlex) {
+        private PeriodicInfo(
+                long intervalMs, long flexMs, boolean hasFlex, boolean expiresAfterWindowEndTime) {
             mIntervalMs = intervalMs;
             mFlexMs = flexMs;
             mHasFlex = hasFlex;
+            mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
         }
 
         /**
@@ -111,14 +119,23 @@
             return mHasFlex;
         }
 
+        /**
+         * @return whether this periodic task expires after {@link #getIntervalMs()} +
+         * {@link #getFlexMs()}
+         * False by default.
+         */
+        public boolean expiresAfterWindowEndTime() {
+            return mExpiresAfterWindowEndTime;
+        }
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder("{");
-            sb.append("{");
-            sb.append("intervalMs: ").append(mIntervalMs);
+            sb.append("intervalMs: ").append(mIntervalMs).append(", ");
             if (mHasFlex) {
-                sb.append(", flexMs: ").append(mFlexMs);
+                sb.append(", flexMs: ").append(mFlexMs).append(", ");
             }
+            sb.append("expiresAfterWindowEndTime (+flex): ").append(mExpiresAfterWindowEndTime);
             sb.append("}");
             return sb.toString();
         }
@@ -212,8 +229,8 @@
         mIsPeriodic = builder.mIsPeriodic;
         if (mIsPeriodic) {
             mOneOffInfo = null;
-            mPeriodicInfo =
-                    new PeriodicInfo(builder.mIntervalMs, builder.mFlexMs, builder.mHasFlex);
+            mPeriodicInfo = new PeriodicInfo(builder.mIntervalMs, builder.mFlexMs, builder.mHasFlex,
+                    builder.mExpiresAfterWindowEndTime);
         } else {
             mOneOffInfo = new OneOffInfo(builder.mWindowStartTimeMs, builder.mWindowEndTimeMs,
                     builder.mHasWindowStartTimeConstraint, builder.mExpiresAfterWindowEndTime);
@@ -465,8 +482,7 @@
          * @param expiresAfterWindowEndTime whether the task expires or not.
          * @return this {@link Builder}.
          */
-        Builder setExpiresAfterWindowEndTime(boolean expiresAfterWindowEndTime) {
-            assert !mIsPeriodic;
+        public Builder setExpiresAfterWindowEndTime(boolean expiresAfterWindowEndTime) {
             mExpiresAfterWindowEndTime = expiresAfterWindowEndTime;
             return this;
         }
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
index 1d1e43a..91864639 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java
@@ -49,6 +49,7 @@
     private ShadowGcmNetworkManager mGcmNetworkManager;
 
     private TaskInfo mTask;
+    private TaskInfo mExpirationTask;
 
     @Before
     public void setUp() {
@@ -67,6 +68,10 @@
         mTask = TaskInfo.createOneOffTask(
                                 TaskIds.TEST, TestBackgroundTask.class, TimeUnit.DAYS.toMillis(1))
                         .build();
+        mExpirationTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                          TimeUnit.DAYS.toMillis(1))
+                                  .setExpiresAfterWindowEndTime(true)
+                                  .build();
     }
 
     @Test
@@ -80,6 +85,19 @@
         verify(mDelegate, times(1)).schedule(eq(RuntimeEnvironment.application), eq(mTask));
         verify(mBackgroundTaskSchedulerUma, times(1))
                 .reportTaskScheduled(eq(TaskIds.TEST), eq(true));
+        verify(mBackgroundTaskSchedulerUma, times(1))
+                .reportTaskCreatedAndExpirationState(eq(TaskIds.TEST), eq(false));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testScheduleTaskWithExpirationSuccessful() {
+        doReturn(true).when(mDelegate).schedule(
+                eq(RuntimeEnvironment.application), eq(mExpirationTask));
+        BackgroundTaskSchedulerFactory.getScheduler().schedule(
+                RuntimeEnvironment.application, mExpirationTask);
+        verify(mBackgroundTaskSchedulerUma, times(1))
+                .reportTaskCreatedAndExpirationState(eq(TaskIds.TEST), eq(true));
     }
 
     @Test
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
index 479decf..e704810 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -194,6 +194,38 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
+    public void testReportTaskScheduledWithExpiration() {
+        doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+        BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+                TaskIds.TEST, /* expires= */ true);
+        verify(mUmaSpy, times(1))
+                .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskCreated.WithExpiration"),
+                        eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testReportTaskScheduledWithoutExpiration() {
+        doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+        BackgroundTaskSchedulerUma.getInstance().reportTaskCreatedAndExpirationState(
+                TaskIds.TEST, /* expires= */ false);
+        verify(mUmaSpy, times(1))
+                .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskCreated.WithoutExpiration"),
+                        eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testReportTaskExpired() {
+        doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
+        BackgroundTaskSchedulerUma.getInstance().reportTaskExpired(TaskIds.TEST);
+        verify(mUmaSpy, times(1))
+                .cacheEvent(eq("Android.BackgroundTaskScheduler.TaskExpired"),
+                        eq(BackgroundTaskSchedulerUma.BACKGROUND_TASK_TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
     public void testReportTaskCanceled() {
         doNothing().when(mUmaSpy).cacheEvent(anyString(), anyInt());
         BackgroundTaskSchedulerUma.getInstance().reportTaskCanceled(
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
index c6aea9c..7bb71a4 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/TaskInfoTest.java
@@ -16,12 +16,15 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 
+import java.util.concurrent.TimeUnit;
+
 /** Unit tests for {@link TaskInfo}. */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class TaskInfoTest {
-    private static final int TEST_START_MS = 300000;
-    private static final int TEST_END_MS = 600000;
+    private static final long TEST_START_MS = TimeUnit.MINUTES.toMillis(5);
+    private static final long TEST_END_MS = TimeUnit.MINUTES.toMillis((10));
+    private static final long TEST_FLEX_MS = 100;
 
     @Before
     public void setUp() {
@@ -36,7 +39,7 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testExpirationWithinDeadline() {
+    public void testOneOffExpirationWithinDeadline() {
         TaskInfo oneOffTask =
                 TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TEST_END_MS)
                         .setExpiresAfterWindowEndTime(true)
@@ -53,37 +56,59 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testExpirationWithinTimeWindow() {
+    public void testOneOffExpirationWithinTimeWindow() {
         TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
                                               TEST_START_MS, TEST_END_MS)
                                       .setExpiresAfterWindowEndTime(true)
                                       .build();
 
-        checkGeneralTaskInfoFields(oneOffTask, TaskIds.TEST, TestBackgroundTask.class);
-
         assertTrue(oneOffTask.getOneOffInfo().hasWindowStartTimeConstraint());
         assertEquals(TEST_START_MS, oneOffTask.getOneOffInfo().getWindowStartTimeMs());
         assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowEndTimeMs());
         assertTrue(oneOffTask.getOneOffInfo().expiresAfterWindowEndTime());
-
-        assertEquals(null, oneOffTask.getPeriodicInfo());
     }
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testExpirationWithinZeroTimeWindow() {
+    public void testOneOffExpirationWithinZeroTimeWindow() {
         TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
                                               TEST_END_MS, TEST_END_MS)
                                       .setExpiresAfterWindowEndTime(true)
                                       .build();
 
-        checkGeneralTaskInfoFields(oneOffTask, TaskIds.TEST, TestBackgroundTask.class);
-
-        assertTrue(oneOffTask.getOneOffInfo().hasWindowStartTimeConstraint());
         assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowStartTimeMs());
         assertEquals(TEST_END_MS, oneOffTask.getOneOffInfo().getWindowEndTimeMs());
         assertTrue(oneOffTask.getOneOffInfo().expiresAfterWindowEndTime());
+    }
 
-        assertEquals(null, oneOffTask.getPeriodicInfo());
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testPeriodicExpirationWithInterval() {
+        TaskInfo periodicTask =
+                TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class, TEST_END_MS)
+                        .setExpiresAfterWindowEndTime(true)
+                        .build();
+
+        checkGeneralTaskInfoFields(periodicTask, TaskIds.TEST, TestBackgroundTask.class);
+
+        assertFalse(periodicTask.getPeriodicInfo().hasFlex());
+        assertEquals(TEST_END_MS, periodicTask.getPeriodicInfo().getIntervalMs());
+        assertTrue(periodicTask.getPeriodicInfo().expiresAfterWindowEndTime());
+
+        assertEquals(null, periodicTask.getOneOffInfo());
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testPeriodicExpirationWithIntervalAndFlex() {
+        TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                TEST_END_MS, TEST_FLEX_MS)
+                                        .setExpiresAfterWindowEndTime(true)
+                                        .build();
+
+        assertTrue(periodicTask.getPeriodicInfo().hasFlex());
+        assertEquals(TEST_FLEX_MS, periodicTask.getPeriodicInfo().getFlexMs());
+        assertEquals(TEST_END_MS, periodicTask.getPeriodicInfo().getIntervalMs());
+        assertTrue(periodicTask.getPeriodicInfo().expiresAfterWindowEndTime());
     }
 }
\ No newline at end of file
diff --git a/components/browser_sync/browser_sync_switches.cc b/components/browser_sync/browser_sync_switches.cc
index aab5aff..c1aa1b8 100644
--- a/components/browser_sync/browser_sync_switches.cc
+++ b/components/browser_sync/browser_sync_switches.cc
@@ -21,4 +21,9 @@
 // flag is present.
 const char kLocalSyncBackendDir[] = "local-sync-backend-dir";
 
+#if defined(OS_ANDROID)
+const base::Feature kSyncManualStartAndroid{"SyncManualStartAndroid",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
 }  // namespace switches
diff --git a/components/browser_sync/browser_sync_switches.h b/components/browser_sync/browser_sync_switches.h
index 1163cb7d..f1e69690 100644
--- a/components/browser_sync/browser_sync_switches.h
+++ b/components/browser_sync/browser_sync_switches.h
@@ -5,12 +5,19 @@
 #ifndef COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
 #define COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
 
+#include "base/feature_list.h"
+#include "build/build_config.h"
+
 namespace switches {
 
 extern const char kDisableSyncTypes[];
 extern const char kEnableLocalSyncBackend[];
 extern const char kLocalSyncBackendDir[];
 
+#if defined(OS_ANDROID)
+extern const base::Feature kSyncManualStartAndroid;
+#endif
+
 }  // namespace switches
 
 #endif  // COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
diff --git a/components/chromeos_camera/OWNERS b/components/chromeos_camera/OWNERS
index f92472c6..63bd952 100644
--- a/components/chromeos_camera/OWNERS
+++ b/components/chromeos_camera/OWNERS
@@ -1,5 +1,4 @@
 jcliang@chromium.org
-shenghao@chromium.org
 shik@chromium.org
 wtlee@chromium.org
 
@@ -8,4 +7,4 @@
 mcasas@chromium.org
 
 # TEAM: chromeos-camera@chromium.org
-# COMPONENT: OS>Kernel>Camera
\ No newline at end of file
+# COMPONENT: OS>Kernel>Camera
diff --git a/components/cronet/native/cronet.idl b/components/cronet/native/cronet.idl
index b28c782c..ec142ebd 100644
--- a/components/cronet/native/cronet.idl
+++ b/components/cronet/native/cronet.idl
@@ -364,7 +364,7 @@
 
   /**
    * Shuts down the Engine if there are no active requests,
-   * otherwise throws an exception.
+   * otherwise returns a failure RESULT.
    *
    * Cannot be called on network thread - the thread Cronet calls into
    * Executor on (which is different from the thread the Executor invokes
@@ -997,9 +997,7 @@
    * UploadDataSink.onRewindError() on failure. Neither read nor rewind
    * will be called until one of those methods or the other is called.
    * Even if the associated UrlRequest is canceled, one or the other
-   * must still be called before resources can be safely freed. Throwing an
-   * exception will also result in resources being freed and the request being
-   * errored out.
+   * must still be called before resources can be safely freed.
    *
    * If rewinding is not supported, this should call
    * UploadDataSink.onRewindError(). Note that rewinding is required to
@@ -1028,7 +1026,7 @@
    * Initialized UrlRequest to |url| with |params|. All methods of |callback| for
    * request will be invoked on |executor|. The |executor| must not run tasks on
    * the thread calling Executor.execute() to prevent blocking networking
-   * operations and causing exceptions during shutdown.
+   * operations and causing failure RESULTs during shutdown.
    *
    * @param engine Engine to process the request.
    * @param url URL for the request.
diff --git a/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc b/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
index 8955d0f..eed2218 100644
--- a/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
+++ b/components/history/core/browser/sync/history_delete_directives_model_type_controller.cc
@@ -31,9 +31,12 @@
 HistoryDeleteDirectivesModelTypeController::
     ~HistoryDeleteDirectivesModelTypeController() {}
 
-bool HistoryDeleteDirectivesModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+HistoryDeleteDirectivesModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return !sync_service_->GetUserSettings()->IsEncryptEverythingEnabled();
+  return sync_service_->GetUserSettings()->IsEncryptEverythingEnabled()
+             ? PreconditionState::kMustStopAndClearData
+             : PreconditionState::kPreconditionsMet;
 }
 
 void HistoryDeleteDirectivesModelTypeController::LoadModels(
@@ -62,7 +65,7 @@
     syncer::SyncService* sync) {
   DCHECK(CalledOnValidThread());
   // Most of these calls will be no-ops but SyncService handles that just fine.
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 }  // namespace browser_sync
diff --git a/components/history/core/browser/sync/history_delete_directives_model_type_controller.h b/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
index 93cb9d3..8141c718 100644
--- a/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
+++ b/components/history/core/browser/sync/history_delete_directives_model_type_controller.h
@@ -34,7 +34,7 @@
   ~HistoryDeleteDirectivesModelTypeController() override;
 
   // DataTypeController overrides.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
   void LoadModels(const syncer::ConfigureContext& configure_context,
                   const ModelLoadCallback& model_load_callback) override;
   void Stop(syncer::ShutdownReason shutdown_reason,
diff --git a/components/history/core/browser/sync/typed_url_model_type_controller.cc b/components/history/core/browser/sync/typed_url_model_type_controller.cc
index 2b1dc8b..33104ea 100644
--- a/components/history/core/browser/sync/typed_url_model_type_controller.cc
+++ b/components/history/core/browser/sync/typed_url_model_type_controller.cc
@@ -47,9 +47,12 @@
 
 TypedURLModelTypeController::~TypedURLModelTypeController() {}
 
-bool TypedURLModelTypeController::ReadyForStart() const {
-  return history_service_ &&
-         !pref_service_->GetBoolean(history_disabled_pref_name_);
+syncer::DataTypeController::PreconditionState
+TypedURLModelTypeController::GetPreconditionState() const {
+  return (history_service_ &&
+          !pref_service_->GetBoolean(history_disabled_pref_name_))
+             ? PreconditionState::kPreconditionsMet
+             : PreconditionState::kMustStopAndClearData;
 }
 
 void TypedURLModelTypeController::OnSavingBrowserHistoryDisabledChanged() {
@@ -57,6 +60,7 @@
     // We've turned off history persistence, so if we are running,
     // generate an unrecoverable error. This can be fixed by restarting
     // Chrome (on restart, typed urls will not be a registered type).
+    // TODO(crbug.com/990802): Adopt DataTypePreconditionChanged().
     if (state() != NOT_RUNNING && state() != STOPPING) {
       ReportModelError(
           syncer::SyncError::DATATYPE_POLICY_ERROR,
diff --git a/components/history/core/browser/sync/typed_url_model_type_controller.h b/components/history/core/browser/sync/typed_url_model_type_controller.h
index 51280ad..07187cc 100644
--- a/components/history/core/browser/sync/typed_url_model_type_controller.h
+++ b/components/history/core/browser/sync/typed_url_model_type_controller.h
@@ -22,7 +22,7 @@
   ~TypedURLModelTypeController() override;
 
   // syncer::DataTypeController implementation.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
  private:
   void OnSavingBrowserHistoryDisabledChanged();
diff --git a/components/onc/docs/onc_spec.md b/components/onc/docs/onc_spec.md
index 4a8e41e..08c92219 100644
--- a/components/onc/docs/onc_spec.md
+++ b/components/onc/docs/onc_spec.md
@@ -194,7 +194,6 @@
         * Cellular
         * Ethernet
         * WiFi
-        * WiMAX
         * Tether
     * List of strings containing disabled network interfaces.
 
@@ -278,11 +277,6 @@
     * (required if **Type** is *WiFi*, otherwise ignored) - [WiFi](#WiFi-type)
     * WiFi settings.
 
-* **WiMAX**
-    * (required if **Type** is *WiMAX*, otherwise ignored) -
-      [WiMAX](#WiMAX-type)
-    * WiMAX settings.
-
 * **Cellular**
     * (required if **Type** is *Cellular*, otherwise ignored) -
       [Cellular](#Cellular-type)
@@ -299,7 +293,6 @@
         * *Cellular*
         * *Ethernet*
         * *WiFi*
-        * *WiMAX*
         * *VPN*
     * Indicates which kind of connection this is.
 
@@ -1307,33 +1300,6 @@
     can be set.
 ---
 
-## WiMAX Networks
-
-For WiMAX connections, **Type** must be set to
-*WiMAX* and the field **WiMAX** must be set to an object of
-type [WiMAX](#WiMAX-type).
-
-Currently only used for representing an existing configuration;
-ONC configuration of of **WiMAX** networks is not yet fully supported.
-
-### WiMAX type
-
-* **AutoConnect**
-    * (optional, defaults to *false*) - **boolean**
-    * Indicating that the network should be connected to automatically when
-      possible.
-
-* **EAP**
-    * (required) - [EAP](#EAP-type)
-    * EAP settings.
-
-* **SignalStrength**
-    * (optional, read-only) - **integer**
-    * The current signal strength for this network in the range [0, 100],
-      provided by the system. If the network is not in range this field will
-      be set to '0' or not present.
-
-
 ## Cellular Networks
 
 For Cellular connections, **Type** must be set to *Cellular* and the
@@ -1903,8 +1869,7 @@
 
 In this example, we only allow managed networks to auto connect and
 disallow any other networks if a managed network is available. We also blacklist
-the "Guest" network (hex("Guest")=4775657374) and disable Cellular and WiMAX
-services.
+the "Guest" network (hex("Guest")=4775657374) and disable Cellular services.
 ```
 {
   "Type": "UnencryptedConfiguration",
@@ -1913,7 +1878,7 @@
     “AllowOnlyPolicyNetworksToConnect”: false,
     “AllowOnlyPolicyNetworksToConnectIfAvailable”: true,
     “BlacklistedHexSSIDs”: [“4775657374”],
-    "DisableNetworkTypes": ["Cellular", "WiMAX"]
+    "DisableNetworkTypes": ["Cellular"]
   }
 }
 ```
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc
index aa072ca..9fda651 100644
--- a/components/onc/onc_constants.cc
+++ b/components/onc/onc_constants.cc
@@ -63,7 +63,7 @@
 const char kType[] = "Type";
 const char kVPN[] = "VPN";
 const char kWiFi[] = "WiFi";
-const char kWimax[] = "WiMAX";
+const char kWimaxDeprecated[] = "WiMAX";
 
 std::string CellularProperty(const std::string& property) {
   return std::string(kCellular) + "." + property;
@@ -90,7 +90,7 @@
 const char kTether[] = "Tether";
 const char kVPN[] = "VPN";
 const char kWiFi[] = "WiFi";
-const char kWimax[] = "WiMAX";
+const char kWimaxDeprecated[] = "WiMAX";
 const char kWireless[] = "Wireless";
 }  // namespace network_type
 
@@ -239,11 +239,11 @@
 const char kWPA2_PSK[] = "WPA2-PSK";
 }  // namespace wifi
 
-namespace wimax {
+// Deprecated, properties exist for ignoring old ONC config entries.
+namespace wimax_deprecated {
 const char kAutoConnect[] = "AutoConnect";
 const char kEAP[] = "EAP";
-const char kSignalStrength[] = "SignalStrength";
-}  // namespace wimax
+}  // namespace wimax_deprecated
 
 namespace client_cert {
 const char kClientCertPattern[] = "ClientCertPattern";
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h
index b57a272..bea11275 100644
--- a/components/onc/onc_constants.h
+++ b/components/onc/onc_constants.h
@@ -86,7 +86,7 @@
 ONC_EXPORT extern const char kType[];
 ONC_EXPORT extern const char kVPN[];
 ONC_EXPORT extern const char kWiFi[];
-ONC_EXPORT extern const char kWimax[];
+ONC_EXPORT extern const char kWimaxDeprecated[];
 
 ONC_EXPORT extern std::string CellularProperty(const std::string& property);
 ONC_EXPORT extern std::string TetherProperty(const std::string& property);
@@ -101,7 +101,7 @@
 ONC_EXPORT extern const char kTether[];
 ONC_EXPORT extern const char kVPN[];
 ONC_EXPORT extern const char kWiFi[];
-ONC_EXPORT extern const char kWimax[];
+ONC_EXPORT extern const char kWimaxDeprecated[];
 // Patterns matching multiple types, not part of the ONC spec.
 ONC_EXPORT extern const char kAllTypes[];
 ONC_EXPORT extern const char kWireless[];
@@ -252,11 +252,10 @@
 ONC_EXPORT extern const char kWPA_EAP[];
 }  // namespace wifi
 
-namespace wimax {
+namespace wimax_deprecated {
 ONC_EXPORT extern const char kAutoConnect[];
 ONC_EXPORT extern const char kEAP[];
-ONC_EXPORT extern const char kSignalStrength[];
-}  // namespace wimax
+}  // namespace wimax_deprecated
 
 namespace client_cert {
 ONC_EXPORT extern const char kClientCertPattern[];
diff --git a/components/password_manager/core/browser/leak_detection/BUILD.gn b/components/password_manager/core/browser/leak_detection/BUILD.gn
index 3afab07..3d1b7355 100644
--- a/components/password_manager/core/browser/leak_detection/BUILD.gn
+++ b/components/password_manager/core/browser/leak_detection/BUILD.gn
@@ -42,10 +42,25 @@
     ":proto",
     "//base",
     "//components/password_manager/core/common",
+    "//components/signin/public/identity_manager",
     "//url",
   ]
 }
 
+jumbo_source_set("test_support") {
+  testonly = true
+  sources = [
+    "mock_leak_detection_delegate.cc",
+    "mock_leak_detection_delegate.h",
+  ]
+  deps = [
+    ":leak_detection",
+    "//base/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
 jumbo_source_set("unit_tests") {
   testonly = true
   sources = [
@@ -55,8 +70,10 @@
 
   deps = [
     ":leak_detection",
+    ":test_support",
     "//base/test:test_support",
     "//components/password_manager/core/common",
+    "//components/signin/public/identity_manager:test_support",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/components/password_manager/core/browser/leak_detection/DEPS b/components/password_manager/core/browser/leak_detection/DEPS
new file mode 100644
index 0000000..e704a471
--- /dev/null
+++ b/components/password_manager/core/browser/leak_detection/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/signin/public",
+]
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
index 011be03..97ac85a 100644
--- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
+++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
@@ -6,9 +6,32 @@
 
 #include <utility>
 
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace password_manager {
+namespace {
+
+constexpr char kAPIScope[] = "https://www.googleapis.com/auth/userinfo.id";
+
+// Returns a Google account that can be used for getting a token.
+CoreAccountId GetAccountForRequest(
+    const signin::IdentityManager* identity_manager) {
+  CoreAccountInfo result = identity_manager->GetUnconsentedPrimaryAccountInfo();
+  if (result.IsEmpty()) {
+    std::vector<CoreAccountInfo> all_accounts =
+        identity_manager->GetAccountsWithRefreshTokens();
+    if (!all_accounts.empty())
+      result = all_accounts.front();
+  }
+  return result.account_id;
+}
+
+}  // namespace
 
 AuthenticatedLeakCheck::AuthenticatedLeakCheck(
     LeakDetectionDelegateInterface* delegate,
@@ -16,18 +39,48 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : delegate_(delegate),
       identity_manager_(identity_manager),
-      url_loader_factory_(std::move(url_loader_factory)) {}
+      url_loader_factory_(std::move(url_loader_factory)) {
+  DCHECK(identity_manager_);
+  DCHECK(delegate_);
+}
 
 AuthenticatedLeakCheck::~AuthenticatedLeakCheck() = default;
 
+// static
+bool AuthenticatedLeakCheck::HasAccountForRequest(
+    const signin::IdentityManager* identity_manager) {
+  // On desktop HasUnconsentedPrimaryAccount() will always return something if
+  // the user is signed in.
+  // On Android it will be empty if the user isn't syncing. Thus,
+  // GetAccountsWithRefreshTokens() check is necessary.
+  return identity_manager &&
+         (identity_manager->HasUnconsentedPrimaryAccount() ||
+          !identity_manager->GetAccountsWithRefreshTokens().empty());
+}
+
 void AuthenticatedLeakCheck::Start(const GURL& url,
                                    base::StringPiece16 username,
                                    base::StringPiece16 password) {
-  // TODO(crbug.com/986298): get the access token here.
-  std::ignore = delegate_;
-  std::ignore = identity_manager_;
-  // TODO(crbug.com/986298): Initiate the network request.
-  std::ignore = url_loader_factory_;
+  token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
+      GetAccountForRequest(identity_manager_),
+      /*consumer_name=*/"leak_detection_service", {kAPIScope},
+      base::BindOnce(&AuthenticatedLeakCheck::OnAccessTokenRequestCompleted,
+                     base::Unretained(this)),
+      signin::AccessTokenFetcher::Mode::kImmediate);
+}
+
+void AuthenticatedLeakCheck::OnAccessTokenRequestCompleted(
+    GoogleServiceAuthError error,
+    signin::AccessTokenInfo access_token_info) {
+  token_fetcher_.reset();
+  if (error.state() == GoogleServiceAuthError::NONE) {
+    // The fetcher successfully obtained an access token.
+    access_token_ = std::move(access_token_info.token);
+    DVLOG(0) << "Token=" << access_token_;
+  } else {
+    DLOG(ERROR) << "Token request error: " << error.error_message();
+    delegate_->OnError(LeakDetectionError::kTokenRequestFailure);
+  }
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
index 9eecc0b..91e0792 100644
--- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
+++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
@@ -5,14 +5,21 @@
 #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_AUTHENTICATED_LEAK_CHECK_H_
 #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_AUTHENTICATED_LEAK_CHECK_H_
 
+#include <memory>
+#include <string>
+
 #include "base/memory/scoped_refptr.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
 
+class GoogleServiceAuthError;
+
 namespace network {
 class SharedURLLoaderFactory;
 }  // namespace network
 
 namespace signin {
+class AccessTokenFetcher;
+struct AccessTokenInfo;
 class IdentityManager;
 }  // namespace signin
 
@@ -29,11 +36,25 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   ~AuthenticatedLeakCheck() override;
 
+  // Returns true if there is a Google account to use for the leak detection
+  // check. Otherwise, instantiating the class is pointless.
+  static bool HasAccountForRequest(
+      const signin::IdentityManager* identity_manager);
+
+  // LeakDetectionCheck:
   void Start(const GURL& url,
              base::StringPiece16 username,
              base::StringPiece16 password) override;
 
+#if defined(UNIT_TEST)
+  const std::string& access_token() const { return access_token_; }
+#endif  // defined(UNIT_TEST)
+
  private:
+  // Called when the token request is done.
+  void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
+                                     signin::AccessTokenInfo access_token_info);
+
   // Delegate for the instance. Should outlive |this|.
   LeakDetectionDelegateInterface* delegate_;
   // Identity manager for the profile.
@@ -41,6 +62,10 @@
   // URL loader factory required for the network request to the identity
   // endpoint.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  // Actual request for the needed token.
+  std::unique_ptr<signin::AccessTokenFetcher> token_fetcher_;
+  // The token to be used for request.
+  std::string access_token_;
 };
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
index 9885633..9bae8d60 100644
--- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
@@ -4,13 +4,90 @@
 
 #include "components/password_manager/core/browser/leak_detection/authenticated_leak_check.h"
 
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace password_manager {
+namespace {
 
-TEST(AuthenticatedLeakCheck, Create) {
-  AuthenticatedLeakCheck check(nullptr, nullptr, nullptr);
+using ::testing::StrictMock;
+
+constexpr char kTestEmail[] = "user@gmail.com";
+constexpr char kUsername[] = "username";
+constexpr char kPassword[] = "password123";
+constexpr char kExampleCom[] = "https://example.com";
+
+class AuthenticatedLeakCheckTest : public testing::Test {
+ public:
+  AuthenticatedLeakCheckTest()
+      : leak_check_(&delegate_,
+                    identity_test_env_.identity_manager(),
+                    /*url_loader_factory=*/nullptr) {}
+  ~AuthenticatedLeakCheckTest() override = default;
+
+  signin::IdentityTestEnvironment& identity_env() { return identity_test_env_; }
+  MockLeakDetectionDelegateInterface& delegate() { return delegate_; }
+  AuthenticatedLeakCheck& leak_check() { return leak_check_; }
+
+ private:
+  base::test::ScopedTaskEnvironment task_env_;
+  signin::IdentityTestEnvironment identity_test_env_;
+  StrictMock<MockLeakDetectionDelegateInterface> delegate_;
+  AuthenticatedLeakCheck leak_check_;
+};
+
+}  // namespace
+
+TEST_F(AuthenticatedLeakCheckTest, Create) {
+  EXPECT_CALL(delegate(), OnLeakDetectionDone).Times(0);
+  EXPECT_CALL(delegate(), OnError).Times(0);
+  // Destroying |leak_check_| doesn't trigger anything.
+}
+
+TEST_F(AuthenticatedLeakCheckTest, HasAccountForRequest_SignedIn) {
+  AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+  identity_env().SetCookieAccounts({{info.email, info.account_id}});
+  identity_env().SetRefreshTokenForAccount(info.account_id);
+  EXPECT_TRUE(AuthenticatedLeakCheck::HasAccountForRequest(
+      identity_env().identity_manager()));
+}
+
+TEST_F(AuthenticatedLeakCheckTest, HasAccountForRequest_Syncing) {
+  identity_env().SetPrimaryAccount(kTestEmail);
+  EXPECT_TRUE(AuthenticatedLeakCheck::HasAccountForRequest(
+      identity_env().identity_manager()));
+}
+
+TEST_F(AuthenticatedLeakCheckTest, GetAccessToken) {
+  AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+  identity_env().SetCookieAccounts({{info.email, info.account_id}});
+  identity_env().SetRefreshTokenForAccount(info.account_id);
+
+  leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+                     base::ASCIIToUTF16(kPassword));
+  identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+      "access_token", base::Time::Max());
+  EXPECT_EQ("access_token", leak_check().access_token());
+}
+
+TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenFailure) {
+  AccountInfo info = identity_env().MakeAccountAvailable(kTestEmail);
+  identity_env().SetCookieAccounts({{info.email, info.account_id}});
+  identity_env().SetRefreshTokenForAccount(info.account_id);
+
+  leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
+                     base::ASCIIToUTF16(kPassword));
+
+  EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
+  identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+      GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+  EXPECT_EQ("", leak_check().access_token());
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h b/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
index c408d0f1..8fb419c 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
@@ -11,7 +11,9 @@
 
 enum class LeakDetectionError {
   // The user isn't signed-in to Chrome.
-  kNotSignIn,
+  kNotSignIn = 0,
+  // Error obtaining a token.
+  kTokenRequestFailure = 1,
   // TODO(crbug.com/986298): add more errors.
 };
 
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl.cc b/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl.cc
index 8835790e..b23d8cf 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl.cc
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "components/password_manager/core/browser/leak_detection/authenticated_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -22,6 +23,11 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) const {
   if (!base::FeatureList::IsEnabled(features::kLeakDetection))
     return nullptr;
+
+  if (!AuthenticatedLeakCheck::HasAccountForRequest(identity_manager)) {
+    delegate->OnError(LeakDetectionError::kNotSignIn);
+    return nullptr;
+  }
   return std::make_unique<AuthenticatedLeakCheck>(
       delegate, identity_manager, std::move(url_loader_factory));
 }
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl_unittest.cc b/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl_unittest.cc
index 784fa49..585f4433 100644
--- a/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl_unittest.cc
@@ -5,36 +5,81 @@
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_factory_impl.h"
 
 #include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
-#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
 #include "components/password_manager/core/common/password_manager_features.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace password_manager {
 namespace {
 
-class TestLeakDetectionDelegateInterface
-    : public LeakDetectionDelegateInterface {
- public:
-  TestLeakDetectionDelegateInterface() = default;
-  ~TestLeakDetectionDelegateInterface() override = default;
+using ::testing::StrictMock;
 
-  // LeakDetectionDelegateInterface:
-  void OnLeakDetectionDone(bool leaked,
-                           const GURL& url,
-                           base::StringPiece16 username) override {}
-  void OnError(LeakDetectionError error) override {}
+constexpr char kTestAccount[] = "user@gmail.com";
+
+class LeakDetectionRequestFactoryImplTest : public testing::Test {
+ public:
+  LeakDetectionRequestFactoryImplTest() = default;
+  ~LeakDetectionRequestFactoryImplTest() override = default;
+
+  signin::IdentityTestEnvironment& identity_env() { return identity_test_env_; }
+  MockLeakDetectionDelegateInterface& delegate() { return delegate_; }
+  LeakDetectionRequestFactoryImpl& request_factory() {
+    return request_factory_;
+  }
+
+ private:
+  base::test::ScopedTaskEnvironment task_env_;
+  signin::IdentityTestEnvironment identity_test_env_;
+  StrictMock<MockLeakDetectionDelegateInterface> delegate_;
+  LeakDetectionRequestFactoryImpl request_factory_;
 };
+
 }  // namespace
 
-TEST(LeakDetectionRequestFactoryImpl, DisabledFeature) {
+TEST_F(LeakDetectionRequestFactoryImplTest, DisabledFeature) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndDisableFeature(features::kLeakDetection);
 
-  LeakDetectionRequestFactoryImpl factory;
-  TestLeakDetectionDelegateInterface delegate;
-  EXPECT_FALSE(factory.TryCreateLeakCheck(&delegate, nullptr, nullptr));
+  EXPECT_FALSE(request_factory().TryCreateLeakCheck(
+      &delegate(), identity_env().identity_manager(),
+      /*url_loader_factory=*/nullptr));
+}
+
+TEST_F(LeakDetectionRequestFactoryImplTest, SignedOut) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+  EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNotSignIn));
+  EXPECT_FALSE(request_factory().TryCreateLeakCheck(
+      &delegate(), identity_env().identity_manager(),
+      /*url_loader_factory=*/nullptr));
+}
+
+TEST_F(LeakDetectionRequestFactoryImplTest, SignedIn) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+  AccountInfo info = identity_env().MakeAccountAvailable(kTestAccount);
+  identity_env().SetCookieAccounts({{info.email, info.account_id}});
+  identity_env().SetRefreshTokenForAccount(info.account_id);
+  EXPECT_TRUE(request_factory().TryCreateLeakCheck(
+      &delegate(), identity_env().identity_manager(),
+      /*url_loader_factory=*/nullptr));
+}
+
+TEST_F(LeakDetectionRequestFactoryImplTest, SignedInAndSyncing) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kLeakDetection);
+
+  identity_env().SetPrimaryAccount(kTestAccount);
+  EXPECT_TRUE(request_factory().TryCreateLeakCheck(
+      &delegate(), identity_env().identity_manager(),
+      /*url_loader_factory=*/nullptr));
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.cc
new file mode 100644
index 0000000..9f7f3b0
--- /dev/null
+++ b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.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/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h"
+
+namespace password_manager {
+
+MockLeakDetectionDelegateInterface::MockLeakDetectionDelegateInterface() =
+    default;
+MockLeakDetectionDelegateInterface::~MockLeakDetectionDelegateInterface() =
+    default;
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h
new file mode 100644
index 0000000..077fffcc
--- /dev/null
+++ b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
+
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace password_manager {
+
+class MockLeakDetectionDelegateInterface
+    : public LeakDetectionDelegateInterface {
+ public:
+  MockLeakDetectionDelegateInterface();
+  ~MockLeakDetectionDelegateInterface() override;
+
+  // LeakDetectionDelegateInterface:
+  MOCK_METHOD3(OnLeakDetectionDone,
+               void(bool, const GURL&, base::StringPiece16));
+  MOCK_METHOD1(OnError, void(LeakDetectionError));
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_MOCK_LEAK_DETECTION_DELEGATE_H_
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc
index 59700ac..2473a75 100644
--- a/components/password_manager/core/browser/leak_detection_delegate.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -50,6 +50,9 @@
       case LeakDetectionError::kNotSignIn:
         logger.LogMessage(Logger::STRING_LEAK_DETECTION_SIGNED_OUT_ERROR);
         break;
+      case LeakDetectionError::kTokenRequestFailure:
+        logger.LogMessage(Logger::STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR);
+        break;
     }
   }
 }
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 951f6cfc..69a17d4 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -211,9 +211,10 @@
 
   // Enumerates network connection types.
   enum ConnectionType {
+    reserved 2;
+
     CONNECTION_TYPE_ETHERNET = 0;
     CONNECTION_TYPE_WIFI = 1;
-    CONNECTION_TYPE_WIMAX = 2;
     CONNECTION_TYPE_BLUETOOTH = 3;
     CONNECTION_TYPE_CELLULAR = 4;
   }
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index 3b192e89..03426cd 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -744,9 +744,10 @@
 message NetworkInterface {
   // Indicates the type of network device.
   enum NetworkDeviceType {
+    reserved 2;
+
     TYPE_ETHERNET = 0;
     TYPE_WIFI = 1;
-    TYPE_WIMAX = 2;
     TYPE_BLUETOOTH = 3;
     TYPE_CELLULAR = 4;
   }
diff --git a/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc b/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
index cad730e1..550d6ad 100644
--- a/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
+++ b/components/send_tab_to_self/send_tab_to_self_model_type_controller.cc
@@ -27,16 +27,19 @@
   sync_service_->RemoveObserver(this);
 }
 
-bool SendTabToSelfModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+SendTabToSelfModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return !(syncer::IsWebSignout(sync_service_->GetAuthError()));
+  return syncer::IsWebSignout(sync_service_->GetAuthError())
+             ? PreconditionState::kMustStopAndClearData
+             : PreconditionState::kPreconditionsMet;
 }
 
 void SendTabToSelfModelTypeController::OnStateChanged(
     syncer::SyncService* sync) {
   DCHECK(CalledOnValidThread());
   // Most of these calls will be no-ops but SyncService handles that just fine.
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 }  // namespace send_tab_to_self
diff --git a/components/send_tab_to_self/send_tab_to_self_model_type_controller.h b/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
index fe9244b..b6b3cb3 100644
--- a/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
+++ b/components/send_tab_to_self/send_tab_to_self_model_type_controller.h
@@ -27,7 +27,7 @@
   ~SendTabToSelfModelTypeController() override;
 
   // DataTypeController overrides.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
   // syncer::SyncServiceObserver implementation.
   void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index f609c05f..d7fac12 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -65,6 +65,13 @@
   return account;
 }
 
+bool ContainsGaiaAccount(const std::vector<gaia::ListedAccount>& gaia_accounts,
+                         const CoreAccountId& account_id) {
+  return gaia_accounts.end() !=
+         std::find_if(gaia_accounts.begin(), gaia_accounts.end(),
+                      AccountEqualToFunc(AccountForId(account_id)));
+}
+
 // Returns a copy of |accounts| without the unverified accounts.
 std::vector<gaia::ListedAccount> FilterUnverifiedAccounts(
     const std::vector<gaia::ListedAccount>& accounts) {
@@ -125,6 +132,50 @@
   return token_revoked;
 }
 
+// TODO(msalama): Move this code and |RevokeAllSecondaryTokens|
+// to |DiceAccountReconcilorDelegate|.
+signin::RevokeTokenAction RevokeTokensNotInCookies(
+    signin::IdentityManager* identity_manager,
+    const CoreAccountId& primary_account,
+    const std::vector<gaia::ListedAccount>& gaia_accounts) {
+  bool invalidated_primary_account_token = false;
+  bool revoked_token_for_secondary_account = false;
+  signin_metrics::SourceForRefreshTokenOperation source =
+      signin_metrics::SourceForRefreshTokenOperation::
+          kAccountReconcilor_RevokeTokensNotInCookies;
+
+  for (const CoreAccountInfo& account_info :
+       identity_manager->GetAccountsWithRefreshTokens()) {
+    CoreAccountId account = account_info.account_id;
+    if (ContainsGaiaAccount(gaia_accounts, account))
+      continue;
+
+    auto* accounts_mutator = identity_manager->GetAccountsMutator();
+    if (account == primary_account) {
+      invalidated_primary_account_token = true;
+      accounts_mutator->InvalidateRefreshTokenForPrimaryAccount(source);
+    } else {
+      revoked_token_for_secondary_account = true;
+      accounts_mutator->RemoveAccount(account, source);
+    }
+  }
+
+  signin::RevokeTokenAction revoke_token_action =
+      signin::RevokeTokenAction::kNone;
+  if (invalidated_primary_account_token &&
+      revoked_token_for_secondary_account) {
+    revoke_token_action =
+        signin::RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts;
+  } else if (invalidated_primary_account_token) {
+    revoke_token_action =
+        signin::RevokeTokenAction::kInvalidatePrimaryAccountToken;
+  } else if (revoked_token_for_secondary_account) {
+    revoke_token_action =
+        signin::RevokeTokenAction::kRevokeSecondaryAccountsTokens;
+  }
+  return revoke_token_action;
+}
+
 // Pick the account will become first after this reconcile is finished.
 CoreAccountId PickFirstGaiaAccount(
     const signin::MultiloginParameters& parameters,
@@ -592,6 +643,12 @@
       << " unverified account(s).";
 
   CoreAccountId primary_account = identity_manager_->GetPrimaryAccountId();
+  if (delegate_->ShouldRevokeTokensNotInCookies()) {
+    signin::RevokeTokenAction revoke_token_action = RevokeTokensNotInCookies(
+        identity_manager_, primary_account, verified_gaia_accounts);
+    delegate_->OnRevokeTokensNotInCookiesCompleted(revoke_token_action);
+  }
+
   // Revoking tokens for secondary accounts causes the AccountTracker to
   // completely remove them from Chrome.
   // Revoking the token for the primary account is not supported (it should be
@@ -758,17 +815,12 @@
   std::vector<CoreAccountId> add_to_cookie_copy = add_to_cookie_;
   int added_to_cookie = 0;
   for (size_t i = 0; i < add_to_cookie_copy.size(); ++i) {
-    if (gaia_accounts.end() !=
-        std::find_if(gaia_accounts.begin(), gaia_accounts.end(),
-                     AccountEqualToFunc(AccountForId(add_to_cookie_copy[i])))) {
+    if (ContainsGaiaAccount(gaia_accounts, add_to_cookie_copy[i])) {
       OnAddAccountToCookieCompleted(add_to_cookie_copy[i],
                                     GoogleServiceAuthError::AuthErrorNone());
     } else {
       PerformMergeAction(add_to_cookie_copy[i]);
-      if (original_gaia_accounts.end() ==
-          std::find_if(
-              original_gaia_accounts.begin(), original_gaia_accounts.end(),
-              AccountEqualToFunc(AccountForId(add_to_cookie_copy[i])))) {
+      if (!ContainsGaiaAccount(original_gaia_accounts, add_to_cookie_copy[i])) {
         added_to_cookie++;
       }
     }
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h
index 387cd6f..f617f00 100644
--- a/components/signin/core/browser/account_reconcilor.h
+++ b/components/signin/core/browser/account_reconcilor.h
@@ -140,6 +140,9 @@
  private:
   friend class AccountReconcilorTest;
   friend class DiceBrowserTest;
+  friend class BaseAccountReconcilorTestTable;
+  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestForceDiceMigration,
+                           TableRowTestCheckNoOp);
   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorEndpointParamTest,
                            IdentityManagerRegistration);
   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorEndpointParamTest, Reauth);
@@ -237,6 +240,8 @@
   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
                            DelegateTimeoutIsNotCalledIfTimeoutIsNotReached);
   FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, MultiloginLogout);
+  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestForceDiceMigration,
+                           TableRowTest);
 
   void set_timer_for_testing(std::unique_ptr<base::OneShotTimer> timer);
 
diff --git a/components/signin/core/browser/account_reconcilor_delegate.cc b/components/signin/core/browser/account_reconcilor_delegate.cc
index 3cf1a3b..46d7d0be 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -176,6 +176,10 @@
   return RevokeTokenOption::kDoNotRevoke;
 }
 
+bool AccountReconcilorDelegate::ShouldRevokeTokensNotInCookies() const {
+  return false;
+}
+
 bool AccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
   return false;
 }
diff --git a/components/signin/core/browser/account_reconcilor_delegate.h b/components/signin/core/browser/account_reconcilor_delegate.h
index ab7cf8a..d9edf545 100644
--- a/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/components/signin/core/browser/account_reconcilor_delegate.h
@@ -18,6 +18,15 @@
 
 namespace signin {
 
+// Possible revoke token actions taken by the AccountReconcilor.
+enum class RevokeTokenAction {
+  kNone,
+  kInvalidatePrimaryAccountToken,
+  kRevokeSecondaryAccountsTokens,
+  kRevokeTokensForPrimaryAndSecondaryAccounts,
+  kMaxValue = kRevokeTokensForPrimaryAndSecondaryAccounts
+};
+
 // Base class for AccountReconcilorDelegate.
 class AccountReconcilorDelegate {
  public:
@@ -84,6 +93,14 @@
   virtual RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
       const std::vector<gaia::ListedAccount>& gaia_accounts);
 
+  // Invalidates primary account token or revokes token for any secondary
+  // account that does not have an equivalent gaia cookie.
+  virtual bool ShouldRevokeTokensNotInCookies() const;
+
+  // Called when |RevokeTokensNotInCookies| is finished.
+  virtual void OnRevokeTokensNotInCookiesCompleted(
+      RevokeTokenAction revoke_token_action) {}
+
   // Returns whether tokens should be revoked when the Gaia cookie has been
   // explicitly deleted by the user.
   // If this returns false, tokens will not be revoked. If this returns true,
@@ -92,9 +109,9 @@
   virtual bool ShouldRevokeTokensOnCookieDeleted();
 
   // Called when reconcile is finished.
-  // |OnReconcileFinished| is always called at the end of reconciliation, even
-  // when there is an error (except in cases where reconciliation times out
-  // before finishing, see |GetReconcileTimeout|).
+  // |OnReconcileFinished| is always called at the end of reconciliation,
+  // even when there is an error (except in cases where reconciliation times
+  // out before finishing, see |GetReconcileTimeout|).
   virtual void OnReconcileFinished(const CoreAccountId& first_account,
                                    bool reconcile_is_noop) {}
 
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 155ca78..9b8a25b 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -46,6 +46,7 @@
 #include "components/signin/core/browser/dice_account_reconcilor_delegate.h"
 #endif
 
+using signin::RevokeTokenAction;
 using signin_metrics::AccountReconcilorState;
 
 namespace {
@@ -99,13 +100,15 @@
   DummyAccountReconcilorWithDelegate(
       signin::IdentityManager* identity_manager,
       SigninClient* client,
-      signin::AccountConsistencyMethod account_consistency)
+      signin::AccountConsistencyMethod account_consistency,
+      bool dice_migration_completed)
       : AccountReconcilor(
             identity_manager,
             client,
             CreateAccountReconcilorDelegate(client,
                                             identity_manager,
-                                            account_consistency)) {
+                                            account_consistency,
+                                            dice_migration_completed)) {
 #if defined(OS_IOS)
     SetIsWKHTTPSystemCookieStoreEnabled(true);
 #endif  // defined(OS_IOS)
@@ -132,7 +135,8 @@
   CreateAccountReconcilorDelegate(
       SigninClient* signin_client,
       signin::IdentityManager* identity_manager,
-      signin::AccountConsistencyMethod account_consistency) {
+      signin::AccountConsistencyMethod account_consistency,
+      bool dice_migration_completed) {
     switch (account_consistency) {
       case signin::AccountConsistencyMethod::kMirror:
 #if defined(OS_ANDROID)
@@ -147,7 +151,7 @@
       case signin::AccountConsistencyMethod::kDice:
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
         return std::make_unique<signin::DiceAccountReconcilorDelegate>(
-            signin_client, account_consistency);
+            signin_client, account_consistency, dice_migration_completed);
 #else
         NOTREACHED();
         return nullptr;
@@ -161,12 +165,12 @@
 class MockAccountReconcilor
     : public testing::StrictMock<DummyAccountReconcilorWithDelegate> {
  public:
-  explicit MockAccountReconcilor(
-      signin::IdentityManager* identity_manager,
-      SigninClient* client,
-      signin::AccountConsistencyMethod account_consistency);
+  MockAccountReconcilor(signin::IdentityManager* identity_manager,
+                        SigninClient* client,
+                        signin::AccountConsistencyMethod account_consistency,
+                        bool dice_migration_completed);
 
-  explicit MockAccountReconcilor(
+  MockAccountReconcilor(
       signin::IdentityManager* identity_manager,
       SigninClient* client,
       std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
@@ -180,11 +184,13 @@
 MockAccountReconcilor::MockAccountReconcilor(
     signin::IdentityManager* identity_manager,
     SigninClient* client,
-    signin::AccountConsistencyMethod account_consistency)
+    signin::AccountConsistencyMethod account_consistency,
+    bool dice_migration_completed)
     : testing::StrictMock<DummyAccountReconcilorWithDelegate>(
           identity_manager,
           client,
-          account_consistency) {}
+          account_consistency,
+          dice_migration_completed) {}
 
 MockAccountReconcilor::MockAccountReconcilor(
     signin::IdentityManager* identity_manager,
@@ -255,6 +261,9 @@
 
   void SetAccountConsistency(signin::AccountConsistencyMethod method);
 
+  // Should never be called before |SetAccountConsistency|.
+  void SetDiceMigrationCompleted(bool dice_migration_completed);
+
   PrefService* pref_service() { return &pref_service_; }
 
   void DeleteReconcilor() { mock_reconcilor_.reset(); }
@@ -264,6 +273,7 @@
  private:
   base::test::ScopedTaskEnvironment task_environment_;
   signin::AccountConsistencyMethod account_consistency_;
+  bool dice_migration_completed_ = false;
   sync_preferences::TestingPrefServiceSyncable pref_service_;
   TestSigninClient test_signin_client_;
   signin::IdentityTestEnvironment identity_test_env_;
@@ -343,7 +353,7 @@
   if (!mock_reconcilor_) {
     mock_reconcilor_ = std::make_unique<MockAccountReconcilor>(
         identity_test_env_.identity_manager(), &test_signin_client_,
-        account_consistency_);
+        account_consistency_, dice_migration_completed_);
   }
 
   return mock_reconcilor_.get();
@@ -402,6 +412,14 @@
 void AccountReconcilorTest::SetAccountConsistency(
     signin::AccountConsistencyMethod method) {
   account_consistency_ = method;
+  dice_migration_completed_ =
+      account_consistency_ == signin::AccountConsistencyMethod::kDice;
+}
+
+void AccountReconcilorTest::SetDiceMigrationCompleted(
+    bool dice_migration_completed) {
+  DCHECK_EQ(signin::AccountConsistencyMethod::kDice, account_consistency_);
+  dice_migration_completed_ = dice_migration_completed;
 }
 
 TEST_F(AccountReconcilorTest, Basic) {
@@ -447,6 +465,15 @@
   return return_params;
 }
 
+struct ForceDiceMigrationTestTableParam {
+  const char* tokens;
+  const char* cookies;
+  const char* gaia_api_calls;
+  const char* tokens_after_reconcile;
+  const char* cookies_after_reconcile;
+  RevokeTokenAction revoke_token_action;
+};
+
 // Pretty prints a AccountReconcilorTestTableParam. Used by gtest.
 void PrintTo(const AccountReconcilorTestTableParam& param, ::std::ostream* os) {
   *os << "Tokens: " << param.tokens << ". Cookies: " << param.cookies
@@ -455,11 +482,36 @@
                                                                : "false");
 }
 
-// Parameterized version of AccountReconcilorTest.
-class AccountReconcilorTestTable
-    : public AccountReconcilorTest,
-      public ::testing::WithParamInterface<AccountReconcilorTestTableParam> {
+class BaseAccountReconcilorTestTable : public AccountReconcilorTest {
  protected:
+  BaseAccountReconcilorTestTable(const AccountReconcilorTestTableParam& param)
+      : BaseAccountReconcilorTestTable(param.tokens,
+                                       param.cookies,
+                                       param.is_first_reconcile,
+                                       param.gaia_api_calls,
+                                       param.tokens_after_reconcile,
+                                       param.cookies_after_reconcile) {}
+
+  BaseAccountReconcilorTestTable(const char* tokens,
+                                 const char* cookies,
+                                 IsFirstReconcile is_first_reconcile,
+                                 const char* gaia_api_calls,
+                                 const char* tokens_after_reconcile,
+                                 const char* cookies_after_reconcile)
+      : tokens_(tokens),
+        cookies_(cookies),
+        is_first_reconcile_(is_first_reconcile),
+        gaia_api_calls_(gaia_api_calls),
+        tokens_after_reconcile_(tokens_after_reconcile),
+        cookies_after_reconcile_(cookies_after_reconcile) {
+    accounts_['A'] = {"a@gmail.com",
+                      signin::GetTestGaiaIdForEmail("a@gmail.com")};
+    accounts_['B'] = {"b@gmail.com",
+                      signin::GetTestGaiaIdForEmail("b@gmail.com")};
+    accounts_['C'] = {"c@gmail.com",
+                      signin::GetTestGaiaIdForEmail("c@gmail.com")};
+  }
+
   struct Account {
     std::string email;
     std::string gaia_id;
@@ -472,15 +524,6 @@
     bool has_error;
   };
 
-  AccountReconcilorTestTable() {
-    accounts_['A'] = {"a@gmail.com",
-                      signin::GetTestGaiaIdForEmail("a@gmail.com")};
-    accounts_['B'] = {"b@gmail.com",
-                      signin::GetTestGaiaIdForEmail("b@gmail.com")};
-    accounts_['C'] = {"c@gmail.com",
-                      signin::GetTestGaiaIdForEmail("c@gmail.com")};
-  }
-
   // Build Tokens from string.
   std::vector<Token> ParseTokenString(const char* token_string) {
     std::vector<Token> parsed_tokens;
@@ -545,11 +588,10 @@
       EXPECT_EQ(CoreAccountId(), identity_manager->GetPrimaryAccountId());
   }
 
-  void SetupTokens() {
-    std::vector<Token> tokens_before_reconcile =
-        ParseTokenString(GetParam().tokens);
+  void SetupTokens(const char* tokens_string) {
+    std::vector<Token> tokens = ParseTokenString(tokens_string);
     Token primary_account;
-    for (const Token& token : tokens_before_reconcile) {
+    for (const Token& token : tokens) {
       CoreAccountId account_id;
       if (token.is_authenticated) {
         account_id = ConnectProfileToAccount(token.email).account_id;
@@ -564,9 +606,145 @@
                 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
       }
     }
-    VerifyCurrentTokens(tokens_before_reconcile);
+    VerifyCurrentTokens(tokens);
   }
 
+  void ConfigureCookieManagerService(const std::vector<Cookie>& cookies) {
+    std::vector<signin::CookieParams> cookie_params;
+    for (const auto& cookie : cookies) {
+      std::string gaia_id = cookie.gaia_id;
+
+      // Figure the account token of this specific account id,
+      // ie 'A', 'B', or 'C'.
+      char account_key = '\0';
+      for (const auto& account : accounts_) {
+        if (account.second.gaia_id == gaia_id) {
+          account_key = account.first;
+          break;
+        }
+      }
+      ASSERT_NE(account_key, '\0');
+
+      cookie_params.push_back({accounts_[account_key].email, gaia_id,
+                               cookie.is_valid, false /* signed_out */,
+                               true /* verified */});
+    }
+    signin::SetListAccountsResponseWithParams(cookie_params,
+                                              &test_url_loader_factory_);
+    identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
+  }
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+  void RunReconcile() {
+    // Setup cookies.
+    std::vector<Cookie> cookies = ParseCookieString(cookies_);
+    ConfigureCookieManagerService(cookies);
+
+    // Setup tokens. This triggers listing cookies so we need to setup cookies
+    // before that.
+    SetupTokens(tokens_);
+
+    // Call list accounts now so that the next call completes synchronously.
+    identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+    base::RunLoop().RunUntilIdle();
+
+    // Setup expectations.
+    testing::InSequence mock_sequence;
+    bool logout_action = false;
+    for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
+      if (gaia_api_calls_[i] == 'X') {
+        logout_action = true;
+        EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+            .Times(1);
+        cookies.clear();
+        continue;
+      }
+      std::string cookie(1, gaia_api_calls_[i]);
+      CoreAccountId account_id_for_cookie = PickAccountIdForAccount(
+          accounts_[cookie[0]].gaia_id, accounts_[cookie[0]].email);
+      EXPECT_CALL(*GetMockReconcilor(),
+                  PerformMergeAction(account_id_for_cookie))
+          .Times(1);
+      // MergeSession fixes an existing cookie or appends it at the end.
+      auto it = std::find(cookies.begin(), cookies.end(),
+                          Cookie{account_id_for_cookie, false /* is_valid */});
+      if (it == cookies.end())
+        cookies.push_back({account_id_for_cookie, true});
+      else
+        it->is_valid = true;
+    }
+    if (!logout_action) {
+      EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+          .Times(0);
+    }
+
+    // Check the expected cookies after reconcile.
+    std::vector<Cookie> expected_cookies =
+        ParseCookieString(cookies_after_reconcile_);
+    ASSERT_EQ(expected_cookies, cookies);
+
+    // Reconcile.
+    AccountReconcilor* reconcilor = GetMockReconcilor();
+    ASSERT_TRUE(reconcilor->first_execution_);
+    reconcilor->first_execution_ =
+        is_first_reconcile_ == IsFirstReconcile::kFirst;
+    ASSERT_TRUE(reconcilor->delegate_->IsAccountConsistencyEnforced());
+    reconcilor->StartReconcile();
+    for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
+      if (gaia_api_calls_[i] == 'X')
+        continue;
+      CoreAccountId account_id =
+          PickAccountIdForAccount(accounts_[gaia_api_calls_[i]].gaia_id,
+                                  accounts_[gaia_api_calls_[i]].email);
+      SimulateAddAccountToCookieCompleted(
+          reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
+    }
+    ASSERT_FALSE(reconcilor->is_reconcile_started_);
+
+    if (tokens_ == tokens_after_reconcile_) {
+      EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+    } else {
+      // If the tokens were changed by the reconcile, a new reconcile should be
+      // scheduled.
+      EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
+                reconcilor->GetState());
+    }
+
+    VerifyCurrentTokens(ParseTokenString(tokens_after_reconcile_));
+
+    testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
+
+    // Another reconcile is sometimes triggered if Chrome accounts have changed.
+    // Allow it to finish.
+    EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
+        .WillRepeatedly(testing::Return());
+    EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+        .WillRepeatedly(testing::Return());
+    ConfigureCookieManagerService({});
+    base::RunLoop().RunUntilIdle();
+  }
+#endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+  std::string GaiaIdForAccountKey(char account_key) {
+    return accounts_[account_key].gaia_id;
+  }
+
+  std::map<char, Account> accounts_;
+  const char* tokens_;
+  const char* cookies_;
+  IsFirstReconcile is_first_reconcile_;
+  const char* gaia_api_calls_;
+  const char* tokens_after_reconcile_;
+  const char* cookies_after_reconcile_;
+};
+
+// Parameterized version of AccountReconcilorTest.
+class AccountReconcilorTestTable
+    : public BaseAccountReconcilorTestTable,
+      public ::testing::WithParamInterface<AccountReconcilorTestTableParam> {
+ protected:
+  AccountReconcilorTestTable() : BaseAccountReconcilorTestTable(GetParam()) {}
+
   // Checks that reconcile is idempotent.
   void CheckReconcileIdempotent(
       const std::vector<AccountReconcilorTestTableParam>& params,
@@ -599,37 +777,6 @@
 
     ADD_FAILURE() << "Could not check that reconcile is idempotent.";
   }
-
-  void ConfigureCookieManagerService(const std::vector<Cookie>& cookies) {
-    std::vector<signin::CookieParams> cookie_params;
-    for (const auto& cookie : cookies) {
-      std::string gaia_id = cookie.gaia_id;
-
-      // Figure the account token of this specific account id,
-      // ie 'A', 'B', or 'C'.
-      char account_key = '\0';
-      for (const auto& account : accounts_) {
-        if (account.second.gaia_id == gaia_id) {
-          account_key = account.first;
-          break;
-        }
-      }
-      ASSERT_NE(account_key, '\0');
-
-      cookie_params.push_back({accounts_[account_key].email, gaia_id,
-                               cookie.is_valid, false /* signed_out */,
-                               true /* verified */});
-    }
-    signin::SetListAccountsResponseWithParams(cookie_params,
-                                              &test_url_loader_factory_);
-    identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
-  }
-
-  std::string GaiaIdForAccountKey(char account_key) {
-    return accounts_[account_key].gaia_id;
-  }
-
-  std::map<char, Account> accounts_;
 };
 
 #if !defined(OS_CHROMEOS)
@@ -898,91 +1045,9 @@
   // Check that reconcile is idempotent: when called twice in a row it should do
   // nothing on the second call.
   CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/false);
-
-  // Setup cookies.
-  std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
-  ConfigureCookieManagerService(cookies);
-
-  // Setup tokens. This triggers listing cookies so we need to setup cookies
-  // before that.
-  SetupTokens();
-
-  // Call list accounts now so that the next call completes synchronously.
-  identity_test_env()->identity_manager()->GetAccountsInCookieJar();
-  base::RunLoop().RunUntilIdle();
-
-  // Setup expectations.
-  testing::InSequence mock_sequence;
-  bool logout_action = false;
-  for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
-    if (GetParam().gaia_api_calls[i] == 'X') {
-      logout_action = true;
-      EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-          .Times(1);
-      cookies.clear();
-      continue;
-    }
-    std::string cookie(1, GetParam().gaia_api_calls[i]);
-    CoreAccountId account_id_for_cookie = PickAccountIdForAccount(
-        accounts_[cookie[0]].gaia_id, accounts_[cookie[0]].email);
-    EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_for_cookie))
-        .Times(1);
-    // MergeSession fixes an existing cookie or appends it at the end.
-    auto it = std::find(cookies.begin(), cookies.end(),
-                        Cookie{account_id_for_cookie.id, false /* is_valid */});
-    if (it == cookies.end())
-      cookies.push_back({account_id_for_cookie.id, true});
-    else
-      it->is_valid = true;
-  }
-  if (!logout_action) {
-    EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-        .Times(0);
-  }
-
-  // Check the expected cookies after reconcile.
-  std::vector<Cookie> expected_cookies =
-      ParseCookieString(GetParam().cookies_after_reconcile);
-  ASSERT_EQ(expected_cookies, cookies);
-
-  // Reconcile.
-  AccountReconcilor* reconcilor = GetMockReconcilor();
-  ASSERT_TRUE(reconcilor->first_execution_);
-  reconcilor->first_execution_ =
-      GetParam().is_first_reconcile == IsFirstReconcile::kFirst;
-  reconcilor->StartReconcile();
-  for (int i = 0; GetParam().gaia_api_calls[i] != '\0'; ++i) {
-    if (GetParam().gaia_api_calls[i] == 'X')
-      continue;
-    CoreAccountId account_id =
-        PickAccountIdForAccount(accounts_[GetParam().gaia_api_calls[i]].gaia_id,
-                                accounts_[GetParam().gaia_api_calls[i]].email);
-    SimulateAddAccountToCookieCompleted(
-        reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
-  }
-  ASSERT_FALSE(reconcilor->is_reconcile_started_);
-
-  if (GetParam().tokens == GetParam().tokens_after_reconcile) {
-    EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
-  } else {
-    // If the tokens were changed by the reconcile, a new reconcile should be
-    // scheduled.
-    EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
-              reconcilor->GetState());
-  }
-
-  VerifyCurrentTokens(ParseTokenString(GetParam().tokens_after_reconcile));
-
-  testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
-
-  // Another reconcile is sometimes triggered if Chrome accounts have changed.
-  // Allow it to finish.
-  EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_))
-      .WillRepeatedly(testing::Return());
-  EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
-      .WillRepeatedly(testing::Return());
-  ConfigureCookieManagerService({});
-  base::RunLoop().RunUntilIdle();
+  RunReconcile();
+  histogram_tester()->ExpectTotalCount("ForceDiceMigration.RevokeTokenAction",
+                                       0);
 }
 
 // Checks one row of the kDiceParams table above.
@@ -990,11 +1055,11 @@
   // Enable Dice Migration.
   SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration);
   // Setup cookies.
-  std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
+  std::vector<Cookie> cookies = ParseCookieString(cookies_);
   ConfigureCookieManagerService(cookies);
   // Setup tokens. This triggers listing cookies so we need to setup cookies
   // before that.
-  SetupTokens();
+  SetupTokens(tokens_);
   // Call list accounts now so that the next call completes synchronously.
   identity_test_env()->identity_manager()->GetAccountsInCookieJar();
   base::RunLoop().RunUntilIdle();
@@ -1019,6 +1084,9 @@
       "Signin.DiceMigrationNotReady.Reason." + histogram_name_suffix,
       GetParam().inconsistency_reason, 1);
 
+  histogram_tester()->ExpectTotalCount("ForceDiceMigration.RevokeTokenAction",
+                                       0);
+
   ConfigureCookieManagerService({});
   base::RunLoop().RunUntilIdle();
 }
@@ -1028,6 +1096,101 @@
     AccountReconcilorTestTable,
     ::testing::ValuesIn(GenerateTestCasesFromParams(kDiceParams)));
 
+class AccountReconcilorTestForceDiceMigration
+    : public BaseAccountReconcilorTestTable,
+      public ::testing::WithParamInterface<ForceDiceMigrationTestTableParam> {
+ public:
+  AccountReconcilorTestForceDiceMigration()
+      : BaseAccountReconcilorTestTable(GetParam().tokens,
+                                       GetParam().cookies,
+                                       IsFirstReconcile::kFirst,
+                                       GetParam().gaia_api_calls,
+                                       GetParam().tokens_after_reconcile,
+                                       GetParam().cookies_after_reconcile) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestForceDiceMigration);
+};
+
+// clang-format off
+const std::vector<ForceDiceMigrationTestTableParam> kForceDiceParams = {
+    {"*A",   "AB",   "XA", "*A",    "A"   , RevokeTokenAction::kNone},
+    {"*AxB", "AB",   "XA", "*A",    "A"   , RevokeTokenAction::kNone},
+    {"AxB",  "AB",   "XA", "A",     "A"   , RevokeTokenAction::kNone},
+    {"xAxB", "AB",   "X",  "",      ""    , RevokeTokenAction::kNone},
+    {"*A",   "",     "",   "*xA",   ""    , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+    {"*A",   "B",    "X",  "*xA",   ""    , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+    {"*AB",  "B",    "",   "*xAB",  "B"   , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+    {"*AxB", "B",    "X",  "*xA",   ""    , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+    {"*ABC", "CB",   "",   "*xABC", "CB"  , RevokeTokenAction::kInvalidatePrimaryAccountToken},
+    {"*AB",  "A",    "",   "*A",    "A"   , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AB",   "A",    "",   "A",     "A"   , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AB",   "",     "",   "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "",     "",   "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "A",    "X",  "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "xA",   "",   "",      "xA"  , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "B",    "",   "B",     "B"   , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AxB",  "B",    "X",  "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AxB",  "",     "",   "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAxB", "",     "",   "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"B",    "xA",   "",   "",      "xA"  , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AB",   "xAB",  "",   "B",     "xAB" , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "xAC",  "X",  "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"xAB",  "AxC",  "X",  "",      ""    , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"AB",   "BC",   "XB", "B",     "B"   , RevokeTokenAction::kRevokeSecondaryAccountsTokens},
+    {"*AB",  "",     "",   "*xA",   ""    , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+    {"*xAB", "",     "",   "*xA",   ""    , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+    {"*AxB", "",     "",   "*xA",   ""    , RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts},
+    {"*AB",  "xBxA", "",   "*xA",   "xBxA", RevokeTokenAction::kRevokeTokensForPrimaryAndSecondaryAccounts}
+  };
+// clang-format on
+
+// Checks one row of the kForceDiceParams table above.
+TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTest) {
+  SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
+  EXPECT_FALSE(test_signin_client()->is_dice_migration_completed());
+  SetDiceMigrationCompleted(false);
+  RunReconcile();
+  EXPECT_TRUE(test_signin_client()->is_dice_migration_completed());
+  EXPECT_FALSE(
+      GetMockReconcilor()->delegate_->ShouldRevokeTokensNotInCookies());
+  histogram_tester()->ExpectUniqueSample("ForceDiceMigration.RevokeTokenAction",
+                                         GetParam().revoke_token_action, 1);
+}
+
+// Check that the result state of the reconcile is in a final state (reconcile
+// started from this state is a no-op).
+TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTestCheckNoOp) {
+  SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
+  // Setup cookies.
+  std::vector<Cookie> cookies = ParseCookieString(cookies_after_reconcile_);
+  ConfigureCookieManagerService(cookies);
+
+  // Setup tokens. This triggers listing cookies so we need to setup cookies
+  // before that.
+  SetupTokens(tokens_after_reconcile_);
+
+  // Call list accounts now so that the next call completes synchronously.
+  identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
+  EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(0);
+  EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
+      .Times(0);
+
+  AccountReconcilor* reconcilor = GetMockReconcilor();
+  EXPECT_FALSE(reconcilor->delegate_->ShouldRevokeTokensNotInCookies());
+  reconcilor->StartReconcile();
+  base::RunLoop().RunUntilIdle();
+  ASSERT_FALSE(reconcilor->is_reconcile_started_);
+  ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+}
+
+INSTANTIATE_TEST_SUITE_P(DiceMigrationTable,
+                         AccountReconcilorTestForceDiceMigration,
+                         ::testing::ValuesIn(kForceDiceParams));
+
 // Parameterized version of AccountReconcilorTest that tests Dice
 // implementation with Multilogin endpoint.
 class AccountReconcilorTestDiceMultilogin : public AccountReconcilorTestTable {
@@ -1043,7 +1206,6 @@
 
 // Checks one row of the kDiceParams table above.
 TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
-  // Enable Mirror.
   SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
   scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
 
@@ -1056,7 +1218,7 @@
 
   // Setup tokens. This triggers listing cookies so we need to setup cookies
   // before that.
-  SetupTokens();
+  SetupTokens(GetParam().tokens);
 
   // Call list accounts now so that the next call completes synchronously.
   identity_test_env()->identity_manager()->GetAccountsInCookieJar();
@@ -1747,7 +1909,7 @@
   scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
 
   // Setup tokens.
-  SetupTokens();
+  SetupTokens(GetParam().tokens);
 
   // Setup cookies.
   std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
@@ -1869,7 +2031,7 @@
 
   // Setup tokens. This triggers listing cookies so we need to setup cookies
   // before that.
-  SetupTokens();
+  SetupTokens(GetParam().tokens);
 
   // Call list accounts now so that the next call completes synchronously.
   identity_test_env()->identity_manager()->GetAccountsInCookieJar();
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
index bc560b6..2adffa0 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -17,11 +17,16 @@
 
 DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
     SigninClient* signin_client,
-    AccountConsistencyMethod account_consistency)
-    : signin_client_(signin_client), account_consistency_(account_consistency) {
+    AccountConsistencyMethod account_consistency,
+    bool migration_completed)
+    : signin_client_(signin_client),
+      account_consistency_(account_consistency),
+      migration_completed_(migration_completed) {
   DCHECK(signin_client_);
   DCHECK(DiceMethodGreaterOrEqual(account_consistency_,
                                   AccountConsistencyMethod::kDiceMigration));
+  DCHECK(account_consistency == AccountConsistencyMethod::kDice ||
+         !migration_completed);
 }
 
 bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
@@ -235,11 +240,24 @@
     return RevokeTokenOption::kRevoke;
   }
 
-  return (account_consistency_ == AccountConsistencyMethod::kDice)
+  return account_consistency_ == AccountConsistencyMethod::kDice
              ? RevokeTokenOption::kRevokeIfInError
              : RevokeTokenOption::kDoNotRevoke;
 }
 
+bool DiceAccountReconcilorDelegate::ShouldRevokeTokensNotInCookies() const {
+  return account_consistency_ == AccountConsistencyMethod::kDice &&
+         !migration_completed_;
+}
+
+void DiceAccountReconcilorDelegate::OnRevokeTokensNotInCookiesCompleted(
+    RevokeTokenAction revoke_token_action) {
+  migration_completed_ = true;
+  signin_client_->SetDiceMigrationCompleted();
+  UMA_HISTOGRAM_ENUMERATION("ForceDiceMigration.RevokeTokenAction",
+                            revoke_token_action);
+}
+
 bool DiceAccountReconcilorDelegate::ShouldRevokeTokensOnCookieDeleted() {
   return account_consistency_ == AccountConsistencyMethod::kDice;
 }
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.h b/components/signin/core/browser/dice_account_reconcilor_delegate.h
index d62c037..f1efaba 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -19,7 +19,8 @@
 class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
  public:
   DiceAccountReconcilorDelegate(SigninClient* signin_client,
-                                AccountConsistencyMethod account_consistency);
+                                AccountConsistencyMethod account_consistency,
+                                bool migration_completed);
   ~DiceAccountReconcilorDelegate() override {}
 
   // AccountReconcilorDelegate:
@@ -39,6 +40,11 @@
       bool will_logout) const override;
   RevokeTokenOption ShouldRevokeSecondaryTokensBeforeReconcile(
       const std::vector<gaia::ListedAccount>& gaia_accounts) override;
+  // Returns true if in force migration to dice state.
+  bool ShouldRevokeTokensNotInCookies() const override;
+  // Disables force dice migration and sets dice migration as completed.
+  void OnRevokeTokensNotInCookiesCompleted(
+      RevokeTokenAction revoke_token_action) override;
   void OnReconcileFinished(const CoreAccountId& first_account,
                            bool reconcile_is_noop) override;
   bool ShouldRevokeTokensOnCookieDeleted() override;
@@ -82,6 +88,7 @@
 
   SigninClient* signin_client_;
   AccountConsistencyMethod account_consistency_;
+  bool migration_completed_;
 
   // Last known "first account". Used when cookies are lost as a best guess.
   CoreAccountId last_known_first_account_;
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
index 5e3134224..10f66fc 100644
--- a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
+++ b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -32,17 +32,21 @@
 TEST(DiceAccountReconcilorDelegateTest, RevokeTokens) {
   sync_preferences::TestingPrefServiceSyncable pref_service;
   TestSigninClient client(&pref_service);
+  gaia::ListedAccount gaia_account;
+  gaia_account.id = CoreAccountId("other");
   {
     // Dice is enabled, revoke only tokens in error state.
-    DiceAccountReconcilorDelegate delegate(&client,
-                                           AccountConsistencyMethod::kDice);
-    EXPECT_EQ(AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
-              delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
-                  std::vector<gaia::ListedAccount>()));
+    DiceAccountReconcilorDelegate delegate(
+        &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
+    EXPECT_EQ(
+        signin::AccountReconcilorDelegate::RevokeTokenOption::kRevokeIfInError,
+        delegate.ShouldRevokeSecondaryTokensBeforeReconcile(
+            std::vector<gaia::ListedAccount>()));
   }
   {
     DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration);
+        &client, AccountConsistencyMethod::kDiceMigration,
+        /*migration_completed=*/false);
     // Gaia accounts are not empty, don't revoke.
     gaia::ListedAccount gaia_account;
     gaia_account.id = CoreAccountId("other");
@@ -68,7 +72,8 @@
     testing::InSequence mock_sequence;
     EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
     DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration);
+        &client, AccountConsistencyMethod::kDiceMigration,
+        /*migration_completed=*/false);
     delegate.OnReconcileFinished(CoreAccountId("account"),
                                  true /* is_reconcile_noop */);
   }
@@ -81,7 +86,8 @@
     testing::InSequence mock_sequence;
     EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
     DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration);
+        &client, AccountConsistencyMethod::kDiceMigration,
+        /*migration_completed=*/false);
     delegate.OnReconcileFinished(CoreAccountId("account"),
                                  false /* is_reconcile_noop */);
   }
@@ -91,26 +97,38 @@
     testing::InSequence mock_sequence;
     EXPECT_CALL(client, SetReadyForDiceMigration(true)).Times(1);
     DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration);
+        &client, AccountConsistencyMethod::kDiceMigration, false);
     delegate.OnReconcileFinished(CoreAccountId("account"),
                                  true /* is_reconcile_noop */);
   }
 }
 
-TEST(DiceAccountReconcilorDelegateTest, ShouldRevokeTokensOnCookieDeleted) {
+TEST(DiceAccountReconcilorDelegateTest, ShouldRevokeTokensBasedOnCookies) {
   sync_preferences::TestingPrefServiceSyncable pref_service;
   TestSigninClient client(&pref_service);
   {
     // Dice is enabled, revoke tokens when Gaia cookie is deleted.
-    DiceAccountReconcilorDelegate delegate(&client,
-                                           AccountConsistencyMethod::kDice);
+    DiceAccountReconcilorDelegate delegate(
+        &client, AccountConsistencyMethod::kDice, /*migration_completed=*/true);
     EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
+    EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
+  }
+  {
+    // Dice is enabled, migration not completed, revoke tokens when
+    // Gaia cookie is deleted.
+    DiceAccountReconcilorDelegate delegate(&client,
+                                           AccountConsistencyMethod::kDice,
+                                           /*migration_completed=*/false);
+    EXPECT_EQ(true, delegate.ShouldRevokeTokensOnCookieDeleted());
+    EXPECT_EQ(true, delegate.ShouldRevokeTokensNotInCookies());
   }
   {
     // Dice is not enabled, do not revoke tokens when Gaia cookie is deleted.
     DiceAccountReconcilorDelegate delegate(
-        &client, AccountConsistencyMethod::kDiceMigration);
+        &client, AccountConsistencyMethod::kDiceMigration,
+        /*migration_completed=*/false);
     EXPECT_EQ(false, delegate.ShouldRevokeTokensOnCookieDeleted());
+    EXPECT_EQ(false, delegate.ShouldRevokeTokensNotInCookies());
   }
 }
 
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
index 7f9ec637..5308623 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service.cc
@@ -62,6 +62,9 @@
       return "MachineLogon::CredentialProvider";
     case SourceForRefreshTokenOperation::kTokenService_ExtractCredentials:
       return "TokenService::ExtractCredentials";
+    case SourceForRefreshTokenOperation::
+        kAccountReconcilor_RevokeTokensNotInCookies:
+      return "AccountReconcilor::RevokeTokensNotInCookies";
   }
 }
 }  // namespace
diff --git a/components/signin/public/base/signin_client.h b/components/signin/public/base/signin_client.h
index d5c7889..3189fa174 100644
--- a/components/signin/public/base/signin_client.h
+++ b/components/signin/public/base/signin_client.h
@@ -93,6 +93,9 @@
       GaiaAuthConsumer* consumer,
       gaia::GaiaSource source) = 0;
 
+  // Marks the DICE migration completed.
+  virtual void SetDiceMigrationCompleted() {}
+
   // Schedules migration to happen at next startup.
   virtual void SetReadyForDiceMigration(bool is_ready) {}
 };
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index 77fe702..ca12cc2 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -310,8 +310,9 @@
   kDiceTurnOnSyncHelper_Abort,
   kMachineLogon_CredentialProvider,
   kTokenService_ExtractCredentials,
+  kAccountReconcilor_RevokeTokensNotInCookies,
 
-  kMaxValue = kTokenService_ExtractCredentials
+  kMaxValue = kAccountReconcilor_RevokeTokensNotInCookies
 };
 
 // Different types of reporting. This is used as a histogram suffix.
diff --git a/components/signin/public/base/test_signin_client.cc b/components/signin/public/base/test_signin_client.cc
index cfa57bc..36b8cb7 100644
--- a/components/signin/public/base/test_signin_client.cc
+++ b/components/signin/public/base/test_signin_client.cc
@@ -20,7 +20,8 @@
       are_signin_cookies_allowed_(true),
       network_calls_delayed_(false),
       is_signout_allowed_(true),
-      is_ready_for_dice_migration_(false) {}
+      is_ready_for_dice_migration_(false),
+      is_dice_migration_completed_(false) {}
 
 TestSigninClient::~TestSigninClient() {}
 
@@ -120,3 +121,7 @@
 void TestSigninClient::SetReadyForDiceMigration(bool ready) {
   is_ready_for_dice_migration_ = ready;
 }
+
+void TestSigninClient::SetDiceMigrationCompleted() {
+  is_dice_migration_completed_ = true;
+}
diff --git a/components/signin/public/base/test_signin_client.h b/components/signin/public/base/test_signin_client.h
index 5ea2dee..9ecf7fa55 100644
--- a/components/signin/public/base/test_signin_client.h
+++ b/components/signin/public/base/test_signin_client.h
@@ -73,6 +73,7 @@
   void set_is_signout_allowed(bool value) { is_signout_allowed_ = value; }
 
   bool is_ready_for_dice_migration() { return is_ready_for_dice_migration_; }
+  bool is_dice_migration_completed() { return is_dice_migration_completed_; }
 
   // When |value| is true, network calls posted through DelayNetworkCall() are
   // delayed indefinitely.
@@ -92,6 +93,7 @@
       gaia::GaiaSource source) override;
   void PreGaiaLogout(base::OnceClosure callback) override;
   void SetReadyForDiceMigration(bool ready) override;
+  void SetDiceMigrationCompleted() override;
 
  private:
   std::unique_ptr<network::TestURLLoaderFactory>
@@ -104,6 +106,7 @@
   bool network_calls_delayed_;
   bool is_signout_allowed_;
   bool is_ready_for_dice_migration_;
+  bool is_dice_migration_completed_;
 
   std::vector<base::OnceClosure> delayed_network_calls_;
 
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index 0ad1c39..75d3a3b 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -139,11 +139,8 @@
   return offset;
 }
 
-// Determines whether the user can provide demographics considering that: (1) it
-// is not possible to infer the month and the day of the birth date when the
-// user is in an age transition, and (2) only users of at least 18 years old can
-// report demographics.
-bool CanProvideDemographics(base::Time now, int user_birth_year, int offset) {
+// Determines whether the user birth year is eligible for being provided.
+bool HasEligibleBirthYear(base::Time now, int user_birth_year, int offset) {
   // Compute user age.
   base::Time::Exploded exploded_now_time;
   now.LocalExplode(&exploded_now_time);
@@ -152,8 +149,8 @@
   // Verify if the user's age has a population size in the age distribution of
   // the society that is big enough to not rise entropy of the user. At a
   // certain point, as the age increase, the size of the population starts
-  // declining sharply as you can see in this rough representation of the age
-  // distribution:
+  // declining sharply as you can see in this approximate representation of the
+  // age distribution:
   // |       ________         max age
   // |______/        \_________ |
   // |                          |\
@@ -171,7 +168,7 @@
   // but we cannot know that because we only have access to the year of the
   // dates (2019 and 1999 respectively). If we make sure that the minimal age is
   // at least 21, we are 100% sure that the user will be at least 20 years old
-  // when reporting demographics.
+  // when providing demographics.
   return user_age > kUserDemographicsMinAgeInYears;
 }
 
@@ -200,7 +197,7 @@
                        ? value->GetInt()
                        : kUserDemographicsGenderDefaultValue;
 
-  // Verify gender is not default.
+  // Verify that gender is not default.
   if (gender_int == kUserDemographicsGenderDefaultValue)
     return base::nullopt;
 
@@ -614,7 +611,7 @@
   }
 
   // Get user demographics. Only one error status code should be used to
-  // represent the case where demographics are invalid, see doc of
+  // represent the case where demographics are ineligible, see doc of
   // UserDemographicsStatus in components/sync/base/user_demographics.h for more
   // details.
 
@@ -638,9 +635,9 @@
         UserDemographicsStatus::kIneligibleDemographicsData);
   }
 
-  // Get the offset and do one last check that demographics are allowed.
+  // Get the offset and do one last check that demographics are eligible.
   int offset = GetBirthYearOffset(pref_service_);
-  if (!CanProvideDemographics(now, *birth_year, offset)) {
+  if (!HasEligibleBirthYear(now, *birth_year, offset)) {
     return UserDemographicsResult::ForStatus(
         UserDemographicsStatus::kIneligibleDemographicsData);
   }
diff --git a/components/sync/driver/data_type_controller.cc b/components/sync/driver/data_type_controller.cc
index 7e94d014..0a17a6b 100644
--- a/components/sync/driver/data_type_controller.cc
+++ b/components/sync/driver/data_type_controller.cc
@@ -45,8 +45,9 @@
   return "Invalid";
 }
 
-bool DataTypeController::ReadyForStart() const {
-  return true;
+DataTypeController::PreconditionState DataTypeController::GetPreconditionState()
+    const {
+  return PreconditionState::kPreconditionsMet;
 }
 
 bool DataTypeController::CalledOnValidThread() const {
diff --git a/components/sync/driver/data_type_controller.h b/components/sync/driver/data_type_controller.h
index b8b56a4..d2fca1b8 100644
--- a/components/sync/driver/data_type_controller.h
+++ b/components/sync/driver/data_type_controller.h
@@ -158,12 +158,15 @@
   // Unique model type for this data type controller.
   ModelType type() const { return type_; }
 
-  // Whether the DataTypeController is ready to start. This is useful if the
-  // datatype itself must make the decision about whether it should be enabled
-  // at all (and therefore whether the initial download of the sync data for
-  // the type should be performed).
-  // Returns true by default.
-  virtual bool ReadyForStart() const;
+  // Whether preconditions are met for the datatype to start. This is useful for
+  // example if the datatype depends on certain user preferences other than the
+  // ones for sync settings themselves.
+  enum class PreconditionState {
+    kPreconditionsMet,
+    kMustStopAndClearData,
+    kMustStopAndKeepData,
+  };
+  virtual PreconditionState GetPreconditionState() const;
 
   // Returns a ListValue representing all nodes for this data type through
   // |callback| on this thread. Can only be called if state() != NOT_RUNNING.
diff --git a/components/sync/driver/data_type_manager.h b/components/sync/driver/data_type_manager.h
index 00a18827..372fb2b5 100644
--- a/components/sync/driver/data_type_manager.h
+++ b/components/sync/driver/data_type_manager.h
@@ -76,7 +76,7 @@
   // controller has changed. If the controller is not ready any more, it will
   // stop |type|. Otherwise, it will trigger reconfiguration so that |type| gets
   // started again. No-op if the type's state didn't actually change.
-  virtual void ReadyForStartChanged(ModelType type) = 0;
+  virtual void DataTypePreconditionChanged(ModelType type) = 0;
 
   // Resets all data type error state.
   virtual void ResetDataTypeErrors() = 0;
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index be7132a1..702c5a8d 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -111,21 +111,34 @@
   ConfigureImpl(Intersection(desired_types, allowed_types), context);
 }
 
-void DataTypeManagerImpl::ReadyForStartChanged(ModelType type) {
-  if (!UpdateUnreadyTypeError(type)) {
+void DataTypeManagerImpl::DataTypePreconditionChanged(ModelType type) {
+  if (!UpdatePreconditionError(type)) {
     // Nothing changed.
     return;
   }
 
-  if (data_type_status_table_.GetUnreadyErrorTypes().Has(type)) {
-    model_association_manager_.StopDatatype(
-        type, DISABLE_SYNC,
-        SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
-                  "Data type is unready.", type));
-  } else if (last_requested_types_.Has(type)) {
-    // Only reconfigure if the type is both ready and desired. This will
-    // internally also update ready state of all other requested types.
-    ForceReconfiguration();
+  switch (controllers_->find(type)->second->GetPreconditionState()) {
+    case DataTypeController::PreconditionState::kPreconditionsMet:
+      if (last_requested_types_.Has(type)) {
+        // Only reconfigure if the type is both ready and desired. This will
+        // internally also update ready state of all other requested types.
+        ForceReconfiguration();
+      }
+      break;
+
+    case DataTypeController::PreconditionState::kMustStopAndClearData:
+      model_association_manager_.StopDatatype(
+          type, DISABLE_SYNC,
+          SyncError(FROM_HERE, syncer::SyncError::DATATYPE_POLICY_ERROR,
+                    "Datatype preconditions not met.", type));
+      break;
+
+    case DataTypeController::PreconditionState::kMustStopAndKeepData:
+      model_association_manager_.StopDatatype(
+          type, STOP_SYNC,
+          SyncError(FROM_HERE, syncer::SyncError::UNREADY_ERROR,
+                    "Data type is unready.", type));
+      break;
   }
 }
 
@@ -292,7 +305,7 @@
     data_type_status_table_.ResetCryptoErrors();
   }
 
-  UpdateUnreadyTypeErrors(last_requested_types_);
+  UpdatePreconditionErrors(last_requested_types_);
 
   last_enabled_types_ = GetEnabledTypes();
   last_restart_time_ = base::Time::Now();
@@ -360,37 +373,42 @@
   return result;
 }
 
-void DataTypeManagerImpl::UpdateUnreadyTypeErrors(
+void DataTypeManagerImpl::UpdatePreconditionErrors(
     const ModelTypeSet& desired_types) {
   for (ModelType type : desired_types) {
-    UpdateUnreadyTypeError(type);
+    UpdatePreconditionError(type);
   }
 }
 
-bool DataTypeManagerImpl::UpdateUnreadyTypeError(ModelType type) {
+bool DataTypeManagerImpl::UpdatePreconditionError(ModelType type) {
   const auto& iter = controllers_->find(type);
   if (iter == controllers_->end())
     return false;
 
-  const DataTypeController* dtc = iter->second.get();
-  bool unready_status =
-      data_type_status_table_.GetUnreadyErrorTypes().Has(type);
-  if (dtc->ReadyForStart() == (unready_status == false))
-    return false;
+  switch (iter->second->GetPreconditionState()) {
+    case DataTypeController::PreconditionState::kPreconditionsMet: {
+      const bool data_type_policy_error_changed =
+          data_type_status_table_.ResetDataTypePolicyErrorFor(type);
+      const bool unready_status_changed =
+          data_type_status_table_.ResetUnreadyErrorFor(type);
+      return data_type_policy_error_changed || unready_status_changed;
+    }
 
-  // Adjust data_type_status_table_ if unready state in it doesn't match
-  // DataTypeController::ReadyForStart().
-  if (dtc->ReadyForStart()) {
-    data_type_status_table_.ResetUnreadyErrorFor(type);
-  } else {
-    SyncError error(FROM_HERE, SyncError::UNREADY_ERROR,
-                    "Datatype not ready at config time.", type);
-    std::map<ModelType, SyncError> errors;
-    errors[type] = error;
-    data_type_status_table_.UpdateFailedDataTypes(errors);
+    case DataTypeController::PreconditionState::kMustStopAndClearData: {
+      return data_type_status_table_.UpdateFailedDataType(
+          type, SyncError(FROM_HERE, SyncError::DATATYPE_POLICY_ERROR,
+                          "Datatype preconditions not met.", type));
+    }
+
+    case DataTypeController::PreconditionState::kMustStopAndKeepData: {
+      return data_type_status_table_.UpdateFailedDataType(
+          type, SyncError(FROM_HERE, SyncError::UNREADY_ERROR,
+                          "Datatype not ready at config time.", type));
+    }
   }
 
-  return true;
+  NOTREACHED();
+  return false;
 }
 
 void DataTypeManagerImpl::ProcessReconfigure() {
@@ -683,9 +701,7 @@
   c_it->second->DeactivateDataType(configurer_);
 
   if (error.IsSet()) {
-    DataTypeStatusTable::TypeErrorMap failed_types;
-    failed_types[type] = error;
-    data_type_status_table_.UpdateFailedDataTypes(failed_types);
+    data_type_status_table_.UpdateFailedDataType(type, error);
 
     // Unrecoverable errors will shut down the entire backend, so no need to
     // reconfigure.
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index 96f8a58..99d4291 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -48,7 +48,7 @@
   // DataTypeManager interface.
   void Configure(ModelTypeSet desired_types,
                  const ConfigureContext& context) override;
-  void ReadyForStartChanged(ModelType type) override;
+  void DataTypePreconditionChanged(ModelType type) override;
   void ResetDataTypeErrors() override;
 
   // Needed only for backend migration.
@@ -136,14 +136,14 @@
   // high priority to low priority.
   TypeSetPriorityList PrioritizeTypes(const ModelTypeSet& types);
 
-  // Update unready state of types in data_type_status_table_ to match value of
-  // DataTypeController::ReadyForStart().
-  void UpdateUnreadyTypeErrors(const ModelTypeSet& desired_types);
+  // Update precondition state of types in data_type_status_table_ to match
+  // value of DataTypeController::GetPreconditionState().
+  void UpdatePreconditionErrors(const ModelTypeSet& desired_types);
 
-  // Update unready state for |type|, such that data_type_status_table_ matches
-  // DataTypeController::ReadyForStart(). Returns true if there was an actual
-  // change.
-  bool UpdateUnreadyTypeError(ModelType type);
+  // Update precondition state for |type|, such that data_type_status_table_
+  // matches DataTypeController::GetPreconditionState(). Returns true if there
+  // was an actual change.
+  bool UpdatePreconditionError(ModelType type);
 
   // Post a task to reconfigure when no downloading or association are running.
   void ProcessReconfigure();
diff --git a/components/sync/driver/data_type_manager_impl_unittest.cc b/components/sync/driver/data_type_manager_impl_unittest.cc
index 532af2b72..165a8f7 100644
--- a/components/sync/driver/data_type_manager_impl_unittest.cc
+++ b/components/sync/driver/data_type_manager_impl_unittest.cc
@@ -1283,11 +1283,12 @@
   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
 }
 
-TEST_F(SyncDataTypeManagerImplTest, UnreadyType) {
+TEST_F(SyncDataTypeManagerImplTest, FailingPreconditionKeepData) {
   AddController(BOOKMARKS);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Bookmarks is never started due to being unready.
+  // Bookmarks is never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1301,9 +1302,10 @@
   observer_.ResetExpectations();
 
   // Bookmarks should start normally now.
-  GetController(BOOKMARKS)->SetReadyForStart(true);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kPreconditionsMet);
   SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
 
   FinishDownload(ModelTypeSet(), ModelTypeSet());
@@ -1316,7 +1318,7 @@
 
   // Should do nothing.
   observer_.ResetExpectations();
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
 
   dtm_->Stop(STOP_SYNC);
   EXPECT_EQ(DataTypeManager::STOPPED, dtm_->state());
@@ -1327,9 +1329,10 @@
 // reconfiguration.
 TEST_F(SyncDataTypeManagerImplTest, UnreadyTypeResetReconfigure) {
   AddController(BOOKMARKS);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Bookmarks is never started due to being unready.
+  // Bookmarks is never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1353,9 +1356,10 @@
 
 TEST_F(SyncDataTypeManagerImplTest, UnreadyTypeLaterReady) {
   AddController(BOOKMARKS);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Bookmarks is never started due to being unready.
+  // Bookmarks is never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1369,8 +1373,9 @@
   ASSERT_EQ(0U, configurer_.activated_types().Size());
 
   // Bookmarks should start normally now.
-  GetController(BOOKMARKS)->SetReadyForStart(true);
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kPreconditionsMet);
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   EXPECT_NE(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
 
@@ -1388,10 +1393,13 @@
        MultipleUnreadyTypesLaterReadyAtTheSameTime) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
-  GetController(PREFERENCES)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
+  GetController(PREFERENCES)
+      ->SetPreconditionState(
+          DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Both types are never started due to being unready.
+  // Both types are never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1407,12 +1415,15 @@
   ASSERT_EQ(0U, configurer_.activated_types().Size());
 
   // Both types should start normally now.
-  GetController(BOOKMARKS)->SetReadyForStart(true);
-  GetController(PREFERENCES)->SetReadyForStart(true);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kPreconditionsMet);
+  GetController(PREFERENCES)
+      ->SetPreconditionState(
+          DataTypeController::PreconditionState::kPreconditionsMet);
 
   // Just triggering state change for one of them causes reconfiguration for all
   // that are ready to start (which is both BOOKMARKS and PREFERENCES).
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   EXPECT_NE(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   EXPECT_NE(DataTypeController::NOT_RUNNING,
@@ -1432,10 +1443,13 @@
 TEST_F(SyncDataTypeManagerImplTest, MultipleUnreadyTypesLaterOneOfThemReady) {
   AddController(BOOKMARKS);
   AddController(PREFERENCES);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
-  GetController(PREFERENCES)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
+  GetController(PREFERENCES)
+      ->SetPreconditionState(
+          DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Both types are never started due to being unready.
+  // Both types are never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1451,8 +1465,9 @@
   ASSERT_EQ(0U, configurer_.activated_types().Size());
 
   // Bookmarks should start normally now. Preferences should still not start.
-  GetController(BOOKMARKS)->SetReadyForStart(true);
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kPreconditionsMet);
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   EXPECT_NE(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
   EXPECT_EQ(DataTypeController::NOT_RUNNING,
@@ -1472,11 +1487,13 @@
   EXPECT_EQ(1U, configurer_.activated_types().Size());
 }
 
-TEST_F(SyncDataTypeManagerImplTest, NoOpReadyForStartChangedWhileStillUnready) {
+TEST_F(SyncDataTypeManagerImplTest,
+       NoOpDataTypePreconditionChangedWhileStillUnready) {
   AddController(BOOKMARKS);
-  GetController(BOOKMARKS)->SetReadyForStart(false);
+  GetController(BOOKMARKS)->SetPreconditionState(
+      DataTypeController::PreconditionState::kMustStopAndKeepData);
 
-  // Bookmarks is never started due to being unready.
+  // Bookmarks is never started due to failing preconditions.
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(
       DataTypeManager::OK,
@@ -1488,13 +1505,15 @@
   ASSERT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   ASSERT_EQ(0U, configurer_.activated_types().Size());
 
-  // Bookmarks is still unready so ReadyForStartChanged() should be ignored.
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  // Bookmarks is still unready so DataTypePreconditionChanged() should be
+  // ignored.
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   EXPECT_EQ(DataTypeController::NOT_RUNNING, GetController(BOOKMARKS)->state());
 }
 
-TEST_F(SyncDataTypeManagerImplTest, NoOpReadyForStartChangedWhileStillReady) {
+TEST_F(SyncDataTypeManagerImplTest,
+       NoOpDataTypePreconditionChangedWhileStillReady) {
   AddController(BOOKMARKS);
 
   SetConfigureStartExpectation();
@@ -1507,8 +1526,9 @@
   ASSERT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   ASSERT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
 
-  // Bookmarks is still ready so ReadyForStartChanged() should be ignored.
-  dtm_->ReadyForStartChanged(BOOKMARKS);
+  // Bookmarks is still ready so DataTypePreconditionChanged() should be
+  // ignored.
+  dtm_->DataTypePreconditionChanged(BOOKMARKS);
   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
   EXPECT_EQ(DataTypeController::RUNNING, GetController(BOOKMARKS)->state());
 }
diff --git a/components/sync/driver/data_type_manager_mock.h b/components/sync/driver/data_type_manager_mock.h
index 07cd55a..acd6ee3 100644
--- a/components/sync/driver/data_type_manager_mock.h
+++ b/components/sync/driver/data_type_manager_mock.h
@@ -17,7 +17,7 @@
   ~DataTypeManagerMock() override;
 
   MOCK_METHOD2(Configure, void(ModelTypeSet, const ConfigureContext&));
-  MOCK_METHOD1(ReadyForStartChanged, void(ModelType));
+  MOCK_METHOD1(DataTypePreconditionChanged, void(ModelType));
   MOCK_METHOD0(ResetDataTypeErrors, void());
   MOCK_METHOD1(PurgeForMigration, void(ModelTypeSet));
   MOCK_METHOD1(Stop, void(ShutdownReason));
diff --git a/components/sync/driver/data_type_status_table.cc b/components/sync/driver/data_type_status_table.cc
index 5b5f7ab2c..cbc75eb 100644
--- a/components/sync/driver/data_type_status_table.cc
+++ b/components/sync/driver/data_type_status_table.cc
@@ -33,33 +33,38 @@
   DVLOG(1) << "Setting " << errors.size() << " new failed types.";
 
   for (auto iter = errors.begin(); iter != errors.end(); ++iter) {
-    SyncError::ErrorType failure_type = iter->second.error_type();
-    switch (failure_type) {
-      case SyncError::UNSET:
-        NOTREACHED();
-        break;
-      case SyncError::UNRECOVERABLE_ERROR:
-        unrecoverable_errors_.insert(*iter);
-        break;
-      case SyncError::DATATYPE_ERROR:
-        data_type_errors_.insert(*iter);
-        break;
-      case SyncError::DATATYPE_POLICY_ERROR:
-        data_type_policy_errors_.insert(*iter);
-        break;
-      case SyncError::CRYPTO_ERROR:
-        crypto_errors_.insert(*iter);
-        break;
-      case SyncError::PERSISTENCE_ERROR:
-        persistence_errors_.insert(*iter);
-        break;
-      case SyncError::UNREADY_ERROR:
-        unready_errors_.insert(*iter);
-        break;
-    }
+    UpdateFailedDataType(iter->first, iter->second);
   }
 }
 
+bool DataTypeStatusTable::UpdateFailedDataType(ModelType type,
+                                               const SyncError& error) {
+  switch (error.error_type()) {
+    case SyncError::UNSET:
+      NOTREACHED();
+      break;
+    case SyncError::UNRECOVERABLE_ERROR:
+      return unrecoverable_errors_.emplace(type, error).second;
+      break;
+    case SyncError::DATATYPE_ERROR:
+      return data_type_errors_.emplace(type, error).second;
+      break;
+    case SyncError::DATATYPE_POLICY_ERROR:
+      return data_type_policy_errors_.emplace(type, error).second;
+    case SyncError::CRYPTO_ERROR:
+      return crypto_errors_.emplace(type, error).second;
+      break;
+    case SyncError::PERSISTENCE_ERROR:
+      return persistence_errors_.emplace(type, error).second;
+      break;
+    case SyncError::UNREADY_ERROR:
+      return unready_errors_.emplace(type, error).second;
+      break;
+  }
+  NOTREACHED();
+  return false;
+}
+
 void DataTypeStatusTable::Reset() {
   DVLOG(1) << "Resetting data type errors.";
   unrecoverable_errors_.clear();
diff --git a/components/sync/driver/data_type_status_table.h b/components/sync/driver/data_type_status_table.h
index 522daf0c..75d446e 100644
--- a/components/sync/driver/data_type_status_table.h
+++ b/components/sync/driver/data_type_status_table.h
@@ -28,6 +28,11 @@
   // error map based on their |error_type()|.
   void UpdateFailedDataTypes(const TypeErrorMap& errors);
 
+  // Update an individual failed datatype. The type will be added to its
+  // corresponding error map based on |error.error_type()|. Returns true if
+  // there was an actual change.
+  bool UpdateFailedDataType(ModelType type, const SyncError& error);
+
   // Resets the current set of data type errors.
   void Reset();
 
diff --git a/components/sync/driver/fake_data_type_controller.cc b/components/sync/driver/fake_data_type_controller.cc
index 0a2a24e0..09f5d071 100644
--- a/components/sync/driver/fake_data_type_controller.cc
+++ b/components/sync/driver/fake_data_type_controller.cc
@@ -22,7 +22,7 @@
                                   GROUP_PASSIVE),
       state_(NOT_RUNNING),
       model_load_delayed_(false),
-      ready_for_start_(true),
+      precondition_state_(PreconditionState::kPreconditionsMet),
       should_load_model_before_configure_(false),
       register_with_backend_call_count_(0),
       clear_metadata_call_count_(0) {}
@@ -127,8 +127,9 @@
   return state_;
 }
 
-bool FakeDataTypeController::ReadyForStart() const {
-  return ready_for_start_;
+DataTypeController::PreconditionState
+FakeDataTypeController::GetPreconditionState() const {
+  return precondition_state_;
 }
 
 void FakeDataTypeController::SetDelayModelLoad() {
@@ -147,8 +148,8 @@
   model_load_callback_.Run(type(), load_error_);
 }
 
-void FakeDataTypeController::SetReadyForStart(bool ready) {
-  ready_for_start_ = ready;
+void FakeDataTypeController::SetPreconditionState(PreconditionState state) {
+  precondition_state_ = state;
 }
 
 void FakeDataTypeController::SetShouldLoadModelBeforeConfigure(bool value) {
diff --git a/components/sync/driver/fake_data_type_controller.h b/components/sync/driver/fake_data_type_controller.h
index 8e07ef1c..7a7d7d5 100644
--- a/components/sync/driver/fake_data_type_controller.h
+++ b/components/sync/driver/fake_data_type_controller.h
@@ -37,7 +37,7 @@
   void Stop(ShutdownReason shutdown_reason) override;
   ChangeProcessor* GetChangeProcessor() const override;
   State state() const override;
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
   std::unique_ptr<DataTypeErrorHandler> CreateErrorHandler() override;
 
   void FinishStart(ConfigureResult result);
@@ -48,7 +48,7 @@
 
   void SimulateModelLoadFinishing();
 
-  void SetReadyForStart(bool ready);
+  void SetPreconditionState(PreconditionState state);
 
   void SetShouldLoadModelBeforeConfigure(bool value);
 
@@ -64,7 +64,7 @@
   StartCallback last_start_callback_;
   ModelLoadCallback model_load_callback_;
   SyncError load_error_;
-  bool ready_for_start_;
+  PreconditionState precondition_state_;
   bool should_load_model_before_configure_;
   int register_with_backend_call_count_;
   int clear_metadata_call_count_;
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index b34929a..0db3701 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -98,7 +98,7 @@
   return user_share_.get();
 }
 
-void FakeSyncService::ReadyForStartChanged(ModelType type) {}
+void FakeSyncService::DataTypePreconditionChanged(ModelType type) {}
 
 syncer::SyncTokenStatus FakeSyncService::GetSyncTokenStatusForDebugging()
     const {
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index 92821c2..d0cc5520 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -47,7 +47,7 @@
   base::Time GetAuthErrorTime() const override;
   bool RequiresClientUpgrade() const override;
   UserShare* GetUserShare() const override;
-  void ReadyForStartChanged(syncer::ModelType type) override;
+  void DataTypePreconditionChanged(syncer::ModelType type) override;
   SyncTokenStatus GetSyncTokenStatusForDebugging() const override;
   bool QueryDetailedSyncStatusForDebugging(SyncStatus* result) const override;
   base::Time GetLastSyncedTimeForDebugging() const override;
diff --git a/components/sync/driver/mock_sync_service.h b/components/sync/driver/mock_sync_service.h
index 2c278525..e69bd2a 100644
--- a/components/sync/driver/mock_sync_service.h
+++ b/components/sync/driver/mock_sync_service.h
@@ -52,7 +52,7 @@
   MOCK_METHOD0(StopAndClear, void());
   MOCK_METHOD1(OnDataTypeRequestsSyncStartup, void(ModelType type));
   MOCK_METHOD1(TriggerRefresh, void(const ModelTypeSet& types));
-  MOCK_METHOD1(ReadyForStartChanged, void(syncer::ModelType type));
+  MOCK_METHOD1(DataTypePreconditionChanged, void(syncer::ModelType type));
   MOCK_METHOD1(SetInvalidationsForSessionsEnabled, void(bool enabled));
   MOCK_METHOD1(GetUserDemographics, UserDemographicsResult(base::Time now));
 
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc
index 7a25f186b..8304004 100644
--- a/components/sync/driver/profile_sync_service.cc
+++ b/components/sync/driver/profile_sync_service.cc
@@ -776,11 +776,11 @@
   sync_prefs_.ClearDirectoryConsistencyPreferences();
 }
 
-void ProfileSyncService::ReadyForStartChanged(ModelType type) {
+void ProfileSyncService::DataTypePreconditionChanged(ModelType type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!engine_ || !engine_->IsInitialized() || !data_type_manager_)
     return;
-  data_type_manager_->ReadyForStartChanged(type);
+  data_type_manager_->DataTypePreconditionChanged(type);
 }
 
 void ProfileSyncService::UpdateEngineInitUMA(bool success) const {
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h
index 2e17895..aeac0a9 100644
--- a/components/sync/driver/profile_sync_service.h
+++ b/components/sync/driver/profile_sync_service.h
@@ -132,7 +132,7 @@
   void StopAndClear() override;
   void OnDataTypeRequestsSyncStartup(ModelType type) override;
   void TriggerRefresh(const ModelTypeSet& types) override;
-  void ReadyForStartChanged(ModelType type) override;
+  void DataTypePreconditionChanged(ModelType type) override;
   void SetInvalidationsForSessionsEnabled(bool enabled) override;
   UserDemographicsResult GetUserDemographics(base::Time now) override;
   void AddObserver(SyncServiceObserver* observer) override;
diff --git a/components/sync/driver/profile_sync_service_unittest.cc b/components/sync/driver/profile_sync_service_unittest.cc
index 8ff4aa4..3776749 100644
--- a/components/sync/driver/profile_sync_service_unittest.cc
+++ b/components/sync/driver/profile_sync_service_unittest.cc
@@ -70,7 +70,7 @@
     configure_called_.Run(context.reason);
   }
 
-  void ReadyForStartChanged(ModelType type) override {}
+  void DataTypePreconditionChanged(ModelType type) override {}
   void ResetDataTypeErrors() override {}
   void PurgeForMigration(ModelTypeSet undesired_types) override {}
   void Stop(ShutdownReason reason) override {}
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index 4cce95b..caf8b46 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -332,11 +332,13 @@
   // from the sync server. Used by tests and debug UI (sync-internals).
   virtual void TriggerRefresh(const ModelTypeSet& types) = 0;
 
-  // Informs the data type manager that the ready-for-start status of a
-  // controller has changed. If the controller is not ready any more, it will
-  // stop |type|. Otherwise, it will trigger reconfiguration so that |type| gets
-  // started again. No-op if the type's state didn't actually change.
-  virtual void ReadyForStartChanged(ModelType type) = 0;
+  // Informs the data type manager that the preconditions for a controller have
+  // changed. If preconditions are NOT met, the datatype will be stopped
+  // according to the metadata clearing policy returned by the controller's
+  // GetPreconditionState(). Otherwise, if preconditions are newly met,
+  // reconfiguration will be triggered so that |type| gets started again. No-op
+  // if the type's state didn't actually change.
+  virtual void DataTypePreconditionChanged(ModelType type) = 0;
 
   // Enables/disables invalidations for session sync related datatypes.
   // The session sync generates a lot of changes, which results in many
diff --git a/components/sync/driver/test_sync_service.cc b/components/sync/driver/test_sync_service.cc
index ea40f6f..20970c5 100644
--- a/components/sync/driver/test_sync_service.cc
+++ b/components/sync/driver/test_sync_service.cc
@@ -193,7 +193,7 @@
 
 void TestSyncService::TriggerRefresh(const ModelTypeSet& types) {}
 
-void TestSyncService::ReadyForStartChanged(ModelType type) {}
+void TestSyncService::DataTypePreconditionChanged(ModelType type) {}
 
 void TestSyncService::AddObserver(SyncServiceObserver* observer) {
   observers_.AddObserver(observer);
diff --git a/components/sync/driver/test_sync_service.h b/components/sync/driver/test_sync_service.h
index 227ef86..e581da5 100644
--- a/components/sync/driver/test_sync_service.h
+++ b/components/sync/driver/test_sync_service.h
@@ -75,7 +75,7 @@
   void StopAndClear() override;
   void OnDataTypeRequestsSyncStartup(ModelType type) override;
   void TriggerRefresh(const ModelTypeSet& types) override;
-  void ReadyForStartChanged(syncer::ModelType type) override;
+  void DataTypePreconditionChanged(syncer::ModelType type) override;
 
   void AddObserver(SyncServiceObserver* observer) override;
   void RemoveObserver(SyncServiceObserver* observer) override;
diff --git a/components/sync_sessions/session_model_type_controller.cc b/components/sync_sessions/session_model_type_controller.cc
index 1054648a..64ae9a53 100644
--- a/components/sync_sessions/session_model_type_controller.cc
+++ b/components/sync_sessions/session_model_type_controller.cc
@@ -45,22 +45,26 @@
   sync_service_->RemoveObserver(this);
 }
 
-bool SessionModelTypeController::ReadyForStart() const {
+syncer::DataTypeController::PreconditionState
+SessionModelTypeController::GetPreconditionState() const {
   DCHECK(CalledOnValidThread());
-  return !pref_service_->GetBoolean(history_disabled_pref_name_) &&
-         !(syncer::IsWebSignout(sync_service_->GetAuthError()) &&
-           base::FeatureList::IsEnabled(kStopSessionsIfSyncPaused));
+  bool preconditions_met =
+      !pref_service_->GetBoolean(history_disabled_pref_name_) &&
+      !(syncer::IsWebSignout(sync_service_->GetAuthError()) &&
+        base::FeatureList::IsEnabled(kStopSessionsIfSyncPaused));
+  return preconditions_met ? PreconditionState::kPreconditionsMet
+                           : PreconditionState::kMustStopAndKeepData;
 }
 
 void SessionModelTypeController::OnStateChanged(syncer::SyncService* sync) {
   DCHECK(CalledOnValidThread());
   // Most of these calls will be no-ops but SyncService handles that just fine.
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 void SessionModelTypeController::OnSavingBrowserHistoryPrefChanged() {
   DCHECK(CalledOnValidThread());
-  sync_service_->ReadyForStartChanged(type());
+  sync_service_->DataTypePreconditionChanged(type());
 }
 
 }  // namespace sync_sessions
diff --git a/components/sync_sessions/session_model_type_controller.h b/components/sync_sessions/session_model_type_controller.h
index b5a77d5..13c0797 100644
--- a/components/sync_sessions/session_model_type_controller.h
+++ b/components/sync_sessions/session_model_type_controller.h
@@ -33,7 +33,7 @@
   ~SessionModelTypeController() override;
 
   // DataTypeController overrides.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
   // syncer::SyncServiceObserver implementation.
   void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/components/sync_user_events/user_event_model_type_controller.cc b/components/sync_user_events/user_event_model_type_controller.cc
index b9d8ef02..5c22457cd 100644
--- a/components/sync_user_events/user_event_model_type_controller.cc
+++ b/components/sync_user_events/user_event_model_type_controller.cc
@@ -27,16 +27,22 @@
   sync_service_->RemoveObserver(this);
 }
 
-bool UserEventModelTypeController::ReadyForStart() const {
+DataTypeController::PreconditionState
+UserEventModelTypeController::GetPreconditionState() const {
+  if (sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase()) {
+    return PreconditionState::kMustStopAndClearData;
+  }
   // TODO(crbug.com/906995): Remove the syncer::IsWebSignout() check once we
   // stop sync in this state. Also remove the "+google_apis/gaia" include
   // dependency and the "//google_apis" build dependency of sync_user_events.
-  return !sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase() &&
-         !syncer::IsWebSignout(sync_service_->GetAuthError());
+  if (syncer::IsWebSignout(sync_service_->GetAuthError())) {
+    return PreconditionState::kMustStopAndClearData;
+  }
+  return PreconditionState::kPreconditionsMet;
 }
 
 void UserEventModelTypeController::OnStateChanged(syncer::SyncService* sync) {
-  sync->ReadyForStartChanged(type());
+  sync->DataTypePreconditionChanged(type());
 }
 
 }  // namespace syncer
diff --git a/components/sync_user_events/user_event_model_type_controller.h b/components/sync_user_events/user_event_model_type_controller.h
index b162b6b..fd4d796 100644
--- a/components/sync_user_events/user_event_model_type_controller.h
+++ b/components/sync_user_events/user_event_model_type_controller.h
@@ -25,7 +25,7 @@
   ~UserEventModelTypeController() override;
 
   // syncer::DataTypeController implementation.
-  bool ReadyForStart() const override;
+  PreconditionState GetPreconditionState() const override;
 
   // syncer::SyncServiceObserver implementation.
   void OnStateChanged(syncer::SyncService* sync) override;
diff --git a/components/visitedlink/test/visitedlink_unittest.cc b/components/visitedlink/test/visitedlink_unittest.cc
index 3dfccc2c..6f0652e 100644
--- a/components/visitedlink/test/visitedlink_unittest.cc
+++ b/components/visitedlink/test/visitedlink_unittest.cc
@@ -653,9 +653,9 @@
     RenderViewHostTestHarness::TearDown();
   }
 
-  content::BrowserContext* CreateBrowserContext() override {
-    content::BrowserContext* context = new content::TestBrowserContext();
-    CreateVisitedLinkMaster(context);
+  std::unique_ptr<content::BrowserContext> CreateBrowserContext() override {
+    auto context = std::make_unique<content::TestBrowserContext>();
+    CreateVisitedLinkMaster(context.get());
     return context;
   }
 
@@ -848,10 +848,10 @@
 
 class VisitedLinkCompletelyResetEventTest : public VisitedLinkEventsTest {
  public:
-  content::BrowserContext* CreateBrowserContext() override {
-    content::BrowserContext* context = new content::TestBrowserContext();
-    CreateVisitedLinkFile(context);
-    CreateVisitedLinkMaster(context);
+  std::unique_ptr<content::BrowserContext> CreateBrowserContext() override {
+    auto context = std::make_unique<content::TestBrowserContext>();
+    CreateVisitedLinkFile(context.get());
+    CreateVisitedLinkMaster(context.get());
     return context;
   }
 
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
index 57c602e..be2a106 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc
@@ -10,6 +10,7 @@
 #include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.h"
 #include "components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h"
 #include "mojo/core/embedder/embedder.h"
+#include "testing/libfuzzer/libfuzzer_exports.h"
 #include "testing/libfuzzer/proto/lpm_interface.h"
 
 #include "components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.pb.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ace93cb..97a3a70e 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1852,6 +1852,8 @@
     "web_package/bundled_exchanges_reader.h",
     "web_package/bundled_exchanges_source.cc",
     "web_package/bundled_exchanges_source.h",
+    "web_package/bundled_exchanges_url_loader_factory.cc",
+    "web_package/bundled_exchanges_url_loader_factory.h",
     "web_package/prefetched_signed_exchange_cache.cc",
     "web_package/prefetched_signed_exchange_cache.h",
     "web_package/prefetched_signed_exchange_cache_adapter.cc",
diff --git a/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
index ac1777af..efb4c7b 100644
--- a/content/browser/accessibility/accessibility_auralinux_browsertest.cc
+++ b/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -1020,4 +1020,80 @@
   g_object_unref(section);
 }
 
+IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
+                       TestFindInPageEvents) {
+  LoadInitialAccessibilityTreeFromHtml(
+      R"HTML(<!DOCTYPE html>
+      <html>
+      <body>
+      <div contenteditable="true">
+        Sufficiently long div content
+      </div>
+      <div contenteditable="true">
+        Second sufficiently long div content
+      </div>
+      </body>
+      </html>)HTML");
+
+  // Retrieve the AtkObject interface for the document node.
+  AtkObject* document = GetRendererAccessible();
+  ASSERT_TRUE(ATK_IS_COMPONENT(document));
+
+  AtkObject* div1 = atk_object_ref_accessible_child(document, 0);
+  AtkObject* div2 = atk_object_ref_accessible_child(document, 1);
+  EXPECT_NE(div1, nullptr);
+  EXPECT_NE(div2, nullptr);
+
+  auto selection_callback =
+      G_CALLBACK(+[](AtkText*, int* count) { *count += 1; });
+  int selection_changed_signals = 0;
+  g_signal_connect(div1, "text-selection-changed", selection_callback,
+                   &selection_changed_signals);
+  g_signal_connect(div2, "text-selection-changed", selection_callback,
+                   &selection_changed_signals);
+
+  auto caret_callback = G_CALLBACK(
+      +[](AtkText*, int new_position, int* caret_position_from_event) {
+        *caret_position_from_event = new_position;
+      });
+  int caret_position_from_event = -1;
+  g_signal_connect(div1, "text-caret-moved", caret_callback,
+                   &caret_position_from_event);
+  g_signal_connect(div2, "text-caret-moved", caret_callback,
+                   &caret_position_from_event);
+
+  AccessibilityNotificationWaiter waiter(
+      shell()->web_contents(), ui::kAXModeComplete,
+      ax::mojom::Event::kTextSelectionChanged);
+  atk_text_set_caret_offset(ATK_TEXT(div1), 4);
+  waiter.WaitForNotification();
+
+  ASSERT_EQ(atk_text_get_caret_offset(ATK_TEXT(div1)), 4);
+  ASSERT_EQ(caret_position_from_event, 4);
+  ASSERT_EQ(selection_changed_signals, 0);
+
+  caret_position_from_event = -1;
+  selection_changed_signals = 0;
+  auto* node = static_cast<ui::AXPlatformNodeAuraLinux*>(
+      ui::AXPlatformNode::FromNativeViewAccessible(div2));
+  node->ActivateFindInPageResult(1, 3);
+
+  ASSERT_EQ(selection_changed_signals, 1);
+  ASSERT_EQ(caret_position_from_event, 3);
+  ASSERT_EQ(atk_text_get_caret_offset(ATK_TEXT(div2)), 3);
+  ASSERT_EQ(atk_text_get_caret_offset(ATK_TEXT(div1)), 4);
+
+  caret_position_from_event = -1;
+  selection_changed_signals = 0;
+  node->TerminateFindInPage();
+
+  ASSERT_EQ(selection_changed_signals, 0);
+  ASSERT_EQ(caret_position_from_event, -1);
+  ASSERT_EQ(atk_text_get_caret_offset(ATK_TEXT(div2)), -1);
+  ASSERT_EQ(atk_text_get_caret_offset(ATK_TEXT(div1)), 4);
+
+  g_object_unref(div1);
+  g_object_unref(div2);
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 830013d..a65464b 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -287,12 +287,12 @@
 
   // Called when a new find in page result is received. We hold on to this
   // information and don't activate it until the user requests it.
-  void OnFindInPageResult(int request_id,
-                          int match_index,
-                          int start_id,
-                          int start_offset,
-                          int end_id,
-                          int end_offset);
+  virtual void OnFindInPageResult(int request_id,
+                                  int match_index,
+                                  int start_id,
+                                  int start_offset,
+                                  int end_id,
+                                  int end_offset);
 
   // This is called when the user has committed to a find in page query,
   // e.g. by pressing enter or tapping on the next / previous result buttons.
@@ -302,6 +302,10 @@
   // when OnFindInPageResult is called.
   void ActivateFindInPageResult(int request_id);
 
+  // This is called when the user finishes a find in page query and all
+  // highlighted matches are deactivated.
+  virtual void OnFindInPageTermination() {}
+
 #if defined(OS_WIN)
   BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
 #endif
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 2d93a1d..8d7b38ee 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -293,4 +293,31 @@
   }
 }
 
+void BrowserAccessibilityManagerAuraLinux::OnFindInPageResult(int request_id,
+                                                              int match_index,
+                                                              int start_id,
+                                                              int start_offset,
+                                                              int end_id,
+                                                              int end_offset) {
+  BrowserAccessibility* node = GetFromID(start_id);
+  if (!node)
+    return;
+  ui::AXPlatformNodeAuraLinux* platform_node =
+      ToBrowserAccessibilityAuraLinux(node)->GetNode();
+
+  // TODO(accessibility): We should support selections that span multiple
+  // elements, but for now if we see a result that spans multiple elements,
+  // just activate until the end of the node.
+  if (end_id != start_id)
+    end_offset = platform_node->GetHypertext().size();
+
+  platform_node->ActivateFindInPageResult(start_offset, end_offset);
+}
+
+void BrowserAccessibilityManagerAuraLinux::OnFindInPageTermination() {
+  static_cast<BrowserAccessibilityAuraLinux*>(GetRoot())
+      ->GetNode()
+      ->TerminateFindInPage();
+}
+
 }  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index 3826fd53..d6b0547 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -39,6 +39,13 @@
   void FireNameChangedEvent(BrowserAccessibility* node);
   void FireDescriptionChangedEvent(BrowserAccessibility* node);
   void FireSubtreeCreatedEvent(BrowserAccessibility* node);
+  void OnFindInPageResult(int request_id,
+                          int match_index,
+                          int start_id,
+                          int start_offset,
+                          int end_id,
+                          int end_offset) override;
+  void OnFindInPageTermination() override;
 
  protected:
   // AXTreeObserver methods.
diff --git a/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc b/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
index 61e3563d..515fcf7 100644
--- a/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
+++ b/content/browser/browsing_data/browsing_data_filter_builder_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/optional.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_deletion_info.h"
 #include "services/network/cookie_manager.h"
@@ -60,8 +61,9 @@
   std::string cookie_line = "A=2";
   GURL test_url(test_case.url);
   EXPECT_TRUE(test_url.is_valid()) << test_case.url;
-  std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
-      test_url, cookie_line, base::Time::Now(), net::CookieOptions());
+  std::unique_ptr<net::CanonicalCookie> cookie =
+      net::CanonicalCookie::Create(test_url, cookie_line, base::Time::Now(),
+                                   base::nullopt /* server_time */);
   EXPECT_TRUE(cookie) << cookie_line << " from " << test_case.url
                       << " is not a valid cookie";
   if (cookie)
@@ -69,22 +71,25 @@
         << cookie->DebugString();
 
   cookie_line = std::string("A=2;domain=") + test_url.host();
-  cookie = net::CanonicalCookie::Create(
-      test_url, cookie_line, base::Time::Now(), net::CookieOptions());
+  cookie =
+      net::CanonicalCookie::Create(test_url, cookie_line, base::Time::Now(),
+                                   base::nullopt /* server_time */);
   if (cookie)
     EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
         << cookie->DebugString();
 
   cookie_line = std::string("A=2; HttpOnly;") + test_url.host();
-  cookie = net::CanonicalCookie::Create(
-      test_url, cookie_line, base::Time::Now(), net::CookieOptions());
+  cookie =
+      net::CanonicalCookie::Create(test_url, cookie_line, base::Time::Now(),
+                                   base::nullopt /* server_time */);
   if (cookie)
     EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
         << cookie->DebugString();
 
   cookie_line = std::string("A=2; HttpOnly; Secure;") + test_url.host();
-  cookie = net::CanonicalCookie::Create(
-      test_url, cookie_line, base::Time::Now(), net::CookieOptions());
+  cookie =
+      net::CanonicalCookie::Create(test_url, cookie_line, base::Time::Now(),
+                                   base::nullopt /* server_time */);
   if (cookie)
     EXPECT_EQ(test_case.should_match, delete_info.Matches(*cookie))
         << cookie->DebugString();
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 cf1c327..dec1ad1 100644
--- a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
+++ b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -223,13 +223,12 @@
     network::mojom::CookieManager* cookie_manager =
         storage_partition()->GetCookieManagerForBrowserProcess();
 
-    net::CookieOptions options;
-    std::unique_ptr<net::CanonicalCookie> cookie(
-        net::CanonicalCookie::Create(url, "A=1", base::Time::Now(), options));
+    std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
+        url, "A=1", base::Time::Now(), base::nullopt /* server_time */));
 
     base::RunLoop run_loop;
     cookie_manager->SetCanonicalCookie(
-        *cookie, url.scheme(), options,
+        *cookie, url.scheme(), net::CookieOptions(),
         base::BindOnce(&ClearSiteDataHandlerBrowserTest::AddCookieCallback,
                        run_loop.QuitClosure()));
     run_loop.Run();
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc
index 37da4c9f..d4621c2 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -1039,9 +1039,23 @@
     return;
   }
 
+  std::vector<std::unique_ptr<net::CanonicalCookie>> cookies;
+  base::Time response_date;
+  base::Optional<base::Time> server_time = base::nullopt;
+  if (headers.GetDateValue(&response_date))
+    server_time = base::make_optional(response_date);
+  base::Time now = base::Time::Now();
+
   const base::StringPiece name("Set-Cookie");
   std::string cookie_line;
   size_t iter = 0;
+  while (headers.EnumerateHeader(&iter, name, &cookie_line)) {
+    std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
+        create_loader_params_->request.url, cookie_line, now, server_time);
+    if (cookie)
+      cookies.emplace_back(std::move(cookie));
+  }
+
   net::CookieOptions options;
   options.set_include_httponly();
   options.set_same_site_cookie_context(
@@ -1050,17 +1064,7 @@
           create_loader_params_->request.site_for_cookies,
           create_loader_params_->request.request_initiator));
 
-  std::vector<std::unique_ptr<net::CanonicalCookie>> cookies;
-  base::Time response_date;
-  if (headers.GetDateValue(&response_date))
-    options.set_server_time(response_date);
-  base::Time now = base::Time::Now();
-  while (headers.EnumerateHeader(&iter, name, &cookie_line)) {
-    std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
-        create_loader_params_->request.url, cookie_line, now, options);
-    if (cookie)
-      cookies.emplace_back(std::move(cookie));
-  }
+  // |this| might be deleted here if |cookies| is empty!
   auto on_cookie_set = base::BindRepeating(
       [](base::RepeatingClosure closure,
          net::CanonicalCookie::CookieInclusionStatus) { closure.Run(); },
diff --git a/content/browser/download/save_package_unittest.cc b/content/browser/download/save_package_unittest.cc
index 45fb3d3..d626e35 100644
--- a/content/browser/download/save_package_unittest.cc
+++ b/content/browser/download/save_package_unittest.cc
@@ -16,6 +16,7 @@
 #include "build/build_config.h"
 #include "content/browser/download/save_file_manager.h"
 #include "content/browser/download/save_package.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/common/url_constants.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
@@ -103,7 +104,7 @@
         temp_dir_.GetPath().Append(long_file_name + FPL("_files")));
   }
 
-  BrowserContext* CreateBrowserContext() override {
+  std::unique_ptr<BrowserContext> CreateBrowserContext() override {
     // Initialize the SaveFileManager instance which we will use for the tests.
     save_file_manager_ = new SaveFileManager();
     return RenderViewHostImplTestHarness::CreateBrowserContext();
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 387511c..76341f9 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -2148,6 +2148,7 @@
     frame_tree_node()->render_manager()->RestoreFromBackForwardCache(
         std::move(rfh_restored_from_back_forward_cache_));
 
+    // Commit the restored frame.
     // Note that this will delete the NavigationRequest.
     render_frame_host()->DidCommitBackForwardCacheNavigation(
         this, MakeDidCommitProvisionalLoadParamsForBFCache());
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 57a65485..904a7f61 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1455,6 +1455,8 @@
                         OnAccessibilityLocationChanges)
     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_FindInPageResult,
                         OnAccessibilityFindInPageResult)
+    IPC_MESSAGE_HANDLER(AccessibilityHostMsg_FindInPageTermination,
+                        OnAccessibilityFindInPageTermination)
     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_ChildFrameHitTestResult,
                         OnAccessibilityChildFrameHitTestResult)
     IPC_MESSAGE_HANDLER(AccessibilityHostMsg_SnapshotResponse,
@@ -2376,6 +2378,9 @@
   DidCommitNavigationInternal(std::move(owned_request), validated_params.get(),
                               /*is_same_document_navigation=*/false);
 
+  // Now that the restored frame has been committed, unfreeze it.
+  frame_tree_node()->render_manager()->UnfreezeCurrentFrameHost();
+
   // The page is already loaded since it came from the cache, so fire the stop
   // loading event.
   OnDidStopLoading();
@@ -3450,6 +3455,16 @@
   }
 }
 
+void RenderFrameHostImpl::OnAccessibilityFindInPageTermination() {
+  ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
+  if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
+    BrowserAccessibilityManager* manager =
+        GetOrCreateBrowserAccessibilityManager();
+    if (manager)
+      manager->OnFindInPageTermination();
+  }
+}
+
 void RenderFrameHostImpl::OnAccessibilityChildFrameHitTestResult(
     int action_request_id,
     const gfx::Point& point,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index a1d0a099..b877b7ba 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1201,6 +1201,7 @@
       const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
   void OnAccessibilityFindInPageResult(
       const AccessibilityHostMsg_FindInPageResultParams& params);
+  void OnAccessibilityFindInPageTermination();
   void OnAccessibilityChildFrameHitTestResult(
       int action_request_id,
       const gfx::Point& point,
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index b795fea..4ccc201 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -580,15 +580,15 @@
 
 void RenderFrameHostManager::RestoreFromBackForwardCache(
     std::unique_ptr<RenderFrameHostImpl> rfh) {
-  rfh->GetProcess()->AddPendingView();  // Matched in CommitPending().
-  // Save as a temp variable to check later to match |current_frame_host()|.
-  RenderFrameHostImpl* tmp_rfh = rfh.get();
+  // Matched in CommitPending().
+  rfh->GetProcess()->AddPendingView();
 
-  // Make the frame restored from the back-forward cache the current frame.
-  CommitPending(std::move(rfh));
-  DCHECK_EQ(tmp_rfh, current_frame_host());
+  // speculative_render_frame_host_ will be committed during
+  // CommitPendingIfNecessary.
+  speculative_render_frame_host_ = std::move(rfh);
+}
 
-  // Resume the page after CommitPending.
+void RenderFrameHostManager::UnfreezeCurrentFrameHost() {
   delegate_->GetControllerForRenderManager().back_forward_cache().Resume(
       current_frame_host());
 }
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index dac4f71e..cab15ebd 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -319,6 +319,11 @@
   void RestoreFromBackForwardCache(std::unique_ptr<RenderFrameHostImpl>);
   void EvictFromBackForwardCache(RenderFrameHostImpl*);
 
+  // BackForwardCache:
+  // Unfreezes the current frame host. This is called after committing a
+  // navigation to a frame that was restored from the back-forward cache.
+  void UnfreezeCurrentFrameHost();
+
   // Deletes any proxy hosts associated with this node. Used during destruction
   // of WebContentsImpl.
   void ResetProxyHosts();
@@ -819,6 +824,10 @@
   // behavior. The speculative RenderFrameHost might be discarded later on if
   // the final URL's SiteInstance isn't compatible with the one used to create
   // it.
+  //
+  // This is also used by the BackForwardCache, which
+  // sets speculative_render_frame_host_ to the restored frame before
+  // committing.
   std::unique_ptr<RenderFrameHostImpl> speculative_render_frame_host_;
 
   // This callback is used when attaching an inner Delegate to |delegate_|
diff --git a/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
index c3af2f1..5eeab65 100644
--- a/content/browser/frame_host/render_frame_message_filter_browsertest.cc
+++ b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -60,7 +60,7 @@
                      const GURL& url,
                      const std::string& cookie_line) {
   auto cookie_obj = net::CanonicalCookie::Create(
-      url, cookie_line, base::Time::Now(), net::CookieOptions());
+      url, cookie_line, base::Time::Now(), base::nullopt /* server_time */);
 
   base::RunLoop run_loop;
   BrowserContext::GetDefaultStoragePartition(tab->GetBrowserContext())
diff --git a/content/browser/renderer_host/input/autoscroll_browsertest.cc b/content/browser/renderer_host/input/autoscroll_browsertest.cc
index c7339bc..5ec783e 100644
--- a/content/browser/renderer_host/input/autoscroll_browsertest.cc
+++ b/content/browser/renderer_host/input/autoscroll_browsertest.cc
@@ -104,7 +104,7 @@
 
   void LoadURL(const std::string& page_data) {
     const GURL data_url("data:text/html," + page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
diff --git a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
index d146cd3f..8c577c87 100644
--- a/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
+++ b/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -81,7 +81,7 @@
  protected:
   void LoadURL() {
     const GURL data_url(kCompositedScrollingDataURL);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     HitTestRegionObserver observer(GetWidgetHost()->GetFrameSinkId());
diff --git a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
index 910af14..c12f815 100644
--- a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
+++ b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
@@ -126,7 +126,7 @@
  protected:
   void LoadURL(const char* page_data) {
     const GURL data_url(page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
diff --git a/content/browser/renderer_host/input/fling_browsertest.cc b/content/browser/renderer_host/input/fling_browsertest.cc
index 01eb36f..b581232 100644
--- a/content/browser/renderer_host/input/fling_browsertest.cc
+++ b/content/browser/renderer_host/input/fling_browsertest.cc
@@ -84,7 +84,7 @@
 
   void LoadURL(const std::string& page_data) {
     const GURL data_url("data:text/html," + page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
@@ -346,7 +346,7 @@
   // Navigate to a second page with the same domain.
   GURL second_url(
       embedded_test_server()->GetURL("a.com", "/scrollable_page.html"));
-  NavigateToURL(shell(), second_url);
+  EXPECT_TRUE(NavigateToURL(shell(), second_url));
   SynchronizeThreads();
 
   // Wait for 100ms. Then check that the second page has not scrolled.
diff --git a/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc b/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc
index cbae86d..a32553da 100644
--- a/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc
+++ b/content/browser/renderer_host/input/interaction_mq_dynamic_browsertest.cc
@@ -41,7 +41,7 @@
   GURL test_url = GetTestUrl("", "interaction-mq-dynamic.html");
   const base::string16 kSuccessTitle(base::ASCIIToUTF16("SUCCESS"));
   TitleWatcher title_watcher(shell()->web_contents(), kSuccessTitle);
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   ui::SetAvailablePointerAndHoverTypesForTesting(ui::POINTER_TYPE_COARSE,
                                                  ui::HOVER_TYPE_HOVER);
diff --git a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
index 70a04eb..d7ce8c9 100644
--- a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
+++ b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
@@ -89,7 +89,7 @@
  protected:
   void LoadURL(const char* page_data) {
     const GURL data_url(page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index 929ed1c..23caf0a 100644
--- a/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -177,7 +177,7 @@
  protected:
   void LoadURL() {
     const GURL data_url(kDataURL);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
diff --git a/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
index 876685f..61e21a6 100644
--- a/content/browser/renderer_host/input/scroll_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -102,7 +102,7 @@
 
   void LoadURL() {
     const GURL data_url(kDataURL);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
diff --git a/content/browser/renderer_host/input/synthetic_input_browsertest.cc b/content/browser/renderer_host/input/synthetic_input_browsertest.cc
index 96855c9..3756534 100644
--- a/content/browser/renderer_host/input/synthetic_input_browsertest.cc
+++ b/content/browser/renderer_host/input/synthetic_input_browsertest.cc
@@ -52,7 +52,7 @@
 // CompletionCallback isn't destroyed before being called or the Mojo pipe
 // being closed.
 IN_PROC_BROWSER_TEST_F(SyntheticInputTest, DestroyWidgetWithOngoingGesture) {
-  NavigateToURL(shell(), GURL("about:blank"));
+  EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
   WaitForLoadStop(shell()->web_contents());
 
   GestureScrollObserver gesture_observer;
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc
index c13373b..af5f534b 100644
--- a/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -158,7 +158,7 @@
  protected:
   void LoadURL(const char* touch_action_url) {
     const GURL data_url(touch_action_url);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     frame_observer_ = std::make_unique<RenderFrameSubmissionObserver>(
diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc
index 14eb583..2ec45b0 100644
--- a/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -109,7 +109,7 @@
   }
   void LoadURL() {
     const GURL data_url(kTouchEventDataURL);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     // Wait to confirm a frame was generated from the navigation.
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index 40380a36..485536a4 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -140,7 +140,7 @@
   void StartTestWithPage(const std::string& url) {
     ASSERT_TRUE(embedded_test_server()->Start());
     GURL test_url(embedded_test_server()->GetURL(url));
-    NavigateToURL(shell(), test_url);
+    EXPECT_TRUE(NavigateToURL(shell(), test_url));
     aura::Window* content = shell()->web_contents()->GetContentNativeView();
     content->GetHost()->SetBoundsInPixels(gfx::Rect(800, 600));
   }
diff --git a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
index 2370b2ca..cf501e0 100644
--- a/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
+++ b/content/browser/renderer_host/input/touchpad_pinch_browsertest.cc
@@ -78,7 +78,7 @@
  protected:
   void LoadURL() {
     const GURL data_url(kTouchpadPinchDataURL);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
     HitTestRegionObserver observer(GetRenderWidgetHost()->GetFrameSinkId());
     observer.WaitForHitTestData();
   }
diff --git a/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc b/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc
index d72cafc5..3315fc06 100644
--- a/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc
+++ b/content/browser/renderer_host/input/wheel_event_listener_browsertest.cc
@@ -64,7 +64,7 @@
 
   void LoadURL(const std::string& page_data) {
     const GURL data_url("data:text/html," + page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(400, 400));
@@ -132,4 +132,4 @@
   WaitForScroll();
 }
 
-}  // namespace content
\ No newline at end of file
+}  // namespace content
diff --git a/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc b/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
index f4bada5e..f9c7e62 100644
--- a/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
+++ b/content/browser/renderer_host/input/wheel_scroll_latching_browsertest.cc
@@ -101,7 +101,7 @@
 
   void LoadURL(const std::string& page_data) {
     const GURL data_url("data:text/html," + page_data);
-    NavigateToURL(shell(), data_url);
+    EXPECT_TRUE(NavigateToURL(shell(), data_url));
 
     RenderWidgetHostImpl* host = GetWidgetHost();
     host->GetView()->SetSize(gfx::Size(600, 600));
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
index 8990f91..d876f56 100644
--- a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -82,9 +82,9 @@
     audio_manager_->Shutdown();
   }
 
-  BrowserContext* CreateBrowserContext() override {
-    // Caller takes ownership.
-    return new TestBrowserContextWithRealURLRequestContextGetter();
+  std::unique_ptr<BrowserContext> CreateBrowserContext() override {
+    return std::make_unique<
+        TestBrowserContextWithRealURLRequestContextGetter>();
   }
 
   void SetUp() override {
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index 7b5e494..a3b61c58 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -153,7 +153,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
   RenderProcessHost* rph =
       shell()->web_contents()->GetMainFrame()->GetProcess();
   // Make it believe it's a guest.
@@ -166,7 +166,7 @@
   replace_host.SetHostStr("localhost");
   GURL another_url = embedded_test_server()->GetURL("/simple_page.html");
   another_url = another_url.ReplaceComponents(replace_host);
-  NavigateToURL(CreateBrowser(), another_url);
+  EXPECT_TRUE(NavigateToURL(CreateBrowser(), another_url));
 
   // Expect that we got another process (the guest renderer was not reused).
   EXPECT_EQ(2, RenderProcessHost::GetCurrentRenderProcessCountForTesting());
@@ -183,7 +183,7 @@
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
   Shell* window = CreateBrowser();
-  NavigateToURL(window, test_url);
+  EXPECT_TRUE(NavigateToURL(window, test_url));
 
   EXPECT_EQ(spare_renderer,
             window->web_contents()->GetMainFrame()->GetProcess());
@@ -211,7 +211,7 @@
       RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
   Shell* window = CreateBrowser();
-  NavigateToURL(window, test_url);
+  EXPECT_TRUE(NavigateToURL(window, test_url));
 
   // There should have been another process created for the navigation.
   EXPECT_NE(spare_renderer,
@@ -287,7 +287,7 @@
   // rather than picked up via MaybeTakeSpareRenderProcessHost().
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
   Shell* new_window = CreateBrowser();
-  NavigateToURL(new_window, test_url);
+  EXPECT_TRUE(NavigateToURL(new_window, test_url));
   // Outside of RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes mode, the
   // spare RPH should have been dropped during CreateBrowser() and given to the
   // new window.  OTOH, even in the IsSpareProcessKeptAtAllTimes mode, the spare
@@ -626,7 +626,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   std::string logging_string;
   ShellCloser shell_closer(shell(), &logging_string);
@@ -665,7 +665,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
   RenderProcessHost* rph =
       shell()->web_contents()->GetMainFrame()->GetProcess();
 
@@ -808,8 +808,8 @@
 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
                        GetUserMediaIncrementsVideoCaptureStreams) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/media/getusermedia.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
   std::string result;
@@ -824,8 +824,8 @@
 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
                        StopResetsVideoCaptureStreams) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/media/getusermedia.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
   std::string result;
@@ -841,8 +841,8 @@
 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
                        KillProcessZerosVideoCaptureStreams) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/media/getusermedia.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
   std::string result;
@@ -888,8 +888,8 @@
 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
                        GetUserMediaAudioOnlyIncrementsMediaStreams) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/media/getusermedia.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
   std::string result;
@@ -906,8 +906,8 @@
 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
                        KillProcessZerosAudioCaptureStreams) {
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/media/getusermedia.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
   std::string result;
@@ -961,7 +961,8 @@
                              {"foo.com"});
   }
 
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/send-beacon.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/send-beacon.html")));
 
   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
       shell()->web_contents()->GetMainFrame());
@@ -975,8 +976,8 @@
 
   // Navigate to a site that will be in a different process.
   base::TimeTicks start = base::TimeTicks::Now();
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("foo.com", "/title1.html")));
 
   WaitUntilProcessExits(1);
 
@@ -998,7 +999,8 @@
       base::BindRepeating(HandleHungBeacon));
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  NavigateToURL(shell(), embedded_test_server()->GetURL("/send-beacon.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/send-beacon.html")));
 
   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
       shell()->web_contents()->GetMainFrame());
@@ -1011,7 +1013,7 @@
   rfh->SetKeepAliveTimeoutForTesting(base::TimeDelta::FromSeconds(1));
 
   base::TimeTicks start = base::TimeTicks::Now();
-  NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>"));
+  EXPECT_TRUE(NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>")));
 
   WaitUntilProcessExits(1);
 
@@ -1034,8 +1036,8 @@
       base::BindRepeating(HandleHungBeacon));
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/fetch-keepalive.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/fetch-keepalive.html")));
 
   RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
       shell()->web_contents()->GetMainFrame());
@@ -1048,7 +1050,7 @@
   rfh->SetKeepAliveTimeoutForTesting(base::TimeDelta::FromSeconds(1));
 
   base::TimeTicks start = base::TimeTicks::Now();
-  NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>"));
+  EXPECT_TRUE(NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>")));
 
   WaitUntilProcessExits(1);
 
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc
index 68dbbe23..bb33f2f 100644
--- a/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -67,7 +67,7 @@
   RenderViewHostTestWebContentsObserver observer(shell()->web_contents());
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   EXPECT_EQ(
       net::HostPortPair::FromURL(embedded_test_server()->base_url()),
@@ -81,7 +81,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   FrameTreeNode* old_root = static_cast<WebContentsImpl*>(
       shell()->web_contents())->GetFrameTree()->root();
@@ -102,7 +102,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL test_url = embedded_test_server()->GetURL("/touch_selection.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   WebContents* contents = shell()->web_contents();
   EXPECT_FALSE(contents->IsFocusedElementEditable());
@@ -120,7 +120,7 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL test_url = embedded_test_server()->GetURL(
       "/access-session-storage.html");
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   // Make a new Shell, a seperate tab with it's own session namespace and
   // have it start loading a url but still be in progress.
@@ -142,7 +142,7 @@
 
   // Do something that causes ipc queues to flush and tasks in
   // flight to complete such that we should have received the ACK.
-  NavigateToURL(shell(), test_url);
+  EXPECT_TRUE(NavigateToURL(shell(), test_url));
 
   // Verify we have the only remaining reference to the namespace.
   EXPECT_TRUE(session_namespace->HasOneRef());
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc
index 185347a..1cb5b75 100644
--- a/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -108,9 +108,9 @@
   void SetUpOnMainThread() override {
     ContentBrowserTest::SetUpOnMainThread();
 
-    NavigateToURL(shell(),
-                  GURL("data:text/html,<!doctype html>"
-                       "<body style='background-color: red;'></body>"));
+    EXPECT_TRUE(NavigateToURL(
+        shell(), GURL("data:text/html,<!doctype html>"
+                      "<body style='background-color: red;'></body>")));
 
     view_ = static_cast<RenderWidgetHostViewBase*>(
         shell()->web_contents()->GetRenderWidgetHostView());
@@ -440,7 +440,7 @@
   GURL target_child_url = main_url.ReplaceComponents(replacement);
   DocumentLoadObserver child_frame_observer(shell()->web_contents(),
                                             target_child_url);
-  NavigateToURL(shell(), main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
   child_frame_observer.Wait();
   auto* filter = GetTouchActionFilterForWidget(web_contents()
                                                    ->GetFrameTree()
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 693355f..c6de209a 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -211,8 +211,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   // Creates the initial RenderWidgetHostViewBase, and connects to a
   // CompositorFrameSink. This will trigger frame eviction.
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/page_with_animation.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/page_with_animation.html")));
   RenderWidgetHostViewBase* rwhvb = GetRenderWidgetHostView();
   // Eviction normally invalidates the LocalSurfaceId, however if the
   // RenderWidgetHostViewBase is visible, a new id must be allocated. Otherwise
@@ -240,8 +240,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   // Creates the initial RenderWidgetHostViewBase, and connects to a
   // CompositorFrameSink.
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/page_with_animation.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/page_with_animation.html")));
   RenderWidgetHostViewBase* rwhvb = GetRenderWidgetHostView();
   EXPECT_TRUE(rwhvb);
   viz::LocalSurfaceId rwhvb_local_surface_id =
@@ -266,8 +266,8 @@
 
   // Perform a navigation to the same content source. This will reuse the
   // existing RenderWidgetHostViewBase.
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/page_with_animation.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/page_with_animation.html")));
   EXPECT_FALSE(rwhvb->GetLocalSurfaceIdAllocation().IsValid());
 
 #if defined(OS_ANDROID)
@@ -300,8 +300,8 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   auto* web_contents = shell()->web_contents();
   // Load a page that draws new frames infinitely.
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/page_with_animation.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/page_with_animation.html")));
   std::unique_ptr<RenderFrameSubmissionObserver> frame_observer(
       std::make_unique<RenderFrameSubmissionObserver>(web_contents));
 
@@ -367,7 +367,7 @@
 
   bool SetUpSourceSurface(const char* wait_message) override {
     content::DOMMessageQueue message_queue;
-    NavigateToURL(shell(), TestUrl());
+    EXPECT_TRUE(NavigateToURL(shell(), TestUrl()));
     if (wait_message != nullptr) {
       std::string result(wait_message);
       if (!message_queue.WaitForMessage(&result)) {
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index 4e5c2189..c1cdca9 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -99,7 +99,7 @@
 // Tests that the screen is properly reflected for RWHVChildFrame.
 IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, Screen) {
   GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
-  NavigateToURL(shell(), main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
 
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
@@ -161,7 +161,7 @@
                        PresentationFeedback) {
   base::HistogramTester histogram_tester;
   GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
-  NavigateToURL(shell(), main_url);
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
 
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index ee994583..a1514df 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -114,9 +114,9 @@
       const GURL& scope,
       const GURL& script_url) {
     base::RunLoop loop;
-    if (!context()->storage()->LazyInitializeForTest(loop.QuitClosure())) {
-      loop.Run();
-    }
+    context()->storage()->LazyInitializeForTest(loop.QuitClosure());
+    loop.Run();
+
     RegistrationAndVersionPair pair;
     blink::mojom::ServiceWorkerRegistrationOptions options;
     options.scope = scope;
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index 85ae455..4722a62 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -105,7 +105,7 @@
           base::MakeRefCounted<URLLoaderFactoryGetter>()) {
   scoped_refptr<base::SequencedTaskRunner> database_task_runner =
       base::ThreadTaskRunnerHandle::Get();
-  wrapper_->InitInternal(
+  wrapper_->InitOnIO(
       user_data_directory, std::move(database_task_runner), nullptr, nullptr,
       nullptr, url_loader_factory_getter_.get(),
       blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index 120cf3b..c30c66c 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -221,8 +221,6 @@
     URLLoaderFactoryGetter* loader_factory_getter) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(storage_partition_);
-  if (watcher_)
-    watcher_->Start();
 
   is_incognito_ = user_data_directory.empty();
   // The database task runner is BLOCK_SHUTDOWN in order to support
@@ -234,13 +232,28 @@
       base::CreateSequencedTaskRunner(
           {base::ThreadPool(), base::MayBlock(),
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-  InitInternal(user_data_directory, std::move(database_task_runner),
-               quota_manager_proxy, special_storage_policy, blob_context,
-               loader_factory_getter,
-               blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()
-                   ? CreateNonNetworkURLLoaderFactoryBundleInfoForUpdateCheck(
-                         storage_partition_->browser_context())
-                   : nullptr);
+  std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+      non_network_loader_factory_bundle_info_for_update_check;
+  if (blink::ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled()) {
+    non_network_loader_factory_bundle_info_for_update_check =
+        CreateNonNetworkURLLoaderFactoryBundleInfoForUpdateCheck(
+            storage_partition_->browser_context());
+  }
+  base::PostTask(
+      FROM_HERE, {BrowserThread::IO},
+      base::BindOnce(
+          &ServiceWorkerContextWrapper::InitOnIO, this, user_data_directory,
+          std::move(database_task_runner),
+          base::RetainedRef(quota_manager_proxy),
+          base::RetainedRef(special_storage_policy),
+          base::RetainedRef(blob_context),
+          base::RetainedRef(loader_factory_getter),
+          std::move(non_network_loader_factory_bundle_info_for_update_check)));
+
+  // The watcher also posts a IO thread task which must run after InitOnIO(), so
+  // start it after posting that task above.
+  if (watcher_)
+    watcher_->Start();
 }
 
 void ServiceWorkerContextWrapper::Shutdown() {
@@ -1127,7 +1140,7 @@
   DCHECK(!resource_context_);
 }
 
-void ServiceWorkerContextWrapper::InitInternal(
+void ServiceWorkerContextWrapper::InitOnIO(
     const base::FilePath& user_data_directory,
     scoped_refptr<base::SequencedTaskRunner> database_task_runner,
     storage::QuotaManagerProxy* quota_manager_proxy,
@@ -1136,21 +1149,9 @@
     URLLoaderFactoryGetter* loader_factory_getter,
     std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
         non_network_loader_factory_bundle_info_for_update_check) {
-  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-    base::PostTask(
-        FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(
-            &ServiceWorkerContextWrapper::InitInternal, this,
-            user_data_directory, std::move(database_task_runner),
-            base::RetainedRef(quota_manager_proxy),
-            base::RetainedRef(special_storage_policy),
-            base::RetainedRef(blob_context),
-            base::RetainedRef(loader_factory_getter),
-            std::move(
-                non_network_loader_factory_bundle_info_for_update_check)));
-    return;
-  }
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!context_core_);
+
   if (quota_manager_proxy) {
     quota_manager_proxy->RegisterClient(new ServiceWorkerQuotaClient(this));
   }
@@ -1535,6 +1536,15 @@
              registrations_for_origin_.end();
 }
 
+void ServiceWorkerContextWrapper::WaitForRegistrationsInitializedForTest() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (registrations_initialized_)
+    return;
+  base::RunLoop loop;
+  on_registrations_initialized_ = loop.QuitClosure();
+  loop.Run();
+}
+
 void ServiceWorkerContextWrapper::OnRegistrationUpdated(
     const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1553,6 +1563,9 @@
       registrations_for_origin_[origin].insert(registration_id);
     }
   }
+
+  if (on_registrations_initialized_)
+    std::move(on_registrations_initialized_).Run();
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index 3f0e309..338ede7c 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -306,6 +306,7 @@
 
   // Whether |origin| has any registrations. Must be called on UI thread.
   bool HasRegistrationForOrigin(const GURL& origin) const;
+  void WaitForRegistrationsInitializedForTest();
 
  private:
   friend class BackgroundSyncManagerTest;
@@ -322,15 +323,14 @@
 
   ~ServiceWorkerContextWrapper() override;
 
-  void InitInternal(
-      const base::FilePath& user_data_directory,
-      scoped_refptr<base::SequencedTaskRunner> database_task_runner,
-      storage::QuotaManagerProxy* quota_manager_proxy,
-      storage::SpecialStoragePolicy* special_storage_policy,
-      ChromeBlobStorageContext* blob_context,
-      URLLoaderFactoryGetter* url_loader_factory_getter,
-      std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
-          non_network_loader_factory_bundle_info_for_update_check);
+  void InitOnIO(const base::FilePath& user_data_directory,
+                scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+                storage::QuotaManagerProxy* quota_manager_proxy,
+                storage::SpecialStoragePolicy* special_storage_policy,
+                ChromeBlobStorageContext* blob_context,
+                URLLoaderFactoryGetter* url_loader_factory_getter,
+                std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
+                    non_network_loader_factory_bundle_info_for_update_check);
   void ShutdownOnIO();
 
   // If |include_installing_version| is true, |callback| is called if there is
@@ -473,6 +473,7 @@
   // fully converted to running on the UI thread.
   base::flat_map<GURL, base::flat_set<int64_t>> registrations_for_origin_;
   bool registrations_initialized_ = false;
+  base::OnceClosure on_registrations_initialized_;
 
   scoped_refptr<ServiceWorkerContextWatcher> watcher_;
 
diff --git a/content/browser/service_worker/service_worker_context_wrapper_unittest.cc b/content/browser/service_worker/service_worker_context_wrapper_unittest.cc
new file mode 100644
index 0000000..6443cf5a
--- /dev/null
+++ b/content/browser/service_worker/service_worker_context_wrapper_unittest.cc
@@ -0,0 +1,110 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_database.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/browser/url_loader_factory_getter.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
+
+namespace content {
+
+// Fixture for the ServiceWorkerContextWrapper test. It uses a disk user data
+// directory in order to test starting the browser with a registration already
+// written to storage.
+class ServiceWorkerContextWrapperTest : public testing::Test {
+ public:
+  ServiceWorkerContextWrapperTest() = default;
+
+  void SetUp() override {
+    ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
+    InitWrapper();
+  }
+
+  void TearDown() override {
+    // Shutdown or else ASAN complains of leaks.
+    wrapper_->Shutdown();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void InitWrapper() {
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    wrapper_ = base::MakeRefCounted<ServiceWorkerContextWrapper>(
+        browser_context_.get());
+    url_loader_factory_getter_ = base::MakeRefCounted<URLLoaderFactoryGetter>();
+    StoragePartitionImpl* storage_partition =
+        static_cast<StoragePartitionImpl*>(
+            BrowserContext::GetStoragePartitionForSite(
+                browser_context_.get(), GURL("https://example.com")));
+    wrapper_->set_storage_partition(storage_partition);
+    wrapper_->Init(user_data_directory_.GetPath(), nullptr, nullptr, nullptr,
+                   url_loader_factory_getter_.get());
+    // Init() posts a couple tasks to the IO thread. Let them finish.
+    base::RunLoop().RunUntilIdle();
+
+    base::RunLoop loop;
+    storage()->LazyInitializeForTest(loop.QuitClosure());
+    loop.Run();
+  }
+
+  ServiceWorkerContextCore* context() { return wrapper_->context(); }
+  ServiceWorkerStorage* storage() { return context()->storage(); }
+
+ protected:
+  TestBrowserThreadBundle browser_thread_bundle_{
+      TestBrowserThreadBundle::IO_MAINLOOP};
+  base::ScopedTempDir user_data_directory_;
+  std::unique_ptr<TestBrowserContext> browser_context_;
+  scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_;
+  scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWrapperTest);
+};
+
+// Test that the UI thread knows which origins have registrations upon
+// browser startup. Regression test for https://crbug.com/991143.
+TEST_F(ServiceWorkerContextWrapperTest, HasRegistration) {
+  // Make a service worker.
+  GURL scope("https://example.com/");
+  GURL script("https://example.com/sw.js");
+  scoped_refptr<ServiceWorkerRegistration> registration =
+      CreateServiceWorkerRegistrationAndVersion(context(), scope, script);
+
+  // Store it.
+  base::RunLoop loop;
+  storage()->StoreRegistration(
+      registration.get(), registration->waiting_version(),
+      base::BindLambdaForTesting(
+          [&loop](blink::ServiceWorkerStatusCode status) {
+            ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
+            loop.Quit();
+          }));
+  loop.Run();
+
+  // Simulate browser shutdown and restart.
+  wrapper_->Shutdown();
+  base::RunLoop().RunUntilIdle();
+  wrapper_.reset();
+  InitWrapper();
+
+  // Now test that registrations are recognized.
+  wrapper_->WaitForRegistrationsInitializedForTest();
+  EXPECT_TRUE(wrapper_->HasRegistrationForOrigin(GURL("https://example.com")));
+  EXPECT_FALSE(wrapper_->HasRegistrationForOrigin(GURL("https://example.org")));
+}
+
+}  // namespace content
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index dc470025..62cfa0bec 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -1176,13 +1176,13 @@
       .Append(kDiskCacheName);
 }
 
-bool ServiceWorkerStorage::LazyInitializeForTest(base::OnceClosure callback) {
+void ServiceWorkerStorage::LazyInitializeForTest(base::OnceClosure callback) {
   if (state_ == STORAGE_STATE_UNINITIALIZED ||
       state_ == STORAGE_STATE_INITIALIZING) {
     LazyInitialize(std::move(callback));
-    return false;
+    return;
   }
-  return !IsDisabled();
+  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
 }
 
 void ServiceWorkerStorage::LazyInitialize(base::OnceClosure callback) {
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 8978199..26c3847 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -287,7 +287,7 @@
   // the uncommitted resource keys.
   void PurgeResources(const ResourceList& resources);
 
-  bool LazyInitializeForTest(base::OnceClosure callback);
+  void LazyInitializeForTest(base::OnceClosure callback);
 
  private:
   friend class service_worker_storage_unittest::ServiceWorkerStorageTest;
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index 36963bee..6dec052 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -365,27 +365,6 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  // Creates a registration with a waiting version in INSTALLED state.
-  scoped_refptr<ServiceWorkerRegistration> CreateLiveRegistrationAndVersion(
-      const GURL& scope,
-      const GURL& script) {
-    blink::mojom::ServiceWorkerRegistrationOptions options;
-    options.scope = scope;
-    auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
-        options, storage()->NewRegistrationId(), context()->AsWeakPtr());
-    auto version = base::MakeRefCounted<ServiceWorkerVersion>(
-        registration.get(), script, blink::mojom::ScriptType::kClassic,
-        storage()->NewVersionId(), context()->AsWeakPtr());
-    std::vector<ResourceRecord> records = {
-        ResourceRecord(storage()->NewResourceId(), script, 100)};
-    version->script_cache_map()->SetResources(records);
-    version->set_fetch_handler_existence(
-        ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
-    version->SetStatus(ServiceWorkerVersion::INSTALLED);
-    registration->SetWaitingVersion(version);
-    return registration;
-  }
-
   blink::ServiceWorkerStatusCode StoreRegistration(
       scoped_refptr<ServiceWorkerRegistration> registration,
       scoped_refptr<ServiceWorkerVersion> version) {
@@ -1035,7 +1014,7 @@
 
   // Store a registration.
   scoped_refptr<ServiceWorkerRegistration> live_registration =
-      CreateLiveRegistrationAndVersion(kScope, kScript);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope, kScript);
   EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
             StoreRegistration(live_registration,
                               live_registration->waiting_version()));
@@ -1774,19 +1753,19 @@
   const GURL kScope1("http://www.example.com/scope/");
   const GURL kScript1("http://www.example.com/script1.js");
   scoped_refptr<ServiceWorkerRegistration> live_registration1 =
-      CreateLiveRegistrationAndVersion(kScope1, kScript1);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope1, kScript1);
 
   // Registration for "/scope/foo".
   const GURL kScope2("http://www.example.com/scope/foo");
   const GURL kScript2("http://www.example.com/script2.js");
   scoped_refptr<ServiceWorkerRegistration> live_registration2 =
-      CreateLiveRegistrationAndVersion(kScope2, kScript2);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope2, kScript2);
 
   // Registration for "/scope/foobar".
   const GURL kScope3("http://www.example.com/scope/foobar");
   const GURL kScript3("http://www.example.com/script3.js");
   scoped_refptr<ServiceWorkerRegistration> live_registration3 =
-      CreateLiveRegistrationAndVersion(kScope3, kScript3);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope3, kScript3);
 
   // Notify storage of them being installed.
   storage()->NotifyInstallingRegistration(live_registration1.get());
@@ -2046,7 +2025,7 @@
   const GURL kScope("https://example.com/scope");
   const GURL kScript("https://example.com/script.js");
   scoped_refptr<ServiceWorkerRegistration> registration =
-      CreateLiveRegistrationAndVersion(kScope, kScript);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope, kScript);
   ServiceWorkerVersion* version = registration->waiting_version();
 
   // Give it a main script response info.
@@ -2105,8 +2084,8 @@
   };
   std::vector<scoped_refptr<ServiceWorkerRegistration>> registrations;
   for (const auto& pair : scope_and_script_pairs) {
-    registrations.emplace_back(
-        CreateLiveRegistrationAndVersion(pair.first, pair.second));
+    registrations.emplace_back(CreateServiceWorkerRegistrationAndVersion(
+        context(), pair.first, pair.second));
   }
 
   // Store all registrations.
@@ -2142,7 +2121,7 @@
   const GURL kScope("https://valid.example.com/scope");
   const GURL kScript("https://valid.example.com/script.js");
   scoped_refptr<ServiceWorkerRegistration> registration =
-      CreateLiveRegistrationAndVersion(kScope, kScript);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope, kScript);
   ServiceWorkerVersion* version = registration->waiting_version();
   version->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration->SetActiveVersion(version);
@@ -2179,7 +2158,7 @@
   const GURL kScript("https://valid.example.com/script.js");
   const std::string kHeaderValue("custom header value");
   scoped_refptr<ServiceWorkerRegistration> registration =
-      CreateLiveRegistrationAndVersion(kScope, kScript);
+      CreateServiceWorkerRegistrationAndVersion(context(), kScope, kScript);
   ServiceWorkerVersion* version = registration->waiting_version();
   version->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration->SetActiveVersion(version);
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index b4ef15ce..8927676 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -311,6 +311,30 @@
   return host;
 }
 
+scoped_refptr<ServiceWorkerRegistration>
+CreateServiceWorkerRegistrationAndVersion(ServiceWorkerContextCore* context,
+                                          const GURL& scope,
+                                          const GURL& script) {
+  ServiceWorkerStorage* storage = context->storage();
+
+  blink::mojom::ServiceWorkerRegistrationOptions options;
+  options.scope = scope;
+  auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
+      options, storage->NewRegistrationId(), context->AsWeakPtr());
+  auto version = base::MakeRefCounted<ServiceWorkerVersion>(
+      registration.get(), script, blink::mojom::ScriptType::kClassic,
+      storage->NewVersionId(), context->AsWeakPtr());
+  std::vector<ServiceWorkerDatabase::ResourceRecord> records = {
+      ServiceWorkerDatabase::ResourceRecord(storage->NewResourceId(), script,
+                                            100)};
+  version->script_cache_map()->SetResources(records);
+  version->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version->SetStatus(ServiceWorkerVersion::INSTALLED);
+  registration->SetWaitingVersion(version);
+  return registration;
+}
+
 ServiceWorkerDatabase::ResourceRecord WriteToDiskCacheSync(
     ServiceWorkerStorage* storage,
     const GURL& script_url,
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h
index 14e6afa..c5a07af 100644
--- a/content/browser/service_worker/service_worker_test_utils.h
+++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -135,6 +135,12 @@
     base::WeakPtr<ServiceWorkerContextCore> context,
     ServiceWorkerRemoteProviderEndpoint* output_endpoint);
 
+// Creates a registration with a waiting version in INSTALLED state.
+scoped_refptr<ServiceWorkerRegistration>
+CreateServiceWorkerRegistrationAndVersion(ServiceWorkerContextCore* context,
+                                          const GURL& scope,
+                                          const GURL& script);
+
 // Writes the script down to |storage| synchronously. This should not be used in
 // base::RunLoop since base::RunLoop is used internally to wait for completing
 // all of tasks. If it's in another base::RunLoop, consider to use
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 48b30baf..7f3540f 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -153,8 +153,8 @@
   void AddCookie() {
     CanonicalCookie::CookieInclusionStatus status;
     std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
-        kOrigin1.GetURL(), "A=1", base::Time::Now(), net::CookieOptions(),
-        &status));
+        kOrigin1.GetURL(), "A=1", base::Time::Now(),
+        base::nullopt /* server_time */, &status));
     storage_partition_->GetCookieManagerForBrowserProcess()->SetCanonicalCookie(
         *cc, kOrigin1.scheme(), net::CookieOptions(),
         base::BindOnce(&RemoveCookieTester::SetCookieCallback,
@@ -1606,22 +1606,26 @@
   GURL url2("https://www.example.com/");
   GURL url3("https://www.google.com/");
 
-  net::CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
   deletion_filter->host_name = url.host();
 
   base::Time now = base::Time::Now();
   std::vector<std::unique_ptr<CanonicalCookie>> valid_cookies;
-  valid_cookies.push_back(CanonicalCookie::Create(url, "A=B", now, options));
-  valid_cookies.push_back(CanonicalCookie::Create(url, "C=F", now, options));
+  valid_cookies.push_back(
+      CanonicalCookie::Create(url, "A=B", now, server_time));
+  valid_cookies.push_back(
+      CanonicalCookie::Create(url, "C=F", now, server_time));
   // We should match a different scheme with the same host.
-  valid_cookies.push_back(CanonicalCookie::Create(url2, "A=B", now, options));
+  valid_cookies.push_back(
+      CanonicalCookie::Create(url2, "A=B", now, server_time));
 
   std::vector<std::unique_ptr<CanonicalCookie>> invalid_cookies;
   // We don't match domain cookies.
+  invalid_cookies.push_back(CanonicalCookie::Create(
+      url2, "A=B;domain=.example.com", now, server_time));
   invalid_cookies.push_back(
-      CanonicalCookie::Create(url2, "A=B;domain=.example.com", now, options));
-  invalid_cookies.push_back(CanonicalCookie::Create(url3, "A=B", now, options));
+      CanonicalCookie::Create(url3, "A=B", now, server_time));
 
   for (const auto& cookie : valid_cookies) {
     EXPECT_TRUE(FilterMatchesCookie(deletion_filter, *cookie))
diff --git a/content/browser/web_package/bundled_exchanges_handle.cc b/content/browser/web_package/bundled_exchanges_handle.cc
index cfdcd7e..21c4732 100644
--- a/content/browser/web_package/bundled_exchanges_handle.cc
+++ b/content/browser/web_package/bundled_exchanges_handle.cc
@@ -10,6 +10,7 @@
 #include "base/task/post_task.h"
 #include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/web_package/bundled_exchanges_reader.h"
+#include "content/browser/web_package/bundled_exchanges_url_loader_factory.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -18,12 +19,41 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 
 namespace content {
 
 namespace {
 
+const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("bundled_exchanges_start_url_loader",
+                                        R"(
+  semantics {
+    sender: "BundledExchanges primary_url Loader"
+    description:
+      "Navigation request for the primary_url provided by a BundledExchanges "
+      "that is requested by the user. This does not trigger any network "
+      "transaction directly, but access to an entry in a local file, or in a "
+      "previously fetched resource over network."
+    trigger: "The user navigates to a BundledExchanges."
+    data: "Nothing."
+    destination: LOCAL
+  }
+  policy {
+    cookies_allowed: NO
+    setting: "These requests cannot be disabled in settings."
+    policy_exception_justification:
+      "Not implemented. This request does not make any network transaction."
+  }
+  comments:
+    "Usually the request accesses an entry in a local file that contains "
+    "multiple archived entries. But once the feature is exposed to the public "
+    "web API, the archive file can be streamed over network. In such case, the "
+    "streaming should be provided by another URLLoader request that is issued "
+    "by Blink, but based on a user initiated navigation."
+  )");
+
 // A class to inherit NavigationLoaderInterceptor for the navigation to a
 // BundledExchanges.
 class Interceptor final : public NavigationLoaderInterceptor {
@@ -141,16 +171,20 @@
 BundledExchangesHandle::CreateInterceptor() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return std::make_unique<Interceptor>(
-      base::BindRepeating(&BundledExchangesHandle::CreatePrimaryURLLoader,
-                          weak_factory_.GetWeakPtr()));
+      source_.IsValid()
+          ? base::BindRepeating(&BundledExchangesHandle::CreatePrimaryURLLoader,
+                                weak_factory_.GetWeakPtr())
+          : base::NullCallback());
 }
 
 void BundledExchangesHandle::CreateURLLoaderFactory(
     mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
     mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(url_loader_factory_);
 
-  NOTIMPLEMENTED();
+  url_loader_factory_->SetFallbackFactory(std::move(fallback_factory));
+  url_loader_factory_->Clone(std::move(receiver));
 }
 
 void BundledExchangesHandle::CreatePrimaryURLLoader(
@@ -160,10 +194,12 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Check if this is the initial request to the BundledExchanges itself, or
-  // subsequent requests to the main exchange in the BundledExchanges.
-  if (!is_redirected_ && source_.Match(resource_request.url)) {
-    // This is the initial request to the BundledExchanges.
+  // subsequent requests to the primary exchange in the BundledExchanges.
+  if (!is_redirected_) {
+    DCHECK(source_.Match(resource_request.url));
     DCHECK(!redirect_loader_);
+
+    // This is the initial request to the BundledExchanges.
     is_redirected_ = true;
     auto redirect_loader =
         std::make_unique<BundledExchangesHandle::PrimaryURLRedirectLoader>(
@@ -176,7 +212,12 @@
         mojo::PendingReceiver<network::mojom::URLLoader>(std::move(request)));
     MayRedirectPrimaryURLLoader();
   } else {
-    // TODO(crbug.com/966753): Implement.
+    DCHECK(url_loader_factory_);
+
+    url_loader_factory_->CreateLoaderAndStart(
+        std::move(request), /*routing_id=*/0, /*request_id=*/0, /*options=*/0,
+        resource_request, std::move(client),
+        net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation));
   }
 }
 
@@ -196,9 +237,14 @@
 void BundledExchangesHandle::OnMetadataReady(
     data_decoder::mojom::BundleMetadataParseErrorPtr error) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(!url_loader_factory_);
 
   primary_url_ = std::move(reader_->GetPrimaryURL());
   metadata_error_ = std::move(error);
+
+  url_loader_factory_ =
+      std::make_unique<BundledExchangesURLLoaderFactory>(std::move(reader_));
+
   MayRedirectPrimaryURLLoader();
 }
 
diff --git a/content/browser/web_package/bundled_exchanges_handle.h b/content/browser/web_package/bundled_exchanges_handle.h
index 0b822a9..0160513 100644
--- a/content/browser/web_package/bundled_exchanges_handle.h
+++ b/content/browser/web_package/bundled_exchanges_handle.h
@@ -21,6 +21,7 @@
 namespace content {
 
 class BundledExchangesReader;
+class BundledExchangesURLLoaderFactory;
 class NavigationLoaderInterceptor;
 
 // A class to provide interfaces to communicate with a BundledExchanges for
@@ -55,6 +56,7 @@
 
   base::WeakPtr<PrimaryURLRedirectLoader> redirect_loader_;
   std::unique_ptr<BundledExchangesReader> reader_;
+  std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory_;
   GURL primary_url_;
   data_decoder::mojom::BundleMetadataParseErrorPtr metadata_error_;
   bool is_redirected_ = false;
diff --git a/content/browser/web_package/bundled_exchanges_reader.cc b/content/browser/web_package/bundled_exchanges_reader.cc
index 5b8860c..9b55f6d 100644
--- a/content/browser/web_package/bundled_exchanges_reader.cc
+++ b/content/browser/web_package/bundled_exchanges_reader.cc
@@ -16,6 +16,7 @@
 #include "mojo/public/cpp/system/data_pipe_producer.h"
 #include "mojo/public/cpp/system/file_data_source.h"
 #include "mojo/public/cpp/system/platform_handle.h"
+#include "net/base/url_util.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -160,7 +161,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(metadata_ready_);
 
-  auto it = entries_.find(url);
+  auto it = entries_.find(net::SimplifyUrlForRequest(url));
   if (it == entries_.end() || it->second->response_locations.empty()) {
     PostTask(FROM_HERE, base::BindOnce(std::move(callback), nullptr));
     return;
@@ -200,7 +201,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(metadata_ready_);
 
-  return entries_.contains(url);
+  return entries_.contains(net::SimplifyUrlForRequest(url));
 }
 
 const GURL& BundledExchangesReader::GetPrimaryURL() const {
diff --git a/content/browser/web_package/bundled_exchanges_reader_unittest.cc b/content/browser/web_package/bundled_exchanges_reader_unittest.cc
index daa41eff..8b91e5c3 100644
--- a/content/browser/web_package/bundled_exchanges_reader_unittest.cc
+++ b/content/browser/web_package/bundled_exchanges_reader_unittest.cc
@@ -14,146 +14,25 @@
 #include "base/optional.h"
 #include "base/test/scoped_task_environment.h"
 #include "content/browser/web_package/bundled_exchanges_source.h"
+#include "content/browser/web_package/mock_bundled_exchanges_reader_factory.h"
 #include "mojo/public/c/system/data_pipe.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace content {
 
 namespace {
 
-class MockParser final : public data_decoder::mojom::BundledExchangesParser {
- public:
-  MockParser(mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
-                 receiver)
-      : receiver_(this, std::move(receiver)) {}
-  ~MockParser() override {}
-
-  void RunMetadataCallback(data_decoder::mojom::BundleMetadataPtr metadata) {
-    base::RunLoop().RunUntilIdle();
-    std::move(metadata_callback_).Run(std::move(metadata), nullptr);
-  }
-  void RunResponseCallback(data_decoder::mojom::BundleResponsePtr response) {
-    base::RunLoop().RunUntilIdle();
-    std::move(response_callback_).Run(std::move(response), nullptr);
-  }
-
-  void WaitUntilParseMetadataCalled(base::OnceClosure closure) {
-    if (metadata_callback_.is_null())
-      wait_parse_metadata_callback_ = std::move(closure);
-    else
-      std::move(closure).Run();
-  }
-
- private:
-  // data_decoder::mojom::BundledExchangesParser implementation.
-  void ParseMetadata(ParseMetadataCallback callback) override {
-    metadata_callback_ = std::move(callback);
-    if (!wait_parse_metadata_callback_.is_null())
-      std::move(wait_parse_metadata_callback_).Run();
-  }
-  void ParseResponse(uint64_t response_offset,
-                     uint64_t response_length,
-                     ParseResponseCallback callback) override {
-    response_callback_ = std::move(callback);
-  }
-
-  mojo::Receiver<data_decoder::mojom::BundledExchangesParser> receiver_;
-
-  ParseMetadataCallback metadata_callback_;
-  ParseResponseCallback response_callback_;
-  base::OnceClosure wait_parse_metadata_callback_;
-};
-
-class MockParserFactory final
-    : public data_decoder::mojom::BundledExchangesParserFactory {
- public:
-  MockParserFactory() {}
-  ~MockParserFactory() override {}
-
-  void WaitUntilParseMetadataCalled(base::OnceClosure closure) {
-    if (parser_)
-      parser_->WaitUntilParseMetadataCalled(std::move(closure));
-    else
-      wait_parse_metadata_callback_ = std::move(closure);
-  }
-
-  void RunMetadataCallback(data_decoder::mojom::BundleMetadataPtr metadata) {
-    base::RunLoop run_loop;
-    WaitUntilParseMetadataCalled(run_loop.QuitClosure());
-    run_loop.Run();
-
-    ASSERT_TRUE(parser_);
-    parser_->RunMetadataCallback(std::move(metadata));
-  }
-  void RunResponseCallback(data_decoder::mojom::BundleResponsePtr response) {
-    ASSERT_TRUE(parser_);
-    parser_->RunResponseCallback(std::move(response));
-  }
-
- private:
-  // data_decoder::mojom::BundledExchangesParserFactory implementation.
-  void GetParserForFile(
-      mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
-          receiver,
-      base::File file) override {
-    parser_ = std::make_unique<MockParser>(std::move(receiver));
-    if (!wait_parse_metadata_callback_.is_null()) {
-      parser_->WaitUntilParseMetadataCalled(
-          std::move(wait_parse_metadata_callback_));
-    }
-  }
-  void GetParserForDataSource(
-      mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
-          receiver,
-      mojo::PendingRemote<data_decoder::mojom::BundleDataSource> data_source)
-      override {
-    NOTREACHED();
-  }
-
-  std::unique_ptr<MockParser> parser_;
-  base::OnceClosure wait_parse_metadata_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockParserFactory);
-};
-
 class BundledExchangesReaderTest : public testing::Test {
  public:
   void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    ASSERT_TRUE(
-        CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path_));
-
-    ASSERT_EQ(base::checked_cast<int>(body_.size()),
-              base::WriteFile(temp_file_path_, body_.data(), body_.size()));
-
-    BundledExchangesSource source(temp_file_path_);
-    reader_ = std::make_unique<BundledExchangesReader>(source);
-
-    std::unique_ptr<MockParserFactory> factory =
-        std::make_unique<MockParserFactory>();
-    factory_ = factory.get();
-    mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> remote;
-    mojo::MakeSelfOwnedReceiver(std::move(factory),
-                                remote.BindNewPipeAndPassReceiver());
-    reader_->SetBundledExchangesParserFactoryForTesting(std::move(remote));
+    reader_factory_ = MockBundledExchangesReaderFactory::Create();
+    reader_ = reader_factory_->CreateReader(body_);
   }
 
  protected:
   void ReadMetadata() {
-    base::RunLoop run_loop;
-    reader_->ReadMetadata(base::BindOnce(
-        [](base::Closure quit_closure,
-           data_decoder::mojom::BundleMetadataParseErrorPtr error) {
-          EXPECT_FALSE(error);
-          std::move(quit_closure).Run();
-        },
-        run_loop.QuitClosure()));
-
     base::flat_map<GURL, data_decoder::mojom::BundleIndexValuePtr> items;
     data_decoder::mojom::BundleIndexValuePtr item =
         data_decoder::mojom::BundleIndexValue::New();
@@ -164,21 +43,25 @@
     data_decoder::mojom::BundleMetadataPtr metadata =
         data_decoder::mojom::BundleMetadata::New(primary_url_, std::move(items),
                                                  GURL() /* manifest_url */);
-    factory_->RunMetadataCallback(std::move(metadata));
-    run_loop.Run();
+    reader_factory_->ReadAndFullfillMetadata(
+        reader_.get(), std::move(metadata),
+        base::BindOnce(
+            [](data_decoder::mojom::BundleMetadataParseErrorPtr error) {
+              EXPECT_FALSE(error);
+            }));
   }
   BundledExchangesReader* GetReader() { return reader_.get(); }
-  MockParserFactory* GetFactory() { return factory_; }
+  MockBundledExchangesReaderFactory* GetMockFactory() {
+    return reader_factory_.get();
+  }
   const GURL& GetPrimaryURL() const { return primary_url_; }
   const std::string& GetBody() const { return body_; }
 
  private:
   base::test::ScopedTaskEnvironment task_environment_;
-  base::ScopedTempDir temp_dir_;
-  base::FilePath temp_file_path_;
+  std::unique_ptr<MockBundledExchangesReaderFactory> reader_factory_;
   std::unique_ptr<BundledExchangesReader> reader_;
-  MockParserFactory* factory_;
-  const GURL primary_url_ = GURL("https://www.google.com/");
+  const GURL primary_url_ = GURL("https://test.example.org/");
   const std::string body_ = std::string("hello new open world.");
 };
 
@@ -186,35 +69,80 @@
   ReadMetadata();
   EXPECT_EQ(GetPrimaryURL(), GetReader()->GetPrimaryURL());
   EXPECT_TRUE(GetReader()->HasEntry(GetPrimaryURL()));
-  EXPECT_FALSE(GetReader()->HasEntry(GURL("https://www.google.com/404")));
+  EXPECT_TRUE(
+      GetReader()->HasEntry(GURL("https://user:pass@test.example.org/")));
+  EXPECT_TRUE(GetReader()->HasEntry(GURL("https://test.example.org/#ref")));
+  EXPECT_FALSE(GetReader()->HasEntry(GURL("https://test.example.org/404")));
 }
 
 TEST_F(BundledExchangesReaderTest, ReadResponse) {
   ReadMetadata();
   ASSERT_TRUE(GetReader()->HasEntry(GetPrimaryURL()));
 
-  base::RunLoop run_loop;
-  GetReader()->ReadResponse(
-      GetPrimaryURL(), base::BindOnce(
-                           [](base::Closure quit_closure,
-                              data_decoder::mojom::BundleResponsePtr response) {
-                             EXPECT_TRUE(response);
-                             if (response) {
-                               EXPECT_EQ(200, response->response_code);
-                               EXPECT_EQ(0xdeadu, response->payload_offset);
-                               EXPECT_EQ(0xbeafu, response->payload_length);
-                             }
-                             std::move(quit_closure).Run();
-                           },
-                           run_loop.QuitClosure()));
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0xdead;
+  response->payload_length = 0xbeaf;
+
+  GetMockFactory()->ReadAndFullfillResponse(
+      GetReader(), GetPrimaryURL(), std::move(response),
+      base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
+        EXPECT_TRUE(response);
+        if (response) {
+          EXPECT_EQ(200, response->response_code);
+          EXPECT_EQ(0xdeadu, response->payload_offset);
+          EXPECT_EQ(0xbeafu, response->payload_length);
+        }
+      }));
+}
+
+TEST_F(BundledExchangesReaderTest, ReadResponseForURLContainingUserAndPass) {
+  GURL url = GURL("https://user:pass@test.example.org/");
+
+  ReadMetadata();
+  ASSERT_TRUE(GetReader()->HasEntry(url));
 
   data_decoder::mojom::BundleResponsePtr response =
       data_decoder::mojom::BundleResponse::New();
   response->response_code = 200;
   response->payload_offset = 0xdead;
   response->payload_length = 0xbeaf;
-  GetFactory()->RunResponseCallback(std::move(response));
-  run_loop.Run();
+
+  GetMockFactory()->ReadAndFullfillResponse(
+      GetReader(), url, std::move(response),
+      base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
+        EXPECT_TRUE(response);
+        if (response) {
+          EXPECT_EQ(200, response->response_code);
+          EXPECT_EQ(0xdeadu, response->payload_offset);
+          EXPECT_EQ(0xbeafu, response->payload_length);
+        }
+      }));
+}
+
+TEST_F(BundledExchangesReaderTest, ReadResponseForURLContainingFragment) {
+  GURL url = GURL("https://test.example.org/#fragment");
+
+  ReadMetadata();
+  ASSERT_TRUE(GetReader()->HasEntry(url));
+
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0xdead;
+  response->payload_length = 0xbeaf;
+
+  GetMockFactory()->ReadAndFullfillResponse(
+      GetReader(), url, std::move(response),
+      base::BindOnce([](data_decoder::mojom::BundleResponsePtr response) {
+        EXPECT_TRUE(response);
+        if (response) {
+          EXPECT_EQ(200, response->response_code);
+          EXPECT_EQ(0xdeadu, response->payload_offset);
+          EXPECT_EQ(0xbeafu, response->payload_length);
+        }
+      }));
 }
 
 TEST_F(BundledExchangesReaderTest, ReadResponseBody) {
diff --git a/content/browser/web_package/bundled_exchanges_source.cc b/content/browser/web_package/bundled_exchanges_source.cc
index a1d8ded..a8478730 100644
--- a/content/browser/web_package/bundled_exchanges_source.cc
+++ b/content/browser/web_package/bundled_exchanges_source.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/web_package/bundled_exchanges_source.h"
 #include "net/base/filename_util.h"
+#include "net/base/url_util.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -34,8 +35,10 @@
   if (!IsValid())
     return false;
 
+  GURL request_url = net::SimplifyUrlForRequest(url);
+
   if (!file_path.empty())
-    return MatchByFilePath(url, file_path);
+    return MatchByFilePath(request_url, file_path);
 
   NOTREACHED();
   return false;
diff --git a/content/browser/web_package/bundled_exchanges_url_loader_factory.cc b/content/browser/web_package/bundled_exchanges_url_loader_factory.cc
new file mode 100644
index 0000000..fc14677
--- /dev/null
+++ b/content/browser/web_package/bundled_exchanges_url_loader_factory.cc
@@ -0,0 +1,191 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/bundled_exchanges_url_loader_factory.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/task/post_task.h"
+#include "content/browser/web_package/bundled_exchanges_reader.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/http/http_util.h"
+#include "services/network/public/cpp/constants.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace content {
+
+namespace {
+
+constexpr char kCrLf[] = "\r\n";
+
+network::ResourceResponseHead CreateResourceResponse(
+    const data_decoder::mojom::BundleResponsePtr& response) {
+  DCHECK_EQ(net::HTTP_OK, response->response_code);
+
+  std::vector<std::string> header_strings;
+  header_strings.push_back("HTTP/1.1 ");
+  header_strings.push_back(base::NumberToString(response->response_code));
+  header_strings.push_back(" ");
+  header_strings.push_back(net::GetHttpReasonPhrase(
+      static_cast<net::HttpStatusCode>(response->response_code)));
+  header_strings.push_back(kCrLf);
+  for (const auto& it : response->response_headers) {
+    header_strings.push_back(it.first);
+    header_strings.push_back(": ");
+    header_strings.push_back(it.second);
+    header_strings.push_back(kCrLf);
+  }
+  header_strings.push_back(kCrLf);
+
+  network::ResourceResponseHead response_head;
+
+  response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+      net::HttpUtil::AssembleRawHeaders(base::JoinString(header_strings, "")));
+  response_head.headers->GetMimeTypeAndCharset(&response_head.mime_type,
+                                               &response_head.charset);
+  return response_head;
+}
+
+}  // namespace
+
+// TODO(crbug.com/966753): Consider security models, i.e. plausible CORS
+// adoption.
+class BundledExchangesURLLoaderFactory::EntryLoader final
+    : public network::mojom::URLLoader {
+ public:
+  EntryLoader(base::WeakPtr<BundledExchangesURLLoaderFactory> factory,
+              mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+              const GURL& url)
+      : factory_(std::move(factory)), loader_client_(std::move(client)) {
+    DCHECK(factory_);
+    factory_->GetReader()->ReadResponse(
+        url, base::BindOnce(&EntryLoader::OnResponseReady,
+                            weak_factory_.GetWeakPtr()));
+  }
+  ~EntryLoader() override = default;
+
+ private:
+  // network::mojom::URLLoader implementation
+  void FollowRedirect(const std::vector<std::string>& removed_headers,
+                      const net::HttpRequestHeaders& modified_headers,
+                      const base::Optional<GURL>& new_url) override {}
+  void SetPriority(net::RequestPriority priority,
+                   int intra_priority_value) override {}
+  void PauseReadingBodyFromNet() override {}
+  void ResumeReadingBodyFromNet() override {}
+
+  void OnResponseReady(data_decoder::mojom::BundleResponsePtr response) {
+    if (!factory_ || !loader_client_.is_connected())
+      return;
+
+    // TODO(crbug.com/990733): For the initial implementation, we allow only
+    // net::HTTP_OK, but we should clarify acceptable status code in the spec.
+    if (!response || response->response_code != net::HTTP_OK) {
+      // TODO(crbug.com/966753): Define and use
+      // net::ERR_INVALID_BUNDLED_EXCHANGES.
+      loader_client_->OnComplete(
+          network::URLLoaderCompletionStatus(net::ERR_FAILED));
+      return;
+    }
+
+    loader_client_->OnReceiveResponse(CreateResourceResponse(response));
+
+    mojo::ScopedDataPipeProducerHandle producer_handle;
+    mojo::ScopedDataPipeConsumerHandle consumer_handle;
+    MojoCreateDataPipeOptions options;
+    options.struct_size = sizeof(MojoCreateDataPipeOptions);
+    options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+    options.element_num_bytes = 1;
+    options.capacity_num_bytes =
+        std::min(static_cast<uint64_t>(network::kDataPipeDefaultAllocationSize),
+                 response->payload_length);
+
+    auto result =
+        mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle);
+    loader_client_->OnStartLoadingResponseBody(std::move(consumer_handle));
+    if (result != MOJO_RESULT_OK) {
+      loader_client_->OnComplete(
+          network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
+      return;
+    }
+
+    factory_->GetReader()->ReadResponseBody(
+        std::move(response), std::move(producer_handle),
+        base::BindOnce(&EntryLoader::FinishReadingBody,
+                       weak_factory_.GetWeakPtr()));
+  }
+
+  void FinishReadingBody(MojoResult result) {
+    if (!loader_client_.is_connected())
+      return;
+
+    network::URLLoaderCompletionStatus status;
+    status.error_code =
+        result == MOJO_RESULT_OK ? net::OK : net::ERR_UNEXPECTED;
+    loader_client_->OnComplete(status);
+  }
+
+  base::WeakPtr<BundledExchangesURLLoaderFactory> factory_;
+  mojo::Remote<network::mojom::URLLoaderClient> loader_client_;
+
+  base::WeakPtrFactory<EntryLoader> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(EntryLoader);
+};
+
+BundledExchangesURLLoaderFactory::BundledExchangesURLLoaderFactory(
+    std::unique_ptr<BundledExchangesReader> reader)
+    : reader_(std::move(reader)) {}
+
+BundledExchangesURLLoaderFactory::~BundledExchangesURLLoaderFactory() = default;
+
+void BundledExchangesURLLoaderFactory::SetFallbackFactory(
+    mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory) {
+  fallback_factory_ = std::move(fallback_factory);
+}
+
+void BundledExchangesURLLoaderFactory::CreateLoaderAndStart(
+    network::mojom::URLLoaderRequest loader_request,
+    int32_t routing_id,
+    int32_t request_id,
+    uint32_t options,
+    const network::ResourceRequest& resource_request,
+    network::mojom::URLLoaderClientPtr loader_client,
+    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+  if (base::EqualsCaseInsensitiveASCII(resource_request.method,
+                                       net::HttpRequestHeaders::kGetMethod) &&
+      reader_->HasEntry(resource_request.url)) {
+    auto loader = std::make_unique<EntryLoader>(weak_factory_.GetWeakPtr(),
+                                                loader_client.PassInterface(),
+                                                resource_request.url);
+    std::unique_ptr<network::mojom::URLLoader> url_loader = std::move(loader);
+    mojo::MakeSelfOwnedReceiver(
+        std::move(url_loader), mojo::PendingReceiver<network::mojom::URLLoader>(
+                                   std::move(loader_request)));
+  } else if (fallback_factory_) {
+    fallback_factory_->CreateLoaderAndStart(
+        std::move(loader_request), routing_id, request_id, options,
+        resource_request, std::move(loader_client), traffic_annotation);
+  } else {
+    loader_client->OnComplete(
+        network::URLLoaderCompletionStatus(net::ERR_FAILED));
+  }
+}
+
+void BundledExchangesURLLoaderFactory::Clone(
+    network::mojom::URLLoaderFactoryRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+}  // namespace content
diff --git a/content/browser/web_package/bundled_exchanges_url_loader_factory.h b/content/browser/web_package/bundled_exchanges_url_loader_factory.h
new file mode 100644
index 0000000..b194b0d
--- /dev/null
+++ b/content/browser/web_package/bundled_exchanges_url_loader_factory.h
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_URL_LOADER_FACTORY_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_URL_LOADER_FACTORY_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+class BundledExchangesReader;
+
+// A class to implements network::mojom::URLLoaderFactory that supports
+// BundledExchanges.
+class CONTENT_EXPORT BundledExchangesURLLoaderFactory final
+    : public network::mojom::URLLoaderFactory {
+ public:
+  explicit BundledExchangesURLLoaderFactory(
+      std::unique_ptr<BundledExchangesReader> reader);
+  ~BundledExchangesURLLoaderFactory() override;
+
+  // Set a |network::mojom::URLLoaderFactory| remote interface used for requests
+  // that are not found in the BundledExchanges. This will override the existing
+  // fallback_factory if it was set previously.
+  void SetFallbackFactory(
+      mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory);
+
+  // mojom::URLLoaderFactory implementation.
+  void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader_request,
+                            int32_t routing_id,
+                            int32_t request_id,
+                            uint32_t options,
+                            const network::ResourceRequest& resource_request,
+                            network::mojom::URLLoaderClientPtr loader_client,
+                            const net::MutableNetworkTrafficAnnotationTag&
+                                traffic_annotation) override;
+  void Clone(network::mojom::URLLoaderFactoryRequest request) override;
+
+ private:
+  class EntryLoader;
+  friend class EntryLoader;
+
+  BundledExchangesReader* GetReader() { return reader_.get(); }
+
+  mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
+  std::unique_ptr<BundledExchangesReader> reader_;
+  mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory_;
+
+  base::WeakPtrFactory<BundledExchangesURLLoaderFactory> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(BundledExchangesURLLoaderFactory);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_URL_LOADER_FACTORY_H_
diff --git a/content/browser/web_package/bundled_exchanges_url_loader_factory_unittest.cc b/content/browser/web_package/bundled_exchanges_url_loader_factory_unittest.cc
new file mode 100644
index 0000000..0ae8b732
--- /dev/null
+++ b/content/browser/web_package/bundled_exchanges_url_loader_factory_unittest.cc
@@ -0,0 +1,270 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/bundled_exchanges_url_loader_factory.h"
+
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "content/browser/web_package/bundled_exchanges_reader.h"
+#include "content/browser/web_package/mock_bundled_exchanges_reader_factory.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+class BundledExchangesURLLoaderFactoryTest : public testing::Test {
+ public:
+  BundledExchangesURLLoaderFactoryTest() {}
+
+  void SetUp() override {
+    mock_factory_ = MockBundledExchangesReaderFactory::Create();
+    auto reader = mock_factory_->CreateReader(body_);
+    reader_ = reader.get();
+    loader_factory_ =
+        std::make_unique<BundledExchangesURLLoaderFactory>(std::move(reader));
+
+    base::flat_map<GURL, data_decoder::mojom::BundleIndexValuePtr> items;
+    data_decoder::mojom::BundleIndexValuePtr item =
+        data_decoder::mojom::BundleIndexValue::New();
+    item->response_locations.push_back(
+        data_decoder::mojom::BundleResponseLocation::New(0u, 0u));
+    items.insert({primary_url_, std::move(item)});
+
+    data_decoder::mojom::BundleMetadataPtr metadata =
+        data_decoder::mojom::BundleMetadata::New(primary_url_, std::move(items),
+                                                 /*manifest_url=*/GURL());
+
+    base::RunLoop run_loop;
+    mock_factory_->ReadAndFullfillMetadata(
+        reader_, std::move(metadata),
+        base::BindOnce(
+            [](base::Closure quit_closure,
+               data_decoder::mojom::BundleMetadataParseErrorPtr error) {
+              std::move(quit_closure).Run();
+            },
+            run_loop.QuitClosure()));
+    run_loop.Run();
+  }
+
+  // This function creates a URLLoader, and simulates a response for
+  // BundledExchangesReader::ReadResponse with |response| if it is given.
+  // |response| can contains nullptr to simulate the case ReadResponse fails.
+  mojo::Remote<network::mojom::URLLoader> CreateLoaderAndStart(
+      const GURL& url,
+      const std::string& method,
+      base::Optional<data_decoder::mojom::BundleResponsePtr> response,
+      bool clone = false) {
+    mojo::Remote<network::mojom::URLLoader> loader;
+    network::ResourceRequest resource_request;
+    resource_request.url = url;
+    resource_request.method = method;
+
+    if (clone) {
+      mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
+      loader_factory_->Clone(loader_factory.BindNewPipeAndPassReceiver());
+      loader_factory->CreateLoaderAndStart(
+          loader.BindNewPipeAndPassReceiver(),
+          /*routing_id=*/0, /*request_id=*/0, /*options=*/0, resource_request,
+          test_client_.CreateInterfacePtr(),
+          net::MutableNetworkTrafficAnnotationTag(
+              TRAFFIC_ANNOTATION_FOR_TESTS));
+
+    } else {
+      loader_factory_->CreateLoaderAndStart(
+          loader.BindNewPipeAndPassReceiver(),
+          /*routing_id=*/0, /*request_id=*/0, /*options=*/0, resource_request,
+          test_client_.CreateInterfacePtr(),
+          net::MutableNetworkTrafficAnnotationTag(
+              TRAFFIC_ANNOTATION_FOR_TESTS));
+    }
+
+    if (response)
+      mock_factory_->FullfillResponse(std::move(*response), base::DoNothing());
+    return loader;
+  }
+
+  const GURL& GetPrimaryURL() const { return primary_url_; }
+  const std::string& GetBody() const { return body_; }
+
+  void RunAndCheck(const std::string expected_body) {
+    test_client_.RunUntilResponseBodyArrived();
+
+    EXPECT_TRUE(test_client_.has_received_response());
+    EXPECT_FALSE(test_client_.has_received_redirect());
+    EXPECT_FALSE(test_client_.has_received_upload_progress());
+    EXPECT_FALSE(test_client_.has_received_cached_metadata());
+
+    ASSERT_TRUE(test_client_.response_head().headers);
+    ASSERT_TRUE(test_client_.response_body());
+
+    EXPECT_EQ(200, test_client_.response_head().headers->response_code());
+
+    if (!expected_body.empty()) {
+      std::vector<char> buffer(expected_body.size() * 2);
+      uint32_t num_bytes = buffer.size();
+      MojoResult result;
+      do {
+        base::RunLoop().RunUntilIdle();
+        result = test_client_.response_body().ReadData(
+            buffer.data(), &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+      } while (result == MOJO_RESULT_SHOULD_WAIT);
+
+      EXPECT_EQ(MOJO_RESULT_OK, result);
+      EXPECT_EQ(expected_body.size(), num_bytes);
+      EXPECT_EQ(expected_body, std::string(buffer.data(), num_bytes));
+    }
+
+    test_client_.RunUntilComplete();
+
+    ASSERT_TRUE(test_client_.has_received_completion());
+    EXPECT_EQ(net::OK, test_client_.completion_status().error_code);
+  }
+
+  void RunAndCheckFailure() {
+    test_client_.RunUntilComplete();
+    ASSERT_TRUE(test_client_.has_received_completion());
+    EXPECT_EQ(net::ERR_FAILED, test_client_.completion_status().error_code);
+  }
+
+  void SetFallbackFactory(
+      mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory) {
+    loader_factory_->SetFallbackFactory(std::move(fallback_factory));
+  }
+
+ private:
+  base::test::ScopedTaskEnvironment task_environment_;
+  std::unique_ptr<MockBundledExchangesReaderFactory> mock_factory_;
+  std::unique_ptr<BundledExchangesURLLoaderFactory> loader_factory_;
+  BundledExchangesReader* reader_;
+  network::TestURLLoaderClient test_client_;
+  const std::string body_ = std::string("present day, present time");
+  const GURL primary_url_ = GURL("https://test.example.org/");
+
+  DISALLOW_COPY_AND_ASSIGN(BundledExchangesURLLoaderFactoryTest);
+};
+
+TEST_F(BundledExchangesURLLoaderFactoryTest, CreateEntryLoader) {
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0;
+  response->payload_length = GetBody().size();
+
+  auto loader =
+      CreateLoaderAndStart(GetPrimaryURL(), net::HttpRequestHeaders::kGetMethod,
+                           std::move(response));
+
+  RunAndCheck(GetBody());
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest,
+       CreateEntryLoaderForURLContainingUserAndPass) {
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0;
+  response->payload_length = GetBody().size();
+
+  auto loader = CreateLoaderAndStart(
+      GURL("https://user:pass@test.example.org/"),
+      net::HttpRequestHeaders::kGetMethod, std::move(response));
+
+  RunAndCheck(GetBody());
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest,
+       CreateEntryLoaderForURLContainingFragment) {
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0;
+  response->payload_length = GetBody().size();
+
+  auto loader = CreateLoaderAndStart(GURL("https://test.example.org/#test"),
+                                     net::HttpRequestHeaders::kGetMethod,
+                                     std::move(response));
+
+  RunAndCheck(GetBody());
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest,
+       CreateEntryLoaderAndFailToReadResponse) {
+  auto loader =
+      CreateLoaderAndStart(GetPrimaryURL(), net::HttpRequestHeaders::kGetMethod,
+                           /*response=*/nullptr);
+
+  RunAndCheckFailure();
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest, CreateLoaderForPost) {
+  // URL should match, but POST method should not be handled by the EntryLoader.
+  auto loader =
+      CreateLoaderAndStart(GetPrimaryURL(), "POST", /*response=*/base::nullopt);
+
+  RunAndCheckFailure();
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest, CreateLoaderForNotSupportedURL) {
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  auto loader = CreateLoaderAndStart(GURL("https://test.example.org/nowhere"),
+                                     net::HttpRequestHeaders::kGetMethod,
+                                     /*response=*/base::nullopt);
+
+  RunAndCheckFailure();
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest, CreateFallbackLoader) {
+  // Create a TestURLLoaderFactory, and set it to the
+  // BundledExchangesURLLoaderFactory as a fallback factory.
+  auto test_factory = std::make_unique<network::TestURLLoaderFactory>();
+  mojo::Remote<network::mojom::URLLoaderFactory> factory;
+  test_factory->Clone(factory.BindNewPipeAndPassReceiver());
+
+  SetFallbackFactory(std::move(factory));
+
+  // Access to the 404 address for the BundledExchanges, so to be handled by
+  // the fallback factory set above.
+  const std::string url_string = "https://test.example.org/somewhere";
+  auto loader = CreateLoaderAndStart(
+      GURL(url_string), net::HttpRequestHeaders::kGetMethod, base::nullopt);
+  ASSERT_EQ(1, test_factory->NumPending());
+
+  // Reply with a mock response.
+  test_factory->SimulateResponseForPendingRequest(url_string, GetBody(),
+                                                  net::HTTP_OK);
+
+  RunAndCheck(GetBody());
+}
+
+TEST_F(BundledExchangesURLLoaderFactoryTest, CreateByClonedFactory) {
+  data_decoder::mojom::BundleResponsePtr response =
+      data_decoder::mojom::BundleResponse::New();
+  response->response_code = 200;
+  response->payload_offset = 0;
+  response->payload_length = GetBody().size();
+
+  auto loader =
+      CreateLoaderAndStart(GetPrimaryURL(), net::HttpRequestHeaders::kGetMethod,
+                           std::move(response), /*clone=*/true);
+
+  RunAndCheck(GetBody());
+}
+
+}  // namespace
+
+}  // namespace content
diff --git a/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc b/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc
new file mode 100644
index 0000000..ac38fb3
--- /dev/null
+++ b/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc
@@ -0,0 +1,243 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_package/mock_bundled_exchanges_reader_factory.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "content/browser/web_package/bundled_exchanges_reader.h"
+#include "content/browser/web_package/bundled_exchanges_source.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class MockParser final : public data_decoder::mojom::BundledExchangesParser {
+ public:
+  MockParser(mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
+                 receiver)
+      : receiver_(this, std::move(receiver)) {}
+  ~MockParser() override = default;
+
+  void RunMetadataCallback(data_decoder::mojom::BundleMetadataPtr metadata) {
+    std::move(metadata_callback_).Run(std::move(metadata), nullptr);
+  }
+  void RunResponseCallback(data_decoder::mojom::BundleResponsePtr response) {
+    std::move(response_callback_).Run(std::move(response), nullptr);
+  }
+
+  void WaitUntilParseMetadataCalled(base::OnceClosure closure) {
+    if (metadata_callback_.is_null())
+      wait_parse_metadata_callback_ = std::move(closure);
+    else
+      std::move(closure).Run();
+  }
+  void WaitUntilParseResponseCalled(base::OnceClosure closure) {
+    if (response_callback_.is_null())
+      wait_parse_response_callback_ = std::move(closure);
+    else
+      std::move(closure).Run();
+  }
+
+ private:
+  // data_decoder::mojom::BundledExchangesParser implementation.
+  void ParseMetadata(ParseMetadataCallback callback) override {
+    metadata_callback_ = std::move(callback);
+    if (!wait_parse_metadata_callback_.is_null())
+      std::move(wait_parse_metadata_callback_).Run();
+  }
+  void ParseResponse(uint64_t response_offset,
+                     uint64_t response_length,
+                     ParseResponseCallback callback) override {
+    response_callback_ = std::move(callback);
+    if (!wait_parse_response_callback_.is_null())
+      std::move(wait_parse_response_callback_).Run();
+  }
+
+  mojo::Receiver<data_decoder::mojom::BundledExchangesParser> receiver_;
+
+  ParseMetadataCallback metadata_callback_;
+  ParseResponseCallback response_callback_;
+  base::OnceClosure wait_parse_metadata_callback_;
+  base::OnceClosure wait_parse_response_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockParser);
+};
+
+class MockParserFactory final
+    : public data_decoder::mojom::BundledExchangesParserFactory {
+ public:
+  MockParserFactory() {}
+  ~MockParserFactory() override = default;
+
+  void WaitUntilParseMetadataCalled(base::OnceClosure closure) {
+    if (parser_)
+      parser_->WaitUntilParseMetadataCalled(std::move(closure));
+    else
+      wait_parse_metadata_callback_ = std::move(closure);
+  }
+  void WaitUntilParseResponseCalled(base::OnceClosure closure) {
+    if (parser_)
+      parser_->WaitUntilParseResponseCalled(std::move(closure));
+    else
+      wait_parse_response_callback_ = std::move(closure);
+  }
+
+  void RunMetadataCallback(data_decoder::mojom::BundleMetadataPtr metadata) {
+    base::RunLoop run_loop;
+    WaitUntilParseMetadataCalled(run_loop.QuitClosure());
+    run_loop.Run();
+
+    ASSERT_TRUE(parser_);
+    parser_->RunMetadataCallback(std::move(metadata));
+  }
+  void RunResponseCallback(data_decoder::mojom::BundleResponsePtr response) {
+    base::RunLoop run_loop;
+    WaitUntilParseResponseCalled(run_loop.QuitClosure());
+    run_loop.Run();
+
+    ASSERT_TRUE(parser_);
+    parser_->RunResponseCallback(std::move(response));
+  }
+
+ private:
+  // data_decoder::mojom::BundledExchangesParserFactory implementation.
+  void GetParserForFile(
+      mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
+          receiver,
+      base::File file) override {
+    parser_ = std::make_unique<MockParser>(std::move(receiver));
+    if (!wait_parse_metadata_callback_.is_null()) {
+      parser_->WaitUntilParseMetadataCalled(
+          std::move(wait_parse_metadata_callback_));
+    }
+  }
+  void GetParserForDataSource(
+      mojo::PendingReceiver<data_decoder::mojom::BundledExchangesParser>
+          receiver,
+      mojo::PendingRemote<data_decoder::mojom::BundleDataSource> data_source)
+      override {
+    NOTREACHED();
+  }
+
+  std::unique_ptr<MockParser> parser_;
+  base::OnceClosure wait_parse_metadata_callback_;
+  base::OnceClosure wait_parse_response_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockParserFactory);
+};
+
+class MockBundledExchangesReaderFactoryImpl final
+    : public MockBundledExchangesReaderFactory {
+ public:
+  MockBundledExchangesReaderFactoryImpl()
+      : MockBundledExchangesReaderFactory() {}
+  ~MockBundledExchangesReaderFactoryImpl() override = default;
+
+  std::unique_ptr<BundledExchangesReader> CreateReader(
+      const std::string& test_file_data) override {
+    if (!temp_dir_.CreateUniqueTempDir() ||
+        !CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path_) ||
+        (test_file_data.size() !=
+         static_cast<size_t>(base::WriteFile(
+             temp_file_path_, test_file_data.data(), test_file_data.size())))) {
+      return nullptr;
+    }
+
+    BundledExchangesSource source(temp_file_path_);
+    auto reader = std::make_unique<BundledExchangesReader>(source);
+
+    std::unique_ptr<MockParserFactory> factory =
+        std::make_unique<MockParserFactory>();
+    factory_ = factory.get();
+    mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> remote;
+    mojo::MakeSelfOwnedReceiver(std::move(factory),
+                                remote.BindNewPipeAndPassReceiver());
+    reader->SetBundledExchangesParserFactoryForTesting(std::move(remote));
+    return reader;
+  }
+
+  void ReadAndFullfillMetadata(
+      BundledExchangesReader* reader,
+      data_decoder::mojom::BundleMetadataPtr metadata,
+      BundledExchangesReader::MetadataCallback callback) override {
+    ASSERT_TRUE(factory_);
+    DCHECK(reader);
+
+    base::RunLoop run_loop;
+    reader->ReadMetadata(base::BindOnce(
+        [](base::Closure quit_closure,
+           BundledExchangesReader::MetadataCallback callback,
+           data_decoder::mojom::BundleMetadataParseErrorPtr error) {
+          std::move(callback).Run(std::move(error));
+          std::move(quit_closure).Run();
+        },
+        run_loop.QuitClosure(), std::move(callback)));
+
+    factory_->RunMetadataCallback(std::move(metadata));
+    run_loop.Run();
+  }
+
+  void ReadAndFullfillResponse(
+      BundledExchangesReader* reader,
+      const GURL& url,
+      data_decoder::mojom::BundleResponsePtr response,
+      BundledExchangesReader::ResponseCallback callback) override {
+    ASSERT_TRUE(factory_);
+    DCHECK(reader);
+
+    base::RunLoop run_loop;
+    reader->ReadResponse(
+        url, base::BindOnce(
+                 [](base::Closure quit_closure,
+                    BundledExchangesReader::ResponseCallback callback,
+                    data_decoder::mojom::BundleResponsePtr response) {
+                   std::move(callback).Run(std::move(response));
+                   std::move(quit_closure).Run();
+                 },
+                 run_loop.QuitClosure(), std::move(callback)));
+
+    factory_->RunResponseCallback(std::move(response));
+    run_loop.Run();
+  }
+
+  void FullfillResponse(
+      data_decoder::mojom::BundleResponsePtr response,
+      BundledExchangesReader::ResponseCallback callback) override {
+    ASSERT_TRUE(factory_);
+
+    factory_->RunResponseCallback(std::move(response));
+  }
+
+ private:
+  std::string test_file_data_;
+  base::ScopedTempDir temp_dir_;
+  base::FilePath temp_file_path_;
+  MockParserFactory* factory_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(MockBundledExchangesReaderFactoryImpl);
+};
+
+}  // namespace
+
+// static
+std::unique_ptr<MockBundledExchangesReaderFactory>
+MockBundledExchangesReaderFactory::Create() {
+  return std::make_unique<MockBundledExchangesReaderFactoryImpl>();
+}
+
+}  // namespace content
diff --git a/content/browser/web_package/mock_bundled_exchanges_reader_factory.h b/content/browser/web_package/mock_bundled_exchanges_reader_factory.h
new file mode 100644
index 0000000..ee82a17
--- /dev/null
+++ b/content/browser/web_package/mock_bundled_exchanges_reader_factory.h
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEB_PACKAGE_MOCK_BUNDLED_EXCHANGES_READER_FACTORY_H_
+#define CONTENT_BROWSER_WEB_PACKAGE_MOCK_BUNDLED_EXCHANGES_READER_FACTORY_H_
+
+#include "base/macros.h"
+#include "content/browser/web_package/bundled_exchanges_reader.h"
+#include "services/data_decoder/public/mojom/bundled_exchanges_parser.mojom.h"
+
+namespace content {
+
+// A class to prepare a BundledExchangesReader instance that uses a mocked
+// BundledExchangesParser instance so that the BundledExchangesReader can run
+// without external utility processes. It also allows to craft arbitrary
+// responses for each parsing request.
+class MockBundledExchangesReaderFactory {
+ public:
+  static std::unique_ptr<MockBundledExchangesReaderFactory> Create();
+
+  MockBundledExchangesReaderFactory() = default;
+  virtual ~MockBundledExchangesReaderFactory() = default;
+
+  // Creates BundledExchangesReader instance. A temporary file is created and
+  // |test_file_data| is stored. This temporary file is used when
+  // BundledExchangesReader::ReadResponseBody() is called.
+  virtual std::unique_ptr<BundledExchangesReader> CreateReader(
+      const std::string& test_file_data) = 0;
+
+  // Calls ReadMetadata with |callback| for |reader|, and simulates the call as
+  // |metadata| is read.
+  virtual void ReadAndFullfillMetadata(
+      BundledExchangesReader* reader,
+      data_decoder::mojom::BundleMetadataPtr metadata,
+      BundledExchangesReader::MetadataCallback callback) = 0;
+
+  // Calls ReadResponse with |callback| for |reader|, and simulates the call as
+  // |response| is read.
+  virtual void ReadAndFullfillResponse(
+      BundledExchangesReader* reader,
+      const GURL& url,
+      data_decoder::mojom::BundleResponsePtr response,
+      BundledExchangesReader::ResponseCallback callback) = 0;
+
+  // Sets up the mocked factory so that the created BundledExchangesReader
+  // instance can read |response| when BundledExchangesReader::ReaderResponse is
+  // called.
+  virtual void FullfillResponse(
+      data_decoder::mojom::BundleResponsePtr response,
+      BundledExchangesReader::ResponseCallback callback) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockBundledExchangesReaderFactory);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEB_PACKAGE_MOCK_BUNDLED_EXCHANGES_READER_FACTORY_H_
diff --git a/content/common/accessibility_messages.h b/content/common/accessibility_messages.h
index 10aa315..b0e26b1 100644
--- a/content/common/accessibility_messages.h
+++ b/content/common/accessibility_messages.h
@@ -195,6 +195,10 @@
     AccessibilityHostMsg_FindInPageResult,
     AccessibilityHostMsg_FindInPageResultParams)
 
+// Sent when a Find In Page operation is finished and all highlighted results
+// are cleared.
+IPC_MESSAGE_ROUTED0(AccessibilityHostMsg_FindInPageTermination)
+
 // Sent in response to PerformAction with parameter kHitTest.
 IPC_MESSAGE_ROUTED5(AccessibilityHostMsg_ChildFrameHitTestResult,
                     int /* action request id of initial caller */,
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
index 7b35979a..6234ad74 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -27,6 +27,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content_public.browser.test.util.Criteria;
@@ -275,6 +276,7 @@
     @MediumTest
     @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @DisabledTest(message = "crbug.com/991463")
     public void testNavigationWithinEditTextField() throws Throwable {
         // Load a really simple webpage.
         final String data = "<form>\n"
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 6cea8ab1..2cc8bff 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1809,14 +1809,14 @@
   BrowserContext::GetDefaultStoragePartition(browser_context)
       ->GetNetworkContext()
       ->GetCookieManager(mojo::MakeRequest(&cookie_manager));
+  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
+      url, value, base::Time::Now(), base::nullopt /* server_time */));
+  DCHECK(cc.get());
+
   net::CookieOptions options;
   options.set_include_httponly();
   options.set_same_site_cookie_context(
       net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
-  std::unique_ptr<net::CanonicalCookie> cc(
-      net::CanonicalCookie::Create(url, value, base::Time::Now(), options));
-  DCHECK(cc.get());
-
   cookie_manager->SetCanonicalCookie(
       *cc.get(), url.scheme(), options,
       base::BindOnce(
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 5fc82ba..94a6dff3 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -251,7 +251,7 @@
   sanity_checker_.reset(new ContentBrowserSanityChecker());
 
   DCHECK(!browser_context_);
-  browser_context_.reset(CreateBrowserContext());
+  browser_context_ = CreateBrowserContext();
 
   SetContents(CreateTestWebContents());
   BrowserSideNavigationSetUp();
@@ -295,8 +295,9 @@
   thread_bundle_.reset();
 }
 
-BrowserContext* RenderViewHostTestHarness::CreateBrowserContext() {
-  return new TestBrowserContext();
+std::unique_ptr<BrowserContext>
+RenderViewHostTestHarness::CreateBrowserContext() {
+  return std::make_unique<TestBrowserContext>();
 }
 
 BrowserContext* RenderViewHostTestHarness::GetBrowserContext() {
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h
index 7c78035..a3115cb8 100644
--- a/content/public/test/test_renderer_host.h
+++ b/content/public/test/test_renderer_host.h
@@ -233,7 +233,7 @@
   // It is invoked by SetUp after threads were started.
   // RenderViewHostTestHarness will take ownership of the returned
   // BrowserContext.
-  virtual BrowserContext* CreateBrowserContext();
+  virtual std::unique_ptr<BrowserContext> CreateBrowserContext();
 
   // Derived classes can override this method to have the test harness use a
   // different BrowserContext than the one owned by this class. This is most
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index 96ac02c..8f87f96 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -309,6 +309,10 @@
   Send(new AccessibilityHostMsg_FindInPageResult(routing_id(), params));
 }
 
+void RenderAccessibilityImpl::HandleAccessibilityFindInPageTermination() {
+  Send(new AccessibilityHostMsg_FindInPageTermination(routing_id()));
+}
+
 void RenderAccessibilityImpl::AccessibilityFocusedElementChanged(
     const WebElement& element) {
   const WebDocument& document = GetMainDocument();
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h
index e5e6325..11052bfa 100644
--- a/content/renderer/accessibility/render_accessibility_impl.h
+++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -106,6 +106,10 @@
       const blink::WebAXObject& end_object,
       int end_offset);
 
+  // Called when a find in page result is terminated and all results are
+  // cleared.
+  void HandleAccessibilityFindInPageTermination();
+
   void AccessibilityFocusedElementChanged(const blink::WebElement& element);
 
   void HandleAXEvent(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 29411d2..af69214 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5777,6 +5777,11 @@
   }
 }
 
+void RenderFrameImpl::HandleAccessibilityFindInPageTermination() {
+  if (render_accessibility_)
+    render_accessibility_->HandleAccessibilityFindInPageTermination();
+}
+
 void RenderFrameImpl::EnterFullscreen(
     const blink::WebFullscreenOptions& options) {
   Send(new FrameHostMsg_EnterFullscreen(routing_id_, options));
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 3040c30..ae3f3c93 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -858,6 +858,7 @@
                                            int start_offset,
                                            const blink::WebNode& end_node,
                                            int end_offset) override;
+  void HandleAccessibilityFindInPageTermination() override;
   void EnterFullscreen(const blink::WebFullscreenOptions& options) override;
   void ExitFullscreen() override;
   void FullscreenStateChanged(bool is_fullscreen) override;
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index 6fbe4b3..15432c3 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -413,10 +413,6 @@
   } else {
     prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight;
   }
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kForceHighContrast)) {
-    prefs->forced_colors = blink::ForcedColors::kActive;
-  }
 }
 
 DevToolsManagerDelegate*
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc
index fce7fd5f..b2ee3b5 100644
--- a/content/shell/browser/web_test/blink_test_controller.cc
+++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -78,7 +78,6 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
-#include "ui/base/ui_base_switches.h"
 #include "ui/gfx/codec/png_codec.h"
 
 #if defined(OS_MACOSX)
@@ -566,10 +565,6 @@
         prefs->accelerated_2d_canvas_enabled = true;
       prefs->mock_scrollbars_enabled = true;
     }
-    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kForceHighContrast)) {
-      prefs->forced_colors = blink::ForcedColors::kActive;
-    }
   }
 }
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 291adb4..472569f4 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -76,6 +76,8 @@
     "../browser/service_worker/service_worker_test_utils.h",
     "../browser/service_worker/test_service_worker_observer.cc",
     "../browser/service_worker/test_service_worker_observer.h",
+    "../browser/web_package/mock_bundled_exchanges_reader_factory.cc",
+    "../browser/web_package/mock_bundled_exchanges_reader_factory.h",
     "../browser/web_package/mock_signed_exchange_handler.cc",
     "../browser/web_package/mock_signed_exchange_handler.h",
     "../browser/web_package/signed_exchange_test_utils.h",
@@ -383,6 +385,7 @@
     "//mojo/core/embedder",
     "//net:test_support",
     "//services/audio/public/mojom",
+    "//services/data_decoder/public/mojom",
     "//services/device/public/mojom",
 
     # TODO(jam): remove this by adding a public header for the NetworkContext
@@ -1779,6 +1782,7 @@
     "../browser/service_worker/service_worker_context_core_unittest.cc",
     "../browser/service_worker/service_worker_context_unittest.cc",
     "../browser/service_worker/service_worker_context_watcher_unittest.cc",
+    "../browser/service_worker/service_worker_context_wrapper_unittest.cc",
     "../browser/service_worker/service_worker_controllee_request_handler_unittest.cc",
     "../browser/service_worker/service_worker_database_unittest.cc",
     "../browser/service_worker/service_worker_installed_scripts_sender_unittest.cc",
@@ -1816,6 +1820,7 @@
     "../browser/web_contents/web_drag_dest_mac_unittest.mm",
     "../browser/web_contents/web_drag_source_mac_unittest.mm",
     "../browser/web_package/bundled_exchanges_reader_unittest.cc",
+    "../browser/web_package/bundled_exchanges_url_loader_factory_unittest.cc",
     "../browser/web_package/signed_exchange_cert_fetcher_unittest.cc",
     "../browser/web_package/signed_exchange_certificate_chain_unittest.cc",
     "../browser/web_package/signed_exchange_envelope_unittest.cc",
diff --git a/docs/sheriff.md b/docs/sheriff.md
index feb3d9bf..a56b939 100644
--- a/docs/sheriff.md
+++ b/docs/sheriff.md
@@ -86,6 +86,16 @@
 main channel clear of smaller status updates and makes it more like an index of
 the threads.
 
+### Monorail
+
+[Monorail] is our bug tracker. Hopefully you are already familiar with it.
+When sheriffing, you use Monorail to:
+
+* Look for existing bugs
+* File bugs when you revert CLs, explaining what happened and including any
+  stack traces or error messages
+* File bugs when you disable tests, again with as much information as practical
+
 ### The Waterfall
 
 The [CI console page], commonly referred to as "the waterfall" because of how it
@@ -267,7 +277,8 @@
 * Start a new thread in Slack for one of the failures
 * Investigate the failure and figure out why it happened - see the "diagnosing
   build failures" section below
-* Fix what went wrong
+* Fix what went wrong, remembering to file a bug to document both the failure
+  and your fix
 * Snooze the failure, with a link to the bug if your investigation resulted in a
   bug
 
@@ -365,6 +376,13 @@
 for Chromium tests you can just mark these as `DISABLED_` in those configurations
 if you want.
 
+When marking a Blink test as slow/flaky/etc, it's often not clear who to send
+the CL to, especially if the test is a WPT test imported from another repository
+or hasn't been edited in a while. In those situations, or when you just can't
+find the right owner for a test, feel free to TBR your CL to one of the other
+sheriffs on your rotation and kick it into the Blink triage queue (ie: mark the
+bug as Untriaged with component Blink).
+
 ### Infra Breakage
 
 If a bot turns purple rather than red, that indicates an infra failure of some
diff --git a/docs/ui/android/night_mode.md b/docs/ui/android/night_mode.md
index d6693be..26ae1bd7 100644
--- a/docs/ui/android/night_mode.md
+++ b/docs/ui/android/night_mode.md
@@ -144,7 +144,7 @@
 * Turn on power save mode (aka **battery saver**) on Android P+
 * Go to **Android Settings -> Developer options -> Night mode** on Android P
 * Go to **Android Settings -> Display -> Theme** on Android Q
-* [Set color scheme](https://cs.chromium.org/chromium/src/third_party/custom_tabs_client/src/customtabs/src/android/support/customtabs/CustomTabsIntent.java?) to `COLOR_SCHEME_DARK` on creating a `CustomTabsIntent.Builder`
+* [Set color scheme](https://cs.chromium.org/chromium/src/third_party/android_sdk/androidx_browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java?) to `COLOR_SCHEME_DARK` on creating a `CustomTabsIntent.Builder`
 
 Some tips:
 
diff --git a/extensions/browser/api/networking_private/networking_private_api.cc b/extensions/browser/api/networking_private/networking_private_api.cc
index b2d03fa..3a70339 100644
--- a/extensions/browser/api/networking_private/networking_private_api.cc
+++ b/extensions/browser/api/networking_private/networking_private_api.cc
@@ -486,9 +486,6 @@
     } else if (type == ::onc::network_type::kWiFi) {
       enabled_networks_list->AppendString(
           private_api::ToString(private_api::NETWORK_TYPE_WIFI));
-    } else if (type == ::onc::network_type::kWimax) {
-      enabled_networks_list->AppendString(
-          private_api::ToString(private_api::NETWORK_TYPE_WIMAX));
     } else if (type == ::onc::network_type::kCellular) {
       enabled_networks_list->AppendString(
           private_api::ToString(private_api::NETWORK_TYPE_CELLULAR));
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc
index a3f08646..73a9d1e 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -654,8 +654,6 @@
     network_list->AppendString(::onc::network_type::kEthernet);
   if (state_handler->IsTechnologyEnabled(NetworkTypePattern::WiFi()))
     network_list->AppendString(::onc::network_type::kWiFi);
-  if (state_handler->IsTechnologyEnabled(NetworkTypePattern::Wimax()))
-    network_list->AppendString(::onc::network_type::kWimax);
   if (state_handler->IsTechnologyEnabled(NetworkTypePattern::Cellular()))
     network_list->AppendString(::onc::network_type::kCellular);
 
@@ -678,9 +676,9 @@
 
   // For any technologies that we do not have a DeviceState entry for, append
   // an entry if the technology is available.
-  const char* technology_types[] = {
-      ::onc::network_type::kEthernet, ::onc::network_type::kWiFi,
-      ::onc::network_type::kWimax, ::onc::network_type::kCellular};
+  const char* technology_types[] = {::onc::network_type::kEthernet,
+                                    ::onc::network_type::kWiFi,
+                                    ::onc::network_type::kCellular};
   for (const char* technology : technology_types) {
     if (base::Contains(technologies_found, technology))
       continue;
diff --git a/extensions/browser/extension_util.cc b/extensions/browser/extension_util.cc
index 854ea5ae..2ad8528f 100644
--- a/extensions/browser/extension_util.cc
+++ b/extensions/browser/extension_util.cc
@@ -12,20 +12,11 @@
 #include "extensions/common/features/feature.h"
 #include "extensions/common/features/feature_provider.h"
 #include "extensions/common/manifest.h"
-#include "extensions/common/manifest_handlers/app_isolation_info.h"
 #include "extensions/common/manifest_handlers/incognito_info.h"
 
 namespace extensions {
 namespace util {
 
-bool SiteHasIsolatedStorage(const GURL& extension_site_url,
-                            content::BrowserContext* context) {
-  const Extension* extension = ExtensionRegistry::Get(context)->
-      enabled_extensions().GetExtensionOrAppByURL(extension_site_url);
-
-  return extension && AppIsolationInfo::HasIsolatedStorage(extension);
-}
-
 bool CanBeIncognitoEnabled(const Extension* extension) {
   return IncognitoInfo::IsIncognitoAllowed(extension) &&
          (!extension->is_platform_app() ||
diff --git a/extensions/browser/extension_util.h b/extensions/browser/extension_util.h
index d2a6531e..05fc35f8 100644
--- a/extensions/browser/extension_util.h
+++ b/extensions/browser/extension_util.h
@@ -23,11 +23,6 @@
 // chrome/browser/extensions/extension_util.h/cc that are only dependent on
 // extensions/ here.
 
-// Returns true if the site URL corresponds to an extension or app and has
-// isolated storage.
-bool SiteHasIsolatedStorage(const GURL& extension_site_url,
-                            content::BrowserContext* context);
-
 // Returns true if the extension can be enabled in incognito mode.
 bool CanBeIncognitoEnabled(const Extension* extension);
 
diff --git a/extensions/common/api/networking_onc.idl b/extensions/common/api/networking_onc.idl
index e1ac012..08da976d 100644
--- a/extensions/common/api/networking_onc.idl
+++ b/extensions/common/api/networking_onc.idl
@@ -4,7 +4,7 @@
 
 // <p>
 //   The <code>chrome.networking.onc</code> API is used for configuring
-//   network connections (Cellular, Ethernet, VPN, WiFi or WiMAX).
+//   network connections (Cellular, Ethernet, VPN or WiFi).
 //   This API is available in Chrome OS kiosk sessions.
 // </p>
 // <p>
@@ -52,7 +52,7 @@
   };
 
   enum NetworkType {
-    All, Cellular, Ethernet, Tether, VPN, Wireless, WiFi, WiMAX
+    All, Cellular, Ethernet, Tether, VPN, Wireless, WiFi
   };
 
   enum ProxySettingsType {
@@ -654,25 +654,12 @@
     DOMString? TetheringState;
   };
 
+  // Deprecated
   dictionary WiMAXProperties {
     // Whether the network should be connected automatically.
     boolean? AutoConnect;
     // The network EAP properties.
     EAPProperties? EAP;
-    // The network signal strength.
-    long? SignalStrength;
-  };
-
-  dictionary ManagedWiMAXProperties {
-    // See $(ref:WiMAXProperties.AutoConnect).
-    ManagedBoolean? AutoConnect;
-    // See $(ref:WiMAXProperties.SignalStrength).
-    long? SignalStrength;
-  };
-
-  dictionary WiMAXStateProperties {
-    // See $(ref:WiMAXProperties.SignalStrength).
-    long? SignalStrength;
   };
 
   dictionary NetworkConfigProperties {
@@ -696,7 +683,7 @@
     VPNProperties? VPN;
     // See $(ref:NetworkProperties.WiFi).
     WiFiProperties? WiFi;
-    // See $(ref:NetworkProperties.WiMAX).
+    // Deprecated.
     WiMAXProperties? WiMAX;
   };
 
@@ -754,8 +741,6 @@
     VPNProperties? VPN;
     // For WiFi networks, the network WiFi properties.
     WiFiProperties? WiFi;
-    // For WiMAX networks, the network WiMAX properties.
-    WiMAXProperties? WiMAX;
   };
 
   [noinline_doc]
@@ -800,8 +785,6 @@
     ManagedVPNProperties? VPN;
     // See $(ref:NetworkProperties.WiFi).
     ManagedWiFiProperties? WiFi;
-    // See $(ref:NetworkProperties.WiMAX).
-    ManagedWiMAXProperties? WiMAX;
   };
 
   dictionary NetworkStateProperties {
@@ -829,8 +812,6 @@
     VPNStateProperties? VPN;
     // See $(ref:NetworkProperties.WiFi).
     WiFiStateProperties? WiFi;
-    // See $(ref:NetworkProperties.WiMAX).
-    WiMAXStateProperties? WiMAX;
   };
 
   dictionary DeviceStateProperties {
@@ -846,8 +827,7 @@
     // The current state of the device.
     DeviceStateType State;
 
-    // The network type associated with the device (Cellular, Ethernet, WiFi, or
-    // WiMAX).
+    // The network type associated with the device (Cellular, Ethernet or WiFi).
     NetworkType Type;
   };
 
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl
index 071e5b6..86746db74 100644
--- a/extensions/common/api/networking_private.idl
+++ b/extensions/common/api/networking_private.idl
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // The <code>chrome.networkingPrivate</code> API is used for configuring
-// network connections (Cellular, Ethernet, VPN, WiFi or WiMAX). This private
+// network connections (Cellular, Ethernet, VPN or WiFi). This private
 // API is only valid if called from a browser or app associated with the
 // primary user. See the Open Network Configuration (ONC) documentation for
 // descriptions of properties:
@@ -58,7 +58,7 @@
   };
 
   enum NetworkType {
-    All, Cellular, Ethernet, Tether, VPN, Wireless, WiFi, WiMAX
+    All, Cellular, Ethernet, Tether, VPN, Wireless, WiFi
   };
 
   enum ProxySettingsType {
@@ -688,22 +688,6 @@
     DOMString? TetheringState;
   };
 
-  dictionary WiMAXProperties {
-    boolean? AutoConnect;
-    EAPProperties? EAP;
-    long? SignalStrength;
-  };
-
-  dictionary ManagedWiMAXProperties {
-    ManagedBoolean? AutoConnect;
-    ManagedEAPProperties? EAP;
-    long? SignalStrength;
-  };
-
-  dictionary WiMAXStateProperties {
-    long? SignalStrength;
-  };
-
   dictionary NetworkConfigProperties {
     CellularProperties? Cellular;
     EthernetProperties? Ethernet;
@@ -717,7 +701,6 @@
     NetworkType? Type;
     VPNProperties? VPN;
     WiFiProperties? WiFi;
-    WiMAXProperties? WiMAX;
   };
 
   dictionary NetworkProperties {
@@ -746,7 +729,6 @@
     NetworkType Type;
     VPNProperties? VPN;
     WiFiProperties? WiFi;
-    WiMAXProperties? WiMAX;
   };
 
   dictionary ManagedProperties {
@@ -772,7 +754,6 @@
     NetworkType Type;
     ManagedVPNProperties? VPN;
     ManagedWiFiProperties? WiFi;
-    ManagedWiMAXProperties? WiMAX;
   };
 
   dictionary NetworkStateProperties {
@@ -790,7 +771,6 @@
     NetworkType Type;
     VPNStateProperties? VPN;
     WiFiStateProperties? WiFi;
-    WiMAXStateProperties? WiMAX;
   };
 
   dictionary DeviceStateProperties {
@@ -806,8 +786,7 @@
     // The current state of the device.
     DeviceStateType State;
 
-    // The network type associated with the device (Cellular, Ethernet, WiFi, or
-    // WiMAX).
+    // The network type associated with the device (Cellular, Ethernet or WiFi).
     NetworkType Type;
 
     // Whether or not any managed networks are available/visible.
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index 98fcfb66..81ae89d 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -131,7 +131,7 @@
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   LazyInitialize();
 
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {web::WebThread::IO},
       base::BindOnce(
           &ChromeBrowserStateImplIOData::ClearNetworkingHistorySinceOnIOThread,
@@ -186,8 +186,9 @@
       profile_path_.Append(kIOSChromeNetworkPersistentStateFilename));
   network_json_store_ = new JsonPrefStore(
       network_json_store_filepath, std::unique_ptr<PrefFilter>(),
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
   network_json_store_->ReadPrefsAsync(nullptr);
 
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
index 71c3edf..78413945 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -110,7 +110,7 @@
                                                       pref_service);
 
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO});
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO});
 
   chrome_http_user_agent_settings_.reset(
       new IOSChromeHttpUserAgentSettings(pref_service));
@@ -297,7 +297,7 @@
   enable_metrics_.Init(metrics::prefs::kMetricsReportingEnabled,
                        GetApplicationContext()->GetLocalState());
   enable_metrics_.MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
 }
 
 bool ChromeBrowserStateIOData::GetMetricsEnabledStateOnIOThread() const {
@@ -348,8 +348,9 @@
     transport_security_persister_ =
         std::make_unique<net::TransportSecurityPersister>(
             transport_security_state_.get(), profile_params_->path,
-            base::CreateSequencedTaskRunnerWithTraits(
-                {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+            base::CreateSequencedTaskRunner(
+                {base::ThreadPool(), base::MayBlock(),
+                 base::TaskPriority::BEST_EFFORT,
                  base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
   }
 
@@ -418,10 +419,10 @@
   // ChromeBrowserStateIOData::IsHandledProtocol().
   bool set_protocol = job_factory->SetProtocolHandler(
       url::kFileScheme,
-      std::make_unique<net::FileProtocolHandler>(
-          base::CreateTaskRunnerWithTraits(
-              {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-               base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
+      std::make_unique<net::FileProtocolHandler>(base::CreateTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
   DCHECK(set_protocol);
 
   set_protocol = job_factory->SetProtocolHandler(
@@ -444,10 +445,9 @@
 
   if (!context_getters->empty()) {
     if (web::WebThread::IsThreadInitialized(web::WebThread::IO)) {
-      base::PostTaskWithTraits(
-          FROM_HERE, {web::WebThread::IO},
-          base::BindOnce(&NotifyContextGettersOfShutdownOnIO,
-                         std::move(context_getters)));
+      base::PostTask(FROM_HERE, {web::WebThread::IO},
+                     base::BindOnce(&NotifyContextGettersOfShutdownOnIO,
+                                    std::move(context_getters)));
     }
   }
 
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
index 7f6ef58..f503a53 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
@@ -137,8 +137,9 @@
   // this profile are executed in expected order (what was previously assured by
   // the FILE thread).
   scoped_refptr<base::SequencedTaskRunner> io_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN,
+           base::MayBlock()});
 
   std::unique_ptr<ChromeBrowserStateImpl> browser_state_impl(
       new ChromeBrowserStateImpl(io_task_runner, path));
@@ -190,9 +191,9 @@
   // Log the browser state size after a reasonable startup delay.
   base::FilePath path =
       browser_state->GetOriginalChromeBrowserState()->GetStatePath();
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&BrowserStateSizeTask, path),
       base::TimeDelta::FromSeconds(112));
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_removal_controller.mm b/ios/chrome/browser/browser_state/chrome_browser_state_removal_controller.mm
index 7b6d0e2..e2b6eb59 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_removal_controller.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_removal_controller.mm
@@ -143,8 +143,9 @@
 
   if (is_removing_browser_states) {
     SetHasBrowserStateBeenRemoved(true);
-    base::PostTaskWithTraits(
-        FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+    base::PostTask(
+        FROM_HERE,
+        {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
         base::BindOnce(&NukeBrowserStates, browser_states_to_nuke));
   }
 }
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc
index e7564e5..917822e 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc
@@ -107,7 +107,7 @@
   // BrowsingDataRemover will never be destroyed and the dialog will never be
   // closed. We must do this asynchronously in order to avoid reentrancy issues.
   if (!completion.is_null()) {
-    base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, completion);
+    base::PostTask(FROM_HERE, {web::WebThread::UI}, completion);
   }
 }
 
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index 31d270b..0a8d5c8e2 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -57,7 +57,7 @@
   // The cache for the incognito profile is in RAM.
   scoped_refptr<net::URLRequestContextGetter> getter =
       main_request_context_getter_;
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {web::WebThread::IO}, base::BindOnce(^{
         DCHECK_CURRENTLY_ON(web::WebThread::IO);
         net::HttpCache* cache = getter->GetURLRequestContext()
diff --git a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
index 784ade44..a7e15312 100644
--- a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
+++ b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
@@ -75,7 +75,7 @@
   bookmark_model->Load(
       browser_state->GetPrefs(), browser_state->GetStatePath(),
       browser_state->GetIOTaskRunner(),
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}));
+      base::CreateSingleThreadTaskRunner({web::WebThread::UI}));
   ios::BookmarkUndoServiceFactory::GetForBrowserState(browser_state)
       ->Start(bookmark_model.get());
   return bookmark_model;
@@ -85,7 +85,7 @@
   const base::FilePath& browser_state_path = context->GetStatePath();
   return std::make_unique<WebDataServiceWrapper>(
       browser_state_path, GetApplicationContext()->GetApplicationLocale(),
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}),
+      base::CreateSingleThreadTaskRunner({web::WebThread::UI}),
       base::DoNothing());
 }
 
@@ -135,8 +135,9 @@
     std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs,
     TestingFactories testing_factories,
     RefcountedTestingFactories refcounted_testing_factories)
-    : ChromeBrowserState(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+    : ChromeBrowserState(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       state_path_(path),
       prefs_(std::move(prefs)),
       testing_prefs_(nullptr),
@@ -280,7 +281,7 @@
 net::URLRequestContextGetter* TestChromeBrowserState::CreateRequestContext(
     ProtocolHandlerMap* protocol_handlers) {
   return new net::TestURLRequestContextGetter(
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
 }
 
 net::URLRequestContextGetter*
diff --git a/ios/chrome/browser/download/ar_quick_look_tab_helper.mm b/ios/chrome/browser/download/ar_quick_look_tab_helper.mm
index 2ec149ab..84ca77c 100644
--- a/ios/chrome/browser/download/ar_quick_look_tab_helper.mm
+++ b/ios/chrome/browser/download/ar_quick_look_tab_helper.mm
@@ -110,8 +110,9 @@
   // Take ownership of |download_task| and start the download.
   download_task_ = std::move(download_task);
   download_task_->AddObserver(this);
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&base::CreateDirectory, download_dir),
       base::BindOnce(&ARQuickLookTabHelper::DownloadWithDestinationDir,
                      AsWeakPtr(), download_dir, download_task_.get()));
@@ -154,8 +155,8 @@
     return;
   }
 
-  auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+  auto task_runner = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
   base::string16 file_name = download_task_->GetSuggestedFilename();
   base::FilePath path = destination_dir.Append(base::UTF16ToUTF8(file_name));
   auto writer = std::make_unique<net::URLFetcherFileWriter>(task_runner, path);
diff --git a/ios/chrome/browser/download/download_directory_util.cc b/ios/chrome/browser/download/download_directory_util.cc
index c1b1c53..9455596 100644
--- a/ios/chrome/browser/download/download_directory_util.cc
+++ b/ios/chrome/browser/download/download_directory_util.cc
@@ -29,7 +29,8 @@
 }
 
 void DeleteDownloadsDirectory() {
-  base::PostTaskWithTraits(FROM_HERE,
-                           {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-                           base::BindOnce(&DeleteDownloadsDirectorySync));
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+      base::BindOnce(&DeleteDownloadsDirectorySync));
 }
diff --git a/ios/chrome/browser/feature_engagement/tracker_factory_util.mm b/ios/chrome/browser/feature_engagement/tracker_factory_util.mm
index 785464c..6ae726c9 100644
--- a/ios/chrome/browser/feature_engagement/tracker_factory_util.mm
+++ b/ios/chrome/browser/feature_engagement/tracker_factory_util.mm
@@ -33,8 +33,8 @@
       ios::ChromeBrowserState::FromBrowserState(context);
 
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                       base::TaskPriority::BEST_EFFORT});
 
   base::FilePath storage_dir = browser_state->GetStatePath().Append(
       kIOSFeatureEngagementTrackerStorageDirname);
diff --git a/ios/chrome/browser/gcm/ios_chrome_gcm_profile_service_factory.cc b/ios/chrome/browser/gcm/ios_chrome_gcm_profile_service_factory.cc
index d9f040e..f294a4f 100644
--- a/ios/chrome/browser/gcm/ios_chrome_gcm_profile_service_factory.cc
+++ b/ios/chrome/browser/gcm/ios_chrome_gcm_profile_service_factory.cc
@@ -42,7 +42,7 @@
     web::BrowserState* context,
     base::WeakPtr<gcm::GCMProfileService> service,
     network::mojom::ProxyResolvingSocketFactoryRequest request) {
-  base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI})
+  base::CreateSingleThreadTaskRunner({web::WebThread::UI})
       ->PostTask(
           FROM_HERE,
           base::BindOnce(&RequestProxyResolvingSocketFactoryOnUIThread, context,
@@ -89,8 +89,9 @@
   DCHECK(!context->IsOffTheRecord());
 
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner(
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
   ios::ChromeBrowserState* browser_state =
       ios::ChromeBrowserState::FromBrowserState(context);
@@ -102,7 +103,7 @@
       GetProductCategoryForSubtypes(),
       IdentityManagerFactory::GetForBrowserState(browser_state),
       base::WrapUnique(new gcm::GCMClientFactory),
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}),
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}),
+      base::CreateSingleThreadTaskRunner({web::WebThread::UI}),
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}),
       blocking_task_runner);
 }
diff --git a/ios/chrome/browser/invalidation/ios_chrome_deprecated_profile_invalidation_provider_factory.mm b/ios/chrome/browser/invalidation/ios_chrome_deprecated_profile_invalidation_provider_factory.mm
index 08cc3ea..93e6f0a 100644
--- a/ios/chrome/browser/invalidation/ios_chrome_deprecated_profile_invalidation_provider_factory.mm
+++ b/ios/chrome/browser/invalidation/ios_chrome_deprecated_profile_invalidation_provider_factory.mm
@@ -51,7 +51,7 @@
     ios::ChromeBrowserState* browser_state,
     base::WeakPtr<TiclInvalidationService> service,
     network::mojom::ProxyResolvingSocketFactoryRequest request) {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {web::WebThread::UI},
       base::BindOnce(&RequestProxyResolvingSocketFactoryOnUIThread,
                      browser_state, std::move(service), std::move(request)));
@@ -103,7 +103,7 @@
       IOSChromeGCMProfileServiceFactory::GetForBrowserState(browser_state)
           ->driver(),
       base::BindRepeating(&RequestProxyResolvingSocketFactory, browser_state),
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}),
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}),
       browser_state->GetSharedURLLoaderFactory(),
       GetApplicationContext()->GetNetworkConnectionTracker()));
   service->Init(
diff --git a/ios/chrome/browser/net/chrome_cookie_store_ios_client.mm b/ios/chrome/browser/net/chrome_cookie_store_ios_client.mm
index a644690..d638a5e 100644
--- a/ios/chrome/browser/net/chrome_cookie_store_ios_client.mm
+++ b/ios/chrome/browser/net/chrome_cookie_store_ios_client.mm
@@ -16,5 +16,5 @@
 
 scoped_refptr<base::SequencedTaskRunner>
 ChromeCookieStoreIOSClient::GetTaskRunner() const {
-  return base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO});
+  return base::CreateSingleThreadTaskRunner({web::WebThread::IO});
 }
diff --git a/ios/chrome/browser/net/cookie_util.mm b/ios/chrome/browser/net/cookie_util.mm
index e899d4c..f98a14e4 100644
--- a/ios/chrome/browser/net/cookie_util.mm
+++ b/ios/chrome/browser/net/cookie_util.mm
@@ -45,10 +45,9 @@
     net::CookieCryptoDelegate* crypto_delegate) {
   return scoped_refptr<net::SQLitePersistentCookieStore>(
       new net::SQLitePersistentCookieStore(
-          path,
-          base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}),
-          base::CreateSequencedTaskRunnerWithTraits(
-              {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
+          path, base::CreateSingleThreadTaskRunner({web::WebThread::IO}),
+          base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                           base::TaskPriority::BEST_EFFORT}),
           restore_old_session_cookies, crypto_delegate));
 }
 
@@ -139,11 +138,11 @@
 void ClearSessionCookies(ios::ChromeBrowserState* browser_state) {
   scoped_refptr<net::URLRequestContextGetter> getter =
       browser_state->GetRequestContext();
-  base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, base::BindOnce(^{
-                             getter->GetURLRequestContext()
-                                 ->cookie_store()
-                                 ->DeleteSessionCookiesAsync(base::DoNothing());
-                           }));
+  base::PostTask(FROM_HERE, {web::WebThread::IO}, base::BindOnce(^{
+                   getter->GetURLRequestContext()
+                       ->cookie_store()
+                       ->DeleteSessionCookiesAsync(base::DoNothing());
+                 }));
 }
 
 }  // namespace cookie_util
diff --git a/ios/chrome/browser/net/cookie_util_unittest.mm b/ios/chrome/browser/net/cookie_util_unittest.mm
index 9b4c01d..d15ae00 100644
--- a/ios/chrome/browser/net/cookie_util_unittest.mm
+++ b/ios/chrome/browser/net/cookie_util_unittest.mm
@@ -7,6 +7,7 @@
 #import <Foundation/Foundation.h>
 
 #include "base/bind.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
@@ -102,7 +103,8 @@
   std::string cookie_line = base::SysNSStringToUTF8(cookie_name) + "=" +
                             base::SysNSStringToUTF8(cookie_value);
   cookie_store->SetCookieWithOptionsAsync(
-      test_url, cookie_line, options, net::CookieStore::SetCookiesCallback());
+      test_url, cookie_line, options, base::nullopt /* server_time */,
+      net::CookieStore::SetCookiesCallback());
 
   __block NSArray<NSHTTPCookie*>* result_cookies = nil;
   __block bool callback_called = false;
diff --git a/ios/chrome/browser/net/ios_chrome_http_user_agent_settings.mm b/ios/chrome/browser/net/ios_chrome_http_user_agent_settings.mm
index baba01a2..07ddc11e 100644
--- a/ios/chrome/browser/net/ios_chrome_http_user_agent_settings.mm
+++ b/ios/chrome/browser/net/ios_chrome_http_user_agent_settings.mm
@@ -24,7 +24,7 @@
   last_http_accept_language_ =
       net::HttpUtil::GenerateAcceptLanguageHeader(last_pref_accept_language_);
   pref_accept_language_.MoveToSequence(
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
 }
 
 IOSChromeHttpUserAgentSettings::~IOSChromeHttpUserAgentSettings() {
diff --git a/ios/chrome/browser/net/ios_chrome_network_delegate.cc b/ios/chrome/browser/net/ios_chrome_network_delegate.cc
index f9b81e6..46dcec9 100644
--- a/ios/chrome/browser/net/ios_chrome_network_delegate.cc
+++ b/ios/chrome/browser/net/ios_chrome_network_delegate.cc
@@ -71,7 +71,7 @@
   if (enable_do_not_track) {
     enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service);
     enable_do_not_track->MoveToSequence(
-        base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}));
+        base::CreateSingleThreadTaskRunner({web::WebThread::IO}));
   }
 }
 
diff --git a/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc
index 916daf3..6ccfee6 100644
--- a/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc
+++ b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc
@@ -119,7 +119,7 @@
 
 scoped_refptr<base::SingleThreadTaskRunner>
 IOSChromeURLRequestContextGetter::GetNetworkTaskRunner() const {
-  return base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO});
+  return base::CreateSingleThreadTaskRunner({web::WebThread::IO});
 }
 
 // static
diff --git a/ios/chrome/browser/omaha/omaha_service.mm b/ios/chrome/browser/omaha/omaha_service.mm
index 07fd502..931bbc8 100644
--- a/ios/chrome/browser/omaha/omaha_service.mm
+++ b/ios/chrome/browser/omaha/omaha_service.mm
@@ -308,9 +308,9 @@
   DCHECK(!result->url_loader_factory_info_ || !result->url_loader_factory_);
   result->url_loader_factory_info_ = std::move(url_loader_factory_info);
   result->locale_lang_ = GetApplicationContext()->GetApplicationLocale();
-  base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO},
-                           base::BindOnce(&OmahaService::SendOrScheduleNextPing,
-                                          base::Unretained(result)));
+  base::PostTask(FROM_HERE, {web::WebThread::IO},
+                 base::BindOnce(&OmahaService::SendOrScheduleNextPing,
+                                base::Unretained(result)));
 }
 
 OmahaService::OmahaService()
@@ -390,10 +390,9 @@
 // static
 void OmahaService::GetDebugInformation(
     const base::Callback<void(base::DictionaryValue*)> callback) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {web::WebThread::IO},
-      base::BindOnce(&OmahaService::GetDebugInformationOnIOThread,
-                     base::Unretained(GetInstance()), callback));
+  base::PostTask(FROM_HERE, {web::WebThread::IO},
+                 base::BindOnce(&OmahaService::GetDebugInformationOnIOThread,
+                                base::Unretained(GetInstance()), callback));
 }
 
 // static
@@ -651,9 +650,8 @@
   // Send notification for updates if needed.
   UpgradeRecommendedDetails* details = [delegate upgradeRecommendedDetails];
   if (details) {
-    base::PostTaskWithTraits(
-        FROM_HERE, {web::WebThread::UI},
-        base::BindOnce(upgrade_recommended_callback_, *details));
+    base::PostTask(FROM_HERE, {web::WebThread::UI},
+                   base::BindOnce(upgrade_recommended_callback_, *details));
   }
 }
 
@@ -682,9 +680,8 @@
                         (timer_.desired_run_time() - base::TimeTicks::Now())));
 
   // Sending the value to the callback.
-  base::PostTaskWithTraits(
-      FROM_HERE, {web::WebThread::UI},
-      base::BindOnce(callback, base::Owned(result.release())));
+  base::PostTask(FROM_HERE, {web::WebThread::UI},
+                 base::BindOnce(callback, base::Owned(result.release())));
 }
 
 bool OmahaService::IsNextPingInstallRetry() {
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc b/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc
index 3c3ef87..e66577ee 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc
+++ b/ios/chrome/browser/passwords/ios_chrome_password_store_factory.cc
@@ -89,8 +89,8 @@
   // TODO(crbug.com/741660): Create the task runner inside password_manager
   // component instead.
   scoped_refptr<base::SequencedTaskRunner> db_task_runner(
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
+      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                       base::TaskPriority::USER_VISIBLE}));
 
   scoped_refptr<password_manager::PasswordStore> store =
       new password_manager::PasswordStoreDefault(std::move(login_db));
diff --git a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
index 66944d48..627cd5d 100644
--- a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
+++ b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
@@ -283,9 +283,9 @@
           .DirName();
 
   base::FilePath offline_path = entry->DistilledPath();
-  base::PostTaskWithTraitsAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(&GetOfflineData, offline_root, offline_path),
       base::BindOnce(&OfflinePageTabHelper::LoadData, base::Unretained(this),
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.cc b/ios/chrome/browser/reading_list/reading_list_download_service.cc
index 416ba956..e5aa661 100644
--- a/ios/chrome/browser/reading_list/reading_list_download_service.cc
+++ b/ios/chrome/browser/reading_list/reading_list_download_service.cc
@@ -169,9 +169,9 @@
         break;
     }
   }
-  base::PostTaskWithTraitsAndReply(
+  base::PostTaskAndReply(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::Bind(&::CleanUpFiles, OfflineRoot(), processed_directories),
       base::Bind(&ReadingListDownloadService::DownloadUnprocessedEntries,
diff --git a/ios/chrome/browser/reading_list/url_downloader.cc b/ios/chrome/browser/reading_list/url_downloader.cc
index 7fc4e33f..74aa4dfb 100644
--- a/ios/chrome/browser/reading_list/url_downloader.cc
+++ b/ios/chrome/browser/reading_list/url_downloader.cc
@@ -59,8 +59,9 @@
       base_directory_(chrome_profile_path),
       mime_type_(),
       url_loader_factory_(std::move(url_loader_factory)),
-      task_runner_(base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      task_runner_(base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
       task_tracker_() {}
 
diff --git a/ios/chrome/browser/sessions/session_service_ios.mm b/ios/chrome/browser/sessions/session_service_ios.mm
index 3f1ee2e9..f4578b2 100644
--- a/ios/chrome/browser/sessions/session_service_ios.mm
+++ b/ios/chrome/browser/sessions/session_service_ios.mm
@@ -81,8 +81,9 @@
 
 - (instancetype)init {
   scoped_refptr<base::SequencedTaskRunner> taskRunner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      base::CreateSequencedTaskRunner(
+          {base::ThreadPool(), base::MayBlock(),
+           base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
   return [self initWithTaskRunner:taskRunner];
 }
diff --git a/ios/chrome/browser/share_extension/share_extension_item_receiver.mm b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
index c7a1f2b..d688e057 100644
--- a/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
+++ b/ios/chrome/browser/share_extension/share_extension_item_receiver.mm
@@ -132,8 +132,9 @@
   if (self) {
     _readingListModel = readingListModel;
     _bookmarkModel = bookmarkModel;
-    _taskRunner = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+    _taskRunner =
+        base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                         base::TaskPriority::BEST_EFFORT});
 
     [[NSNotificationCenter defaultCenter]
         addObserver:self
@@ -181,9 +182,9 @@
   }
 
   __weak ShareExtensionItemReceiver* weakSelf = self;
-  base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
-                             [weakSelf readingListFolderCreated];
-                           }));
+  base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+                   [weakSelf readingListFolderCreated];
+                 }));
 }
 
 - (void)readingListFolderCreated {
@@ -295,8 +296,8 @@
                             }));
     }
   };
-  base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI},
-                           base::BindOnce(processEntryBlock));
+  base::PostTask(FROM_HERE, {web::WebThread::UI},
+                 base::BindOnce(processEntryBlock));
   return YES;
 }
 
@@ -392,9 +393,9 @@
 
   if ([files count]) {
     __weak ShareExtensionItemReceiver* weakSelf = self;
-    base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
-                               [weakSelf entriesReceived:files];
-                             }));
+    base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+                     [weakSelf entriesReceived:files];
+                   }));
   }
 }
 
@@ -411,11 +412,11 @@
     _taskRunner->PostTask(FROM_HERE, base::BindOnce(^{
                             [weakSelf handleFileAtURL:fileURL
                                        withCompletion:^{
-                                         base::PostTaskWithTraits(
-                                             FROM_HERE, {web::WebThread::UI},
-                                             base::BindOnce(^{
-                                               batchToken.reset();
-                                             }));
+                                         base::PostTask(FROM_HERE,
+                                                        {web::WebThread::UI},
+                                                        base::BindOnce(^{
+                                                          batchToken.reset();
+                                                        }));
                                        }];
                           }));
   }
diff --git a/ios/chrome/browser/signin/authentication_service_unittest.mm b/ios/chrome/browser/signin/authentication_service_unittest.mm
index dcb6ab8c..bfa5224 100644
--- a/ios/chrome/browser/signin/authentication_service_unittest.mm
+++ b/ios/chrome/browser/signin/authentication_service_unittest.mm
@@ -88,6 +88,9 @@
     AuthenticationServiceFactory::CreateAndInitializeForBrowserState(
         browser_state_.get(),
         std::make_unique<AuthenticationServiceDelegateFake>());
+    // Account ID migration is done on iOS.
+    DCHECK_EQ(signin::IdentityManager::MIGRATION_DONE,
+              identity_manager()->GetAccountIdMigrationState());
   }
 
   std::unique_ptr<sync_preferences::PrefServiceSyncable> CreatePrefService() {
@@ -110,10 +113,6 @@
     authentication_service()->StoreAccountsInPrefs();
   }
 
-  void MigrateAccountsStoredInPrefsIfNeeded() {
-    authentication_service()->MigrateAccountsStoredInPrefsIfNeeded();
-  }
-
   std::vector<std::string> GetAccountsInPrefs() {
     return authentication_service()->GetAccountsInPrefs();
   }
@@ -330,20 +329,8 @@
   accounts = GetAccountsInPrefs();
   ASSERT_EQ(2u, accounts.size());
 
-  switch (identity_manager()->GetAccountIdMigrationState()) {
-    case signin::IdentityManager::MIGRATION_NOT_STARTED:
-      EXPECT_EQ("foo2@foo.com", accounts[0]);
-      EXPECT_EQ("foo@foo.com", accounts[1]);
-      break;
-    case signin::IdentityManager::MIGRATION_IN_PROGRESS:
-    case signin::IdentityManager::MIGRATION_DONE:
       EXPECT_EQ("foo2ID", accounts[0]);
       EXPECT_EQ("fooID", accounts[1]);
-      break;
-    case signin::IdentityManager::NUM_MIGRATION_STATES:
-      FAIL() << "NUM_MIGRATION_STATES is not a real migration state.";
-      break;
-  }
 }
 
 TEST_F(AuthenticationServiceTest,
@@ -363,20 +350,8 @@
   std::sort(accounts.begin(), accounts.end(), account_compare_func);
   ASSERT_EQ(2u, accounts.size());
 
-  switch (identity_manager()->GetAccountIdMigrationState()) {
-    case signin::IdentityManager::MIGRATION_NOT_STARTED:
-      EXPECT_EQ("foo2@foo.com", accounts[0].account_id);
-      EXPECT_EQ("foo@foo.com", accounts[1].account_id);
-      break;
-    case signin::IdentityManager::MIGRATION_IN_PROGRESS:
-    case signin::IdentityManager::MIGRATION_DONE:
       EXPECT_EQ("foo2ID", accounts[0].account_id);
       EXPECT_EQ("fooID", accounts[1].account_id);
-      break;
-    case signin::IdentityManager::NUM_MIGRATION_STATES:
-      FAIL() << "NUM_MIGRATION_STATES is not a real migration state.";
-      break;
-  }
 
   // Simulate a switching to background and back to foreground, triggering a
   // credentials reload.
@@ -388,22 +363,9 @@
   accounts = identity_manager()->GetAccountsWithRefreshTokens();
   std::sort(accounts.begin(), accounts.end(), account_compare_func);
   ASSERT_EQ(3u, accounts.size());
-  switch (identity_manager()->GetAccountIdMigrationState()) {
-    case signin::IdentityManager::MIGRATION_NOT_STARTED:
-      EXPECT_EQ("foo2@foo.com", accounts[0].account_id);
-      EXPECT_EQ("foo3@foo.com", accounts[1].account_id);
-      EXPECT_EQ("foo@foo.com", accounts[2].account_id);
-      break;
-    case signin::IdentityManager::MIGRATION_IN_PROGRESS:
-    case signin::IdentityManager::MIGRATION_DONE:
       EXPECT_EQ("foo2ID", accounts[0].account_id);
       EXPECT_EQ("foo3ID", accounts[1].account_id);
       EXPECT_EQ("fooID", accounts[2].account_id);
-      break;
-    case signin::IdentityManager::NUM_MIGRATION_STATES:
-      FAIL() << "NUM_MIGRATION_STATES is not a real migration state.";
-      break;
-  }
 }
 
 TEST_F(AuthenticationServiceTest, HaveAccountsNotChangedDefault) {
@@ -474,56 +436,6 @@
   EXPECT_FALSE(authentication_service()->IsAuthenticated());
 }
 
-TEST_F(AuthenticationServiceTest, MigrateAccountsStoredInPref) {
-  if (identity_manager()->GetAccountIdMigrationState() ==
-      signin::IdentityManager::MIGRATION_NOT_STARTED) {
-    // The account tracker is not migratable. Skip the test as the accounts
-    // cannot be migrated.
-    return;
-  }
-
-  // Force the migration state to MIGRATION_NOT_STARTED before signing in.
-  browser_state_->GetPrefs()->SetInteger(
-      prefs::kAccountIdMigrationState,
-      signin::IdentityManager::MIGRATION_NOT_STARTED);
-  browser_state_->GetPrefs()->SetBoolean(prefs::kSigninLastAccountsMigrated,
-                                         false);
-
-  // Sign in user emails as account ids.
-  SetExpectationsForSignIn();
-  authentication_service()->SignIn(identity(0));
-  std::vector<std::string> accounts_in_prefs = GetAccountsInPrefs();
-  ASSERT_EQ(2U, accounts_in_prefs.size());
-  EXPECT_EQ("foo2@gmail.com", accounts_in_prefs[0]);
-  EXPECT_EQ("foo@gmail.com", accounts_in_prefs[1]);
-
-  // Migrate the accounts.
-  browser_state_->GetPrefs()->SetInteger(
-      prefs::kAccountIdMigrationState, signin::IdentityManager::MIGRATION_DONE);
-
-  // Reload all credentials to find account info with the refresh token.
-  // If it tries to find refresh token with gaia ID after
-  // AccountTrackerService::Initialize(), it fails because account ids are
-  // updated with gaia ID from email at MigrateToGaiaId. As IdentityManager
-  // needs refresh token to find account info, it reloads all credentials.
-  identity_manager()
-      ->GetDeviceAccountsSynchronizer()
-      ->ReloadAllAccountsFromSystem();
-
-  // Actually migrate the accounts in prefs.
-  MigrateAccountsStoredInPrefsIfNeeded();
-  std::vector<std::string> migrated_accounts_in_prefs = GetAccountsInPrefs();
-  ASSERT_EQ(2U, migrated_accounts_in_prefs.size());
-  EXPECT_EQ("foo2ID", migrated_accounts_in_prefs[0]);
-  EXPECT_EQ("fooID", migrated_accounts_in_prefs[1]);
-  EXPECT_TRUE(browser_state_->GetPrefs()->GetBoolean(
-      prefs::kSigninLastAccountsMigrated));
-
-  // Calling migrate after the migration is done is a no-op.
-  MigrateAccountsStoredInPrefsIfNeeded();
-  EXPECT_EQ(migrated_accounts_in_prefs, GetAccountsInPrefs());
-}
-
 // Tests that MDM errors are correctly cleared on foregrounding, sending
 // notifications that the state of error has changed.
 TEST_F(AuthenticationServiceTest, MDMErrorsClearedOnForeground) {
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index be67f57..3f39cbe 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -284,8 +284,9 @@
     cacheDirectory_ = cacheDirectory;
     snapshotsScale_ = snapshotsScale;
 
-    taskRunner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+    taskRunner_ =
+        base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                         base::TaskPriority::USER_VISIBLE});
 
     _observers = [SnapshotCacheObservers observers];
     _markedIDs = [[NSMutableSet alloc] init];
diff --git a/ios/chrome/browser/snapshots/snapshot_generator.mm b/ios/chrome/browser/snapshots/snapshot_generator.mm
index 405d813..75500fa 100644
--- a/ios/chrome/browser/snapshots/snapshot_generator.mm
+++ b/ios/chrome/browser/snapshots/snapshot_generator.mm
@@ -138,10 +138,9 @@
 
   if (![self canTakeSnapshot]) {
     if (completion) {
-      base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI},
-                               base::BindOnce(^{
-                                 completion(nil);
-                               }));
+      base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+                       completion(nil);
+                     }));
     }
     return;
   }
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
index c2914ddc..debc3810 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
@@ -144,7 +144,7 @@
         break;
 
       bool was_loading = was_loading_during_last_snapshot_;
-      base::PostDelayedTaskWithTraits(
+      base::PostDelayedTask(
           FROM_HERE, {web::WebThread::UI},
           base::BindOnce(
               &SnapshotTabHelper::UpdateSnapshotWithCallback,
diff --git a/ios/chrome/browser/snapshots/snapshots_util.mm b/ios/chrome/browser/snapshots/snapshots_util.mm
index 922f2c3..b940c52 100644
--- a/ios/chrome/browser/snapshots/snapshots_util.mm
+++ b/ios/chrome/browser/snapshots/snapshots_util.mm
@@ -40,8 +40,9 @@
   // list of snapshots stored on the device can't be obtained programmatically.
   std::vector<base::FilePath> snapshots_paths;
   GetSnapshotsPaths(&snapshots_paths);
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&DeleteAllFiles, std::move(snapshots_paths)),
       std::move(callback));
 }
diff --git a/ios/chrome/browser/sync/glue/sync_start_util.cc b/ios/chrome/browser/sync/glue/sync_start_util.cc
index cecc6646..5e4d9eb9 100644
--- a/ios/chrome/browser/sync/glue/sync_start_util.cc
+++ b/ios/chrome/browser/sync/glue/sync_start_util.cc
@@ -47,7 +47,7 @@
 
 void StartSyncProxy(const base::FilePath& browser_state_path,
                     syncer::ModelType type) {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE, {web::WebThread::UI},
       base::BindOnce(&StartSyncOnUIThread, browser_state_path, type));
 }
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 5be5093..a1ae124 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -108,9 +108,8 @@
 
   component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl(
       this, ::GetChannel(), prefs::kSavingBrowserHistoryDisabled,
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}),
-      db_thread_, profile_web_data_service_, account_web_data_service_,
-      password_store_,
+      base::CreateSingleThreadTaskRunner({web::WebThread::UI}), db_thread_,
+      profile_web_data_service_, account_web_data_service_, password_store_,
       ios::BookmarkSyncServiceFactory::GetForBrowserState(browser_state_)));
 }
 
@@ -309,7 +308,7 @@
       return new syncer::SequencedModelWorker(db_thread_, syncer::GROUP_DB);
     case syncer::GROUP_UI:
       return new syncer::UIModelWorker(
-          base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::UI}));
+          base::CreateSingleThreadTaskRunner({web::WebThread::UI}));
     case syncer::GROUP_PASSIVE:
       return new syncer::PassiveModelWorker();
     case syncer::GROUP_PASSWORD: {
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory.cc b/ios/chrome/browser/sync/profile_sync_service_factory.cc
index 3012314..a073f033 100644
--- a/ios/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/ios/chrome/browser/sync/profile_sync_service_factory.cc
@@ -65,10 +65,9 @@
 void UpdateNetworkTime(const base::Time& network_time,
                        const base::TimeDelta& resolution,
                        const base::TimeDelta& latency) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {web::WebThread::UI},
-      base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time, resolution,
-                     latency, base::TimeTicks::Now()));
+  base::PostTask(FROM_HERE, {web::WebThread::UI},
+                 base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time,
+                                resolution, latency, base::TimeTicks::Now()));
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 944c089..864c5c2e 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -654,7 +654,7 @@
   // active sessions.
   CleanCertificatePolicyCache(
       &_clearPoliciesTaskTracker,
-      base::CreateSingleThreadTaskRunnerWithTraits({web::WebThread::IO}),
+      base::CreateSingleThreadTaskRunner({web::WebThread::IO}),
       web::BrowserState::GetCertificatePolicyCache(_browserState),
       _webStateList.get());
 
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn
index 37c276f..6cbf9ec 100644
--- a/ios/chrome/browser/ui/bookmarks/BUILD.gn
+++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -92,11 +92,11 @@
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:presentation",
     "//ios/chrome/browser/ui/table_view:styler",
-    "//ios/chrome/browser/ui/table_view/resources:placeholder_image_tint_color",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/undo",
     "//ios/chrome/browser/url_loading",
     "//ios/chrome/browser/web_state_list",
+    "//ios/chrome/common/colors",
     "//ios/chrome/common/favicon",
     "//ios/chrome/common/ui_util",
     "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_empty_background.mm b/ios/chrome/browser/ui/bookmarks/bookmark_empty_background.mm
index 94c65cbe..9cc8446 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_empty_background.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_empty_background.mm
@@ -39,7 +39,7 @@
     UIImage* image = [[UIImage imageNamed:@"bookmark_empty_star"]
         imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
     UIImageView* imageView = [[UIImageView alloc] initWithImage:image];
-    imageView.tintColor = [UIColor colorNamed:@"placeholder_image_tint_color"];
+    imageView.tintColor = [UIColor colorNamed:kPlaceholderImageTintColor];
 
     // The explanatory text label.
     self.textLabel = [[UILabel alloc] init];
diff --git a/ios/chrome/browser/ui/bubble/BUILD.gn b/ios/chrome/browser/ui/bubble/BUILD.gn
index 68927677..9794d5a 100644
--- a/ios/chrome/browser/ui/bubble/BUILD.gn
+++ b/ios/chrome/browser/ui/bubble/BUILD.gn
@@ -29,6 +29,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common",
+    "//ios/chrome/common/colors",
     "//ios/third_party/material_components_ios",
     "//net",
     "//ui/base",
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm
index 3192606..d293aa09 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -9,6 +9,7 @@
 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #include "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -17,10 +18,9 @@
 
 
 namespace {
-const int kBubbleColor = 0x4285F4;
 // The color of the bubble (both circular background and arrow).
 UIColor* BubbleColor() {
-  return UIColorFromRGB(kBubbleColor);
+  return [UIColor colorNamed:kBlueColor];
 }
 
 // The corner radius of the bubble's background, which causes the ends of the
@@ -63,6 +63,8 @@
 @property(nonatomic, strong, readonly) UIView* background;
 // Triangular arrow that points to the target UI element.
 @property(nonatomic, strong, readonly) UIView* arrow;
+// Triangular shape, the backing layer for the arrow.
+@property(nonatomic, weak) CAShapeLayer* arrowLayer;
 @property(nonatomic, assign, readonly) BubbleArrowDirection direction;
 @property(nonatomic, assign, readonly) BubbleAlignment alignment;
 // Indicate whether view properties need to be added as subviews of the bubble.
@@ -150,6 +152,7 @@
     [layer setPath:path.CGPath];
     [layer setFillColor:BubbleColor().CGColor];
     [arrow.layer addSublayer:layer];
+    _arrowLayer = layer;
     [arrow setTranslatesAutoresizingMaskIntoConstraints:NO];
     _arrow = arrow;
   }
@@ -164,7 +167,7 @@
   UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero];
   [label setText:text];
   [label setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
-  [label setTextColor:[UIColor whiteColor]];
+  [label setTextColor:[UIColor colorNamed:kSolidButtonTextColor]];
   [label setTextAlignment:NSTextAlignmentCenter];
   [label setNumberOfLines:0];
   [label setLineBreakMode:NSLineBreakByWordWrapping];
@@ -347,6 +350,21 @@
   return optimalSize;
 }
 
+- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
+  [super traitCollectionDidChange:previousTraitCollection];
+#if defined(__IPHONE_13_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0)
+  if (@available(iOS 13, *)) {
+    if ([self.traitCollection
+            hasDifferentColorAppearanceComparedToTraitCollection:
+                previousTraitCollection]) {
+      UIColor* resolvedColor =
+          [BubbleColor() resolvedColorWithTraitCollection:self.traitCollection];
+      self.arrowLayer.fillColor = resolvedColor.CGColor;
+    }
+  }
+#endif
+}
+
 #pragma mark - Private sizes
 
 // The minimum bubble width is two times the bubble alignment offset, which
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.mm b/ios/chrome/browser/ui/download/download_manager_mediator.mm
index 580eb74..c981e4c 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_mediator.mm
@@ -58,8 +58,9 @@
   // "Start Download" button.
   [consumer_ setState:kDownloadManagerStateInProgress];
 
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
       base::BindOnce(&base::CreateDirectory, download_dir),
       base::BindOnce(&DownloadManagerMediator::DownloadWithDestinationDir,
                      weak_ptr_factory_.GetWeakPtr(), download_dir, task_));
@@ -79,8 +80,8 @@
     return;
   }
 
-  auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+  auto task_runner = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT});
   base::string16 file_name = task_->GetSuggestedFilename();
   base::FilePath path = destination_dir.Append(base::UTF16ToUTF8(file_name));
   auto writer = std::make_unique<net::URLFetcherFileWriter>(task_runner, path);
diff --git a/ios/chrome/browser/ui/first_run/first_run_util.mm b/ios/chrome/browser/ui/first_run/first_run_util.mm
index 51b823f..28eaaa4e 100644
--- a/ios/chrome/browser/ui/first_run/first_run_util.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_util.mm
@@ -145,9 +145,10 @@
     ios::ChromeBrowserState* browserState,
     BOOL sign_in_attempted,
     BOOL has_sso_account) {
-  base::PostTaskWithTraits(FROM_HERE,
-                           {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-                           base::BindOnce(&CreateSentinel));
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+      base::BindOnce(&CreateSentinel));
   RecordFirstRunMetricsInternal(browserState, sign_in_attempted,
                                 has_sso_account);
 }
diff --git a/ios/chrome/browser/ui/image_util/image_copier.mm b/ios/chrome/browser/ui/image_util/image_copier.mm
index ff0625ae..03d5d5be 100644
--- a/ios/chrome/browser/ui/image_util/image_copier.mm
+++ b/ios/chrome/browser/ui/image_util/image_copier.mm
@@ -147,7 +147,7 @@
                  style:UIAlertActionStyleCancel];
 
   // Delays launching alert by |kAlertDelayInMs|.
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
         // Checks that the copy has not finished yet.
         if (callbackID == weakSelf.activeID) {
diff --git a/ios/chrome/browser/ui/image_util/image_saver.mm b/ios/chrome/browser/ui/image_util/image_saver.mm
index 55161de..226ff12 100644
--- a/ios/chrome/browser/ui/image_util/image_saver.mm
+++ b/ios/chrome/browser/ui/image_util/image_saver.mm
@@ -124,9 +124,9 @@
 - (void)saveImage:(NSData*)data
     withFileExtension:(NSString*)fileExtension
            completion:(void (^)(BOOL, NSError*))completion {
-  base::PostTaskWithTraits(
+  base::PostTask(
       FROM_HERE,
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
       base::BindOnce(^{
         base::ScopedBlockingCall scoped_blocking_call(
@@ -145,14 +145,16 @@
           return;
         }
 
-        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
-          [PHAssetChangeRequest
-              creationRequestForAssetFromImageAtFileURL:fileURL];
-        }
+        [[PHPhotoLibrary sharedPhotoLibrary]
+            performChanges:^{
+              [PHAssetChangeRequest
+                  creationRequestForAssetFromImageAtFileURL:fileURL];
+            }
             completionHandler:^(BOOL success, NSError* error) {
-              base::PostTaskWithTraits(
+              base::PostTask(
                   FROM_HERE,
-                  {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+                  {base::ThreadPool(), base::MayBlock(),
+                   base::TaskPriority::BEST_EFFORT,
                    base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
                   base::BindOnce(^{
                     base::ScopedBlockingCall scoped_blocking_call(
diff --git a/ios/chrome/browser/ui/ntp/ntp_tile_saver.mm b/ios/chrome/browser/ui/ntp/ntp_tile_saver.mm
index f8c34e5..ce8323c 100644
--- a/ios/chrome/browser/ui/ntp/ntp_tile_saver.mm
+++ b/ios/chrome/browser/ui/ntp/ntp_tile_saver.mm
@@ -127,8 +127,9 @@
   }
   UpdateTileList(most_visited_data);
 
-  base::PostTaskWithTraitsAndReply(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTaskAndReply(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(&ClearOutdatedIcons, most_visited_data,
                      favicons_directory),
       base::BindOnce(
@@ -207,9 +208,10 @@
             [imageData writeToURL:fileURL atomically:YES];
           });
 
-          base::PostTaskWithTraits(
-              FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-              std::move(writeImage));
+          base::PostTask(FROM_HERE,
+                         {base::ThreadPool(), base::MayBlock(),
+                          base::TaskPriority::BEST_EFFORT},
+                         std::move(writeImage));
         } else {
           NSDictionary* tiles = ReadSavedMostVisited();
           NTPTile* tile = [tiles objectForKey:siteNSURL];
@@ -232,9 +234,10 @@
             [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
           });
 
-          base::PostTaskWithTraits(
-              FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-              std::move(removeImage));
+          base::PostTask(FROM_HERE,
+                         {base::ThreadPool(), base::MayBlock(),
+                          base::TaskPriority::BEST_EFFORT},
+                         std::move(removeImage));
         }
       };
 
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
index a45d707b..754eb31 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -105,11 +105,6 @@
 }
 
 - (void)testCopyPaste {
-  // TODO(crbug.com/989550) Disable broken system callout tests on Xc11b5.
-  if (@available(iOS 13, *)) {
-    EARL_GREY_TEST_DISABLED(@"Test disabled on iOS13.");
-  }
-
   [self openPage1];
 
   // Long pressing should allow copying.
@@ -146,18 +141,18 @@
   // Visit copied link should now be available.
   NSString* a11yLabelPasteGo =
       l10n_util::GetNSString(IDS_IOS_VISIT_COPIED_LINK);
-  id<GREYMatcher> pasteAndGoMatcher = grey_accessibilityLabel(a11yLabelPasteGo);
+  id<GREYMatcher> pasteAndGoMatcher =
+      grey_allOf(grey_accessibilityLabel(a11yLabelPasteGo),
+                 chrome_test_util::SystemSelectionCallout(), nil);
   [[EarlGrey selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
       performAction:grey_longPress()];
-  [[[EarlGrey selectElementWithMatcher:pasteAndGoMatcher]
-      inRoot:chrome_test_util::SystemSelectionCallout()]
+  [[EarlGrey selectElementWithMatcher:pasteAndGoMatcher]
       assertWithMatcher:grey_notNil()];
 
   [self checkLocationBarSteadyState];
 
   // Tapping it should navigate to Page 1.
-  [[[EarlGrey selectElementWithMatcher:pasteAndGoMatcher]
-      inRoot:chrome_test_util::SystemSelectionCallout()]
+  [[EarlGrey selectElementWithMatcher:pasteAndGoMatcher]
       performAction:grey_tap()];
 
   [ChromeEarlGrey waitForPageToFinishLoading];
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller.mm b/ios/chrome/browser/ui/open_in/open_in_controller.mm
index 3854100..f1f9a708 100644
--- a/ios/chrome/browser/ui/open_in/open_in_controller.mm
+++ b/ios/chrome/browser/ui/open_in/open_in_controller.mm
@@ -234,8 +234,9 @@
         initWithTarget:self
                 action:@selector(handleTapFrom:)];
     [tapRecognizer_ setDelegate:self];
-    sequencedTaskRunner_ = base::CreateSequencedTaskRunnerWithTraits(
-        {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+    sequencedTaskRunner_ =
+        base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
+                                         base::TaskPriority::BEST_EFFORT});
     isOpenInMenuDisplayed_ = NO;
     _previousScrollViewOffset = 0;
   }
diff --git a/ios/chrome/browser/ui/safe_mode/BUILD.gn b/ios/chrome/browser/ui/safe_mode/BUILD.gn
index 902dfa3..6e79c33 100644
--- a/ios/chrome/browser/ui/safe_mode/BUILD.gn
+++ b/ios/chrome/browser/ui/safe_mode/BUILD.gn
@@ -21,6 +21,7 @@
     "//ios/chrome/browser/safe_mode",
     "//ios/chrome/browser/ui/fancy_ui",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/common/colors",
     "//ui/gfx",
   ]
 
diff --git a/ios/chrome/browser/ui/safe_mode/safe_mode_view_controller.mm b/ios/chrome/browser/ui/safe_mode/safe_mode_view_controller.mm
index 75a2d7d5..8b83791 100644
--- a/ios/chrome/browser/ui/safe_mode/safe_mode_view_controller.mm
+++ b/ios/chrome/browser/ui/safe_mode/safe_mode_view_controller.mm
@@ -13,6 +13,7 @@
 #import "ios/chrome/browser/ui/fancy_ui/primary_action_button.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #import "ui/gfx/ios/NSString+CrStringDrawing.h"
 
@@ -153,22 +154,18 @@
   }
   UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:mainBounds];
   self.view = scrollView;
-  [self.view setBackgroundColor:[UIColor colorWithWhite:0.902 alpha:1.0]];
+  self.view.backgroundColor = [UIColor colorNamed:kBackgroundColor];
   const CGFloat kIPadInset =
       (mainBounds.size.width - kIPadWidth - kHorizontalSpacing) / 2;
   const CGFloat widthInset = IsIPadIdiom() ? kIPadInset : kHorizontalSpacing;
   innerView_ = [[UIView alloc]
       initWithFrame:CGRectInset(mainBounds, widthInset, kVerticalSpacing * 2)];
-  [innerView_ setBackgroundColor:[UIColor whiteColor]];
-  [innerView_ layer].cornerRadius = 3;
-  [innerView_ layer].borderWidth = 1;
-  [innerView_ layer].borderColor =
-      [UIColor colorWithWhite:0.851 alpha:1.0].CGColor;
-  [innerView_ layer].masksToBounds = YES;
   [scrollView addSubview:innerView_];
 
-  UIImage* fatalImage = [UIImage imageNamed:@"fatal_error.png"];
+  UIImage* fatalImage = [[UIImage imageNamed:@"fatal_error.png"]
+      imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
   UIImageView* imageView = [[UIImageView alloc] initWithImage:fatalImage];
+  imageView.tintColor = [UIColor colorNamed:kPlaceholderImageTintColor];
   // Shift the image down a bit.
   CGRect imageFrame = [imageView frame];
   imageFrame.origin.y = kVerticalSpacing;
@@ -178,8 +175,7 @@
 
   UILabel* awSnap = [[UILabel alloc] init];
   [awSnap setText:NSLocalizedString(@"IDS_IOS_SAFE_MODE_AW_SNAP", @"")];
-  [awSnap setBackgroundColor:[UIColor clearColor]];
-  [awSnap setTextColor:[UIColor blackColor]];
+  awSnap.textColor = [UIColor colorNamed:kTextPrimaryColor];
   [awSnap setFont:[UIFont boldSystemFontOfSize:21]];
   [awSnap sizeToFit];
   [self centerView:awSnap afterView:imageView];
@@ -187,8 +183,7 @@
 
   UILabel* description = [[UILabel alloc] init];
   [description setText:[self startupCrashModuleText]];
-  [description setBackgroundColor:[UIColor clearColor]];
-  [description setTextColor:[UIColor colorWithWhite:0.31 alpha:1.0]];
+  description.textColor = [UIColor colorNamed:kTextSecondaryColor];
   [description setTextAlignment:NSTextAlignmentCenter];
   [description setNumberOfLines:0];
   [description setLineBreakMode:NSLineBreakByWordWrapping];
@@ -237,9 +232,8 @@
       [uploadDescription_
           setText:NSLocalizedString(@"IDS_IOS_SAFE_MODE_SENDING_CRASH_REPORT",
                                     @"")];
-      [uploadDescription_ setBackgroundColor:[UIColor clearColor]];
       [uploadDescription_ setFont:[UIFont systemFontOfSize:13]];
-      [uploadDescription_ setTextColor:[UIColor colorWithWhite:0.31 alpha:1.0]];
+      uploadDescription_.textColor = [UIColor colorNamed:kTextSecondaryColor];
       [uploadDescription_ sizeToFit];
       [self centerView:uploadDescription_ afterView:startButton_];
       [innerView_ addSubview:uploadDescription_];
diff --git a/ios/chrome/browser/ui/settings/password/password_exporter.mm b/ios/chrome/browser/ui/settings/password/password_exporter.mm
index 59f3c4d..7f89c98b 100644
--- a/ios/chrome/browser/ui/settings/password/password_exporter.mm
+++ b/ios/chrome/browser/ui/settings/password/password_exporter.mm
@@ -43,8 +43,9 @@
 - (void)serializePasswords:
             (std::vector<std::unique_ptr<autofill::PasswordForm>>)passwords
                    handler:(void (^)(std::string))serializedPasswordsHandler {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&password_manager::PasswordCSVWriter::SerializePasswords,
                      std::move(passwords)),
       base::BindOnce(serializedPasswordsHandler));
@@ -89,8 +90,9 @@
     }
     return WriteToURLStatus::SUCCESS;
   };
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
       base::BindOnce(writeToFile), base::BindOnce(handler));
 }
 
@@ -324,8 +326,9 @@
 - (void)deleteTemporaryFile:(NSURL*)passwordsTempFileURL {
   NSURL* uniqueDirectoryURL =
       [passwordsTempFileURL URLByDeletingLastPathComponent];
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+  base::PostTask(
+      FROM_HERE,
+      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
       base::BindOnce(^{
         NSFileManager* fileManager = [NSFileManager defaultManager];
         base::ScopedBlockingCall scoped_blocking_call(
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 838da37..b18d9d1c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -1125,7 +1125,7 @@
         // Visibly scroll to the regular tabs panel after a slight delay when
         // the user is already in the tab switcher.
         __weak TabGridViewController* weakSelf = self;
-        base::PostDelayedTaskWithTraits(
+        base::PostDelayedTask(
             FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
               [weakSelf setCurrentPageAndPageControlSelectedPage:
                             TabGridPageRegularTabs
diff --git a/ios/chrome/browser/ui/table_view/BUILD.gn b/ios/chrome/browser/ui/table_view/BUILD.gn
index ba9fa25..f5216e54 100644
--- a/ios/chrome/browser/ui/table_view/BUILD.gn
+++ b/ios/chrome/browser/ui/table_view/BUILD.gn
@@ -22,10 +22,10 @@
     ":presentation",
     ":styler",
     ":views",
-    "resources:placeholder_image_tint_color",
     "//base",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/material_components",
+    "//ios/chrome/common/colors",
     "//ios/third_party/material_components_ios",
   ]
   public_deps = [
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
index 0ed225a..b129eaa 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -16,6 +16,7 @@
 #import "ios/chrome/browser/ui/table_view/table_view_loading_view.h"
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -155,8 +156,7 @@
   self.emptyView = [[TableViewEmptyView alloc] initWithFrame:self.view.bounds
                                                      message:message
                                                        image:image];
-  self.emptyView.tintColor =
-      [UIColor colorNamed:@"placeholder_image_tint_color"];
+  self.emptyView.tintColor = [UIColor colorNamed:kPlaceholderImageTintColor];
 }
 
 - (void)addEmptyTableViewWithAttributedMessage:
@@ -165,8 +165,7 @@
   self.emptyView = [[TableViewEmptyView alloc] initWithFrame:self.view.bounds
                                            attributedMessage:attributedMessage
                                                        image:image];
-  self.emptyView.tintColor =
-      [UIColor colorNamed:@"placeholder_image_tint_color"];
+  self.emptyView.tintColor = [UIColor colorNamed:kPlaceholderImageTintColor];
 }
 
 - (void)updateEmptyTableViewMessageAccessibilityLabel:(NSString*)newLabel {
diff --git a/ios/chrome/browser/ui/table_view/resources/BUILD.gn b/ios/chrome/browser/ui/table_view/resources/BUILD.gn
deleted file mode 100644
index 427865e..0000000
--- a/ios/chrome/browser/ui/table_view/resources/BUILD.gn
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/ios/asset_catalog.gni")
-
-colorset("placeholder_image_tint_color") {
-  sources = [
-    "placeholder_image_tint_color.colorset/Contents.json",
-  ]
-}
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index 64add5e44..454bcbf67 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -26,8 +26,6 @@
   ]
   deps = [
     "resources:open_new_tab_background",
-    "resources:tabstrip_active_tab_close_button_color",
-    "resources:tabstrip_active_tab_incognito_close_button_color",
     "resources:tabstrip_background_tab",
     "resources:tabstrip_foreground_tab",
     "resources:tabstrip_inactive_tab_close_button_color",
diff --git a/ios/chrome/browser/ui/tabs/resources/BUILD.gn b/ios/chrome/browser/ui/tabs/resources/BUILD.gn
index b088fd30..281c64a6 100644
--- a/ios/chrome/browser/ui/tabs/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/resources/BUILD.gn
@@ -81,18 +81,6 @@
   ]
 }
 
-colorset("tabstrip_active_tab_close_button_color") {
-  sources = [
-    "tabstrip_active_tab_close_button_color.colorset/Contents.json",
-  ]
-}
-
-colorset("tabstrip_active_tab_incognito_close_button_color") {
-  sources = [
-    "tabstrip_active_tab_incognito_close_button_color.colorset/Contents.json",
-  ]
-}
-
 colorset("tabstrip_inactive_tab_close_button_color") {
   sources = [
     "tabstrip_inactive_tab_close_button_color.colorset/Contents.json",
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm
index 432f4f3..16699d1 100644
--- a/ios/chrome/browser/ui/tabs/tab_view.mm
+++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -394,10 +394,8 @@
   // Style the close button tint color.
   NSString* closeButtonColorName;
   if (selected) {
-    closeButtonColorName =
-        useIncognitoFallback
-            ? @"tabstrip_active_tab_incognito_close_button_color"
-            : @"tabstrip_active_tab_close_button_color";
+    closeButtonColorName = useIncognitoFallback ? @"close_button_dark_color"
+                                                : @"close_button_color";
   } else {
     closeButtonColorName = @"tabstrip_inactive_tab_close_button_color";
   }
diff --git a/ios/chrome/browser/web/image_fetch_tab_helper.mm b/ios/chrome/browser/web/image_fetch_tab_helper.mm
index 5e64dd8..5f32af3 100644
--- a/ios/chrome/browser/web/image_fetch_tab_helper.mm
+++ b/ios/chrome/browser/web/image_fetch_tab_helper.mm
@@ -130,7 +130,7 @@
   DCHECK_EQ(js_callbacks_.count(call_id_), 0UL);
   js_callbacks_.insert({call_id_, std::move(callback)});
 
-  base::PostDelayedTaskWithTraits(
+  base::PostDelayedTask(
       FROM_HERE, {web::WebThread::UI},
       base::BindRepeating(&ImageFetchTabHelper::OnJsTimeout,
                           weak_ptr_factory_.GetWeakPtr(), call_id_),
diff --git a/ios/chrome/common/colors/resources/BUILD.gn b/ios/chrome/common/colors/resources/BUILD.gn
index e826d518..3557e64cc7 100644
--- a/ios/chrome/common/colors/resources/BUILD.gn
+++ b/ios/chrome/common/colors/resources/BUILD.gn
@@ -10,11 +10,14 @@
     ":background_dark_color",
     ":blue_color",
     ":blue_dark_color",
+    ":close_button_color",
+    ":close_button_dark_color",
     ":disabled_tint_color",
     ":favicon_background_color",
     ":green_color",
     ":green_dark_color",
     ":mdc_ink_color",
+    ":placeholder_image_tint_color",
     ":red_color",
     ":red_dark_color",
     ":scrim_background_color",
@@ -98,6 +101,12 @@
   ]
 }
 
+colorset("placeholder_image_tint_color") {
+  sources = [
+    "placeholder_image_tint_color.colorset/Contents.json",
+  ]
+}
+
 colorset("scrim_background_color") {
   sources = [
     "scrim_background_color.colorset/Contents.json",
@@ -169,3 +178,14 @@
     "textfield_background_dark_color.colorset/Contents.json",
   ]
 }
+colorset("close_button_color") {
+  sources = [
+    "close_button_color.colorset/Contents.json",
+  ]
+}
+
+colorset("close_button_dark_color") {
+  sources = [
+    "close_button_dark_color.colorset/Contents.json",
+  ]
+}
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_active_tab_close_button_color.colorset/Contents.json b/ios/chrome/common/colors/resources/close_button_color.colorset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/tabs/resources/tabstrip_active_tab_close_button_color.colorset/Contents.json
rename to ios/chrome/common/colors/resources/close_button_color.colorset/Contents.json
diff --git a/ios/chrome/browser/ui/tabs/resources/tabstrip_active_tab_incognito_close_button_color.colorset/Contents.json b/ios/chrome/common/colors/resources/close_button_dark_color.colorset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/tabs/resources/tabstrip_active_tab_incognito_close_button_color.colorset/Contents.json
rename to ios/chrome/common/colors/resources/close_button_dark_color.colorset/Contents.json
diff --git a/ios/chrome/browser/ui/table_view/resources/placeholder_image_tint_color.colorset/Contents.json b/ios/chrome/common/colors/resources/placeholder_image_tint_color.colorset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/table_view/resources/placeholder_image_tint_color.colorset/Contents.json
rename to ios/chrome/common/colors/resources/placeholder_image_tint_color.colorset/Contents.json
diff --git a/ios/chrome/common/colors/semantic_color_names.h b/ios/chrome/common/colors/semantic_color_names.h
index 26cc196..bb4b2bd3 100644
--- a/ios/chrome/common/colors/semantic_color_names.h
+++ b/ios/chrome/common/colors/semantic_color_names.h
@@ -10,10 +10,13 @@
 // Element Colors
 
 extern NSString* const kBackgroundColor;
+extern NSString* const kCloseButtonColor;
 extern NSString* const kDisabledTintColor;
 // Background color used in the rounded squares behind favicons.
 extern NSString* const kFaviconBackgroundColor;
 extern NSString* const kMDCInkColor;
+// Color used to tint placeholder images and icons.
+extern NSString* const kPlaceholderImageTintColor;
 extern NSString* const kScrimBackgroundColor;
 extern NSString* const kSolidButtonTextColor;
 extern NSString* const kTableViewRowHighlightColor;
@@ -39,6 +42,7 @@
 // TODO(crbug.com/981889): Clean up after iOS 12 support is dropped.
 
 extern NSString* const kBackgroundDarkColor;
+extern NSString* const kCloseButtonDarkColor;
 extern NSString* const kTableViewRowHighlightDarkColor;
 extern NSString* const kTextPrimaryDarkColor;
 extern NSString* const kTextSecondaryDarkColor;
diff --git a/ios/chrome/common/colors/semantic_color_names.mm b/ios/chrome/common/colors/semantic_color_names.mm
index 1c8dd30..4a612ab 100644
--- a/ios/chrome/common/colors/semantic_color_names.mm
+++ b/ios/chrome/common/colors/semantic_color_names.mm
@@ -10,9 +10,11 @@
 
 #pragma mark - Element Colors
 NSString* const kBackgroundColor = @"background_color";
+NSString* const kCloseButtonColor = @"close_button_color";
 NSString* const kDisabledTintColor = @"disabled_tint_color";
 NSString* const kFaviconBackgroundColor = @"favicon_background_color";
 NSString* const kMDCInkColor = @"mdc_ink_color";
+NSString* const kPlaceholderImageTintColor = @"placeholder_image_tint_color";
 NSString* const kScrimBackgroundColor = @"scrim_background_color";
 NSString* const kSolidButtonTextColor = @"solid_button_text_color";
 NSString* const kTableViewRowHighlightColor = @"table_view_row_highlight_color";
@@ -29,6 +31,7 @@
 // Temporary for iOS 12
 
 NSString* const kBackgroundDarkColor = @"background_dark_color";
+NSString* const kCloseButtonDarkColor = @"close_button_dark_color";
 NSString* const kTableViewRowHighlightDarkColor =
     @"table_view_row_highlight_dark_color";
 NSString* const kTextPrimaryDarkColor = @"text_primary_dark_color";
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h
index 45139b4a..eacb87b4 100644
--- a/ios/net/cookies/cookie_store_ios.h
+++ b/ios/net/cookies/cookie_store_ios.h
@@ -18,6 +18,7 @@
 #include "base/containers/linked_list.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "ios/net/cookies/cookie_cache.h"
@@ -86,6 +87,7 @@
   void SetCookieWithOptionsAsync(const GURL& url,
                                  const std::string& cookie_line,
                                  const net::CookieOptions& options,
+                                 base::Optional<base::Time> server_time,
                                  SetCookiesCallback callback) override;
   void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie,
                                std::string source_scheme,
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index aea8e14..358921c 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -103,9 +103,10 @@
 
 // Builds a NSHTTPCookie from a header cookie line ("Set-Cookie: xxx") and a
 // URL.
-NSHTTPCookie* GetNSHTTPCookieFromCookieLine(const std::string& cookie_line,
-                                            const GURL& url,
-                                            base::Time server_time) {
+NSHTTPCookie* GetNSHTTPCookieFromCookieLine(
+    const std::string& cookie_line,
+    const GURL& url,
+    base::Optional<base::Time> server_time) {
   NSURL* nsurl = net::NSURLWithGURL(url);
   NSString* ns_cookie_line = base::SysUTF8ToNSString(cookie_line);
   if (!ns_cookie_line) {
@@ -119,11 +120,13 @@
     return nil;
 
   NSHTTPCookie* cookie = [cookies objectAtIndex:0];
-  if (![cookie expiresDate] || server_time.is_null())
+  if (![cookie expiresDate] || !server_time.has_value() ||
+      server_time->is_null()) {
     return cookie;
+  }
 
   // Perform clock skew correction.
-  base::TimeDelta clock_skew = base::Time::Now() - server_time;
+  base::TimeDelta clock_skew = base::Time::Now() - server_time.value();
   NSDate* corrected_expire_date =
       [[cookie expiresDate] dateByAddingTimeInterval:clock_skew.InSecondsF()];
   NSMutableDictionary* properties =
@@ -272,6 +275,7 @@
     const GURL& url,
     const std::string& cookie_line,
     const net::CookieOptions& options,
+    base::Optional<base::Time> server_time,
     SetCookiesCallback callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
@@ -283,8 +287,6 @@
   // engine.
   DCHECK(!options.exclude_httponly());
 
-  base::Time server_time =
-      options.has_server_time() ? options.server_time() : base::Time();
   NSHTTPCookie* cookie =
       GetNSHTTPCookieFromCookieLine(cookie_line, url, server_time);
   DLOG_IF(WARNING, !cookie) << "Could not create cookie for line: "
diff --git a/ios/net/cookies/cookie_store_ios_persistent.h b/ios/net/cookies/cookie_store_ios_persistent.h
index 29681cfb..73c0838 100644
--- a/ios/net/cookies/cookie_store_ios_persistent.h
+++ b/ios/net/cookies/cookie_store_ios_persistent.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #import "ios/net/cookies/cookie_store_ios.h"
 #include "net/cookies/cookie_monster.h"
@@ -45,6 +46,7 @@
   void SetCookieWithOptionsAsync(const GURL& url,
                                  const std::string& cookie_line,
                                  const net::CookieOptions& options,
+                                 base::Optional<base::Time> server_time,
                                  SetCookiesCallback callback) override;
   void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie,
                                std::string source_scheme,
diff --git a/ios/net/cookies/cookie_store_ios_persistent.mm b/ios/net/cookies/cookie_store_ios_persistent.mm
index 80e4a921..415857d 100644
--- a/ios/net/cookies/cookie_store_ios_persistent.mm
+++ b/ios/net/cookies/cookie_store_ios_persistent.mm
@@ -61,11 +61,13 @@
     const GURL& url,
     const std::string& cookie_line,
     const net::CookieOptions& options,
+    base::Optional<base::Time> server_time,
     SetCookiesCallback callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   cookie_monster()->SetCookieWithOptionsAsync(
-      url, cookie_line, options, WrapSetCallback(std::move(callback)));
+      url, cookie_line, options, server_time,
+      WrapSetCallback(std::move(callback)));
 }
 
 void CookieStoreIOSPersistent::SetCanonicalCookieAsync(
diff --git a/ios/net/cookies/cookie_store_ios_test_util.mm b/ios/net/cookies/cookie_store_ios_test_util.mm
index 6b179f5f..2f9cc4da 100644
--- a/ios/net/cookies/cookie_store_ios_test_util.mm
+++ b/ios/net/cookies/cookie_store_ios_test_util.mm
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -37,11 +38,9 @@
 
 void TestPersistentCookieStore::RunLoadedCallback() {
   std::vector<std::unique_ptr<net::CanonicalCookie>> cookies;
-  net::CookieOptions options;
-  options.set_include_httponly();
-
-  std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
-      kTestCookieURL, "a=b", base::Time::Now(), options));
+  std::unique_ptr<net::CanonicalCookie> cookie(
+      net::CanonicalCookie::Create(kTestCookieURL, "a=b", base::Time::Now(),
+                                   base::nullopt /* server_time */));
   cookies.push_back(std::move(cookie));
 
   std::unique_ptr<net::CanonicalCookie> bad_canonical_cookie(
@@ -136,6 +135,7 @@
   net::CookieOptions options;
   options.set_include_httponly();
   store->SetCookieWithOptionsAsync(url, cookie_line, options,
+                                   base::nullopt /* server_time */,
                                    base::DoNothing());
   net::CookieStoreIOS::NotifySystemCookiesChanged();
   // Wait until the flush is posted.
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm
index cc3c2bd8..3a6a657 100644
--- a/ios/net/cookies/cookie_store_ios_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/bind_test_util.h"
@@ -236,17 +237,14 @@
   ClearCookies();
   SetCookie("abc=def");
 
-  // Match options to what SetCookie uses.
-  CookieOptions options;
-  options.set_include_httponly();
-
   // Time is different, though.
   base::Time not_now = base::Time::Now() - base::TimeDelta::FromDays(30);
 
   // Semantics for CookieMonster::DeleteCanonicalCookieAsync don't match deletes
   // for same key if cookie value changed.  Document CookieStoreIOS compat.
-  std::unique_ptr<CanonicalCookie> non_equiv_cookie = CanonicalCookie::Create(
-      kTestCookieURLFooBar, "abc=wfg", not_now, options);
+  std::unique_ptr<CanonicalCookie> non_equiv_cookie =
+      CanonicalCookie::Create(kTestCookieURLFooBar, "abc=wfg", not_now,
+                              base::nullopt /* server_time */);
   base::RunLoop run_loop;
   store_->DeleteCanonicalCookieAsync(
       *non_equiv_cookie, base::BindLambdaForTesting([&](uint32_t deleted) {
@@ -267,8 +265,9 @@
   run_loop2.Run();
 
   // Now delete equivalent one with non-matching ctime.
-  std::unique_ptr<CanonicalCookie> equiv_cookie = CanonicalCookie::Create(
-      kTestCookieURLFooBar, "abc=def", not_now, options);
+  std::unique_ptr<CanonicalCookie> equiv_cookie =
+      CanonicalCookie::Create(kTestCookieURLFooBar, "abc=def", not_now,
+                              base::nullopt /* server_time */);
 
   base::RunLoop run_loop3;
   store_->DeleteCanonicalCookieAsync(
@@ -334,7 +333,7 @@
   net::CookieOptions options;
   options.set_include_httponly();
   cookie_store->SetCookieWithOptionsAsync(
-      kTestCookieURLFooBar, "a=b", options,
+      kTestCookieURLFooBar, "a=b", options, base::nullopt /* server_time */,
       net::CookieStore::SetCookiesCallback());
   // Check we can get the cookie.
   GetAllCookiesCallback callback;
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index f026820..aeb56abc 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -15,7 +15,10 @@
     "src/components/Buttons/src/ShapeThemer/MaterialButtons+ShapeThemer.h",
     "src/components/Buttons/src/TypographyThemer/MaterialButtons+TypographyThemer.h",
     "src/components/Cards/src/MaterialCards.h",
+    "src/components/Dialogs/src/ColorThemer/MaterialDialogs+ColorThemer.h",
+    "src/components/Dialogs/src/MDCAlertController+ButtonForAction.h",
     "src/components/Dialogs/src/MaterialDialogs.h",
+    "src/components/Dialogs/src/TypographyThemer/MaterialDialogs+TypographyThemer.h",
     "src/components/ShadowElevations/src/MaterialShadowElevations.h",
     "src/components/Typography/src/MaterialTypography.h",
     "src/components/schemes/Color/src/MaterialColorScheme.h",
@@ -222,6 +225,8 @@
     "src/components/Dialogs/src/DialogThemer/MDCAlertControllerThemer.m",
     "src/components/Dialogs/src/DialogThemer/MDCAlertScheme.h",
     "src/components/Dialogs/src/DialogThemer/MDCAlertScheme.m",
+    "src/components/Dialogs/src/MDCAlertController+ButtonForAction.h",
+    "src/components/Dialogs/src/MDCAlertController+ButtonForAction.m",
     "src/components/Dialogs/src/MDCAlertController.h",
     "src/components/Dialogs/src/MDCAlertController.m",
     "src/components/Dialogs/src/MDCAlertControllerView.h",
@@ -230,6 +235,8 @@
     "src/components/Dialogs/src/MDCDialogTransitionController.h",
     "src/components/Dialogs/src/MDCDialogTransitionController.m",
     "src/components/Dialogs/src/MaterialDialogs.h",
+    "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.h",
+    "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.m",
     "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.h",
     "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.m",
     "src/components/Dialogs/src/UIViewController+MaterialDialogs.h",
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index af1171b..e754530 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -191,7 +191,7 @@
     const GURL& url,
     const std::string& cookie_line,
     const base::Time& creation_time,
-    const CookieOptions& options,
+    base::Optional<base::Time> server_time,
     CookieInclusionStatus* status) {
   // Put a pointer on the stack so the rest of the function can assign to it if
   // the default nullptr is passed in.
@@ -221,14 +221,13 @@
   std::string cookie_path = CanonPathWithString(
       url, parsed_cookie.HasPath() ? parsed_cookie.Path() : std::string());
 
-  Time server_time(creation_time);
-  if (options.has_server_time())
-    server_time = options.server_time();
+  Time cookie_server_time(creation_time);
+  if (server_time.has_value() && !server_time->is_null())
+    cookie_server_time = server_time.value();
 
   DCHECK(!creation_time.is_null());
-  Time cookie_expires = CanonicalCookie::CanonExpiration(parsed_cookie,
-                                                         creation_time,
-                                                         server_time);
+  Time cookie_expires = CanonicalCookie::CanonExpiration(
+      parsed_cookie, creation_time, cookie_server_time);
 
   CookiePrefix prefix = GetCookiePrefix(parsed_cookie.Name());
   bool is_cookie_valid = IsCookiePrefixValid(prefix, url, parsed_cookie);
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index 3a700e3..a63f546 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -87,12 +87,13 @@
   // |creation_time|.  Canonicalizes inputs.  May return nullptr if
   // an attribute value is invalid.  |url| must be valid.  |creation_time| may
   // not be null. Sets optional |status| to the relevant CookieInclusionStatus
-  // if provided.
+  // if provided.  |server_time| indicates what the server sending us the Cookie
+  // thought the current time was when the cookie was produced.  This is used to
+  // adjust for clock skew between server and host.
   //
-  // SameSite and HttpOnly related parameters in |options| are not checked here,
+  // SameSite and HttpOnly related parameters are not checked here,
   // so creation of CanonicalCookies with e.g. SameSite=Strict from a cross-site
-  // context is allowed. The same |options| should be given when creating and
-  // setting a cookie. Create() also does not check whether |url| has a secure
+  // context is allowed. Create() also does not check whether |url| has a secure
   // scheme if attempting to create a Secure cookie. The Secure, SameSite, and
   // HttpOnly related parameters should be checked when setting the cookie in
   // the CookieStore.
@@ -102,7 +103,7 @@
       const GURL& url,
       const std::string& cookie_line,
       const base::Time& creation_time,
-      const CookieOptions& options,
+      base::Optional<base::Time> server_time,
       CookieInclusionStatus* status = nullptr);
 
   // Create a canonical cookie based on sanitizing the passed inputs in the
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 318260a..6f083491 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/cookies/canonical_cookie.h"
 
+#include "base/optional.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "net/base/features.h"
@@ -32,17 +33,17 @@
   GURL url("http://www.example.com/test");
   base::Time current_time = base::Time::Now();
 
-  std::unique_ptr<CanonicalCookie> cookie(std::make_unique<CanonicalCookie>(
+  std::unique_ptr<CanonicalCookie> cookie1(std::make_unique<CanonicalCookie>(
       "A", "2", "www.example.com", "/test", current_time, base::Time(),
       base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
       COOKIE_PRIORITY_DEFAULT));
-  EXPECT_EQ("A", cookie->Name());
-  EXPECT_EQ("2", cookie->Value());
-  EXPECT_EQ("www.example.com", cookie->Domain());
-  EXPECT_EQ("/test", cookie->Path());
-  EXPECT_FALSE(cookie->IsSecure());
-  EXPECT_FALSE(cookie->IsHttpOnly());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
+  EXPECT_EQ("A", cookie1->Name());
+  EXPECT_EQ("2", cookie1->Value());
+  EXPECT_EQ("www.example.com", cookie1->Domain());
+  EXPECT_EQ("/test", cookie1->Path());
+  EXPECT_FALSE(cookie1->IsSecure());
+  EXPECT_FALSE(cookie1->IsHttpOnly());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie1->SameSite());
 
   std::unique_ptr<CanonicalCookie> cookie2(std::make_unique<CanonicalCookie>(
       "A", "2", ".www.example.com", "/", current_time, base::Time(),
@@ -55,22 +56,34 @@
   EXPECT_FALSE(cookie2->IsSecure());
   EXPECT_FALSE(cookie2->IsHttpOnly());
   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite());
+
+  auto cookie = std::make_unique<CanonicalCookie>(
+      "A", "2", ".www.example.com", "/test", current_time, base::Time(),
+      base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
+      COOKIE_PRIORITY_DEFAULT);
+  EXPECT_EQ("A", cookie->Name());
+  EXPECT_EQ("2", cookie->Value());
+  EXPECT_EQ(".www.example.com", cookie->Domain());
+  EXPECT_EQ("/test", cookie->Path());
+  EXPECT_FALSE(cookie->IsSecure());
+  EXPECT_FALSE(cookie->IsHttpOnly());
+  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 }
 
 TEST(CanonicalCookie, CreationCornerCases) {
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
   std::unique_ptr<CanonicalCookie> cookie;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   // Space in name.
   cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
-                                   "A C=2", creation_time, options);
+                                   "A C=2", creation_time, server_time);
   EXPECT_TRUE(cookie.get());
   EXPECT_EQ("A C", cookie->Name());
 
   // Semicolon in path.
   cookie = CanonicalCookie::Create(GURL("http://fool/;/"), "*", creation_time,
-                                   options);
+                                   server_time);
   EXPECT_TRUE(cookie.get());
 }
 
@@ -79,10 +92,10 @@
   GURL url("http://www.example.com/test/foo.html");
   GURL https_url("https://www.example.com/test/foo.html");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::unique_ptr<CanonicalCookie> cookie(
-      CanonicalCookie::Create(url, "A=2", creation_time, options));
+      CanonicalCookie::Create(url, "A=2", creation_time, server_time));
   EXPECT_EQ("A", cookie->Name());
   EXPECT_EQ("2", cookie->Value());
   EXPECT_EQ("www.example.com", cookie->Domain());
@@ -90,7 +103,7 @@
   EXPECT_FALSE(cookie->IsSecure());
 
   GURL url2("http://www.foo.com");
-  cookie = CanonicalCookie::Create(url2, "B=1", creation_time, options);
+  cookie = CanonicalCookie::Create(url2, "B=1", creation_time, server_time);
   EXPECT_EQ("B", cookie->Name());
   EXPECT_EQ("1", cookie->Value());
   EXPECT_EQ("www.foo.com", cookie->Domain());
@@ -100,141 +113,59 @@
   // Test creating secure cookies. Secure scheme is not checked upon creation,
   // so a URL of any scheme can create a Secure cookie.
   CanonicalCookie::CookieInclusionStatus status;
-  cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options,
-                                   &status);
+  cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time,
+                                   server_time, &status);
   EXPECT_TRUE(cookie->IsSecure());
 
   cookie = CanonicalCookie::Create(https_url, "A=2; Secure", creation_time,
-                                   options, &status);
+                                   server_time, &status);
   EXPECT_TRUE(cookie->IsSecure());
 
   // Test creating http only cookies. HttpOnly is not checked upon creation.
-  cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options,
-                                   &status);
+  cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
+                                   server_time, &status);
   EXPECT_TRUE(cookie->IsHttpOnly());
 
-  CookieOptions httponly_options;
-  httponly_options.set_include_httponly();
-  cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
-                                   httponly_options);
+  cookie =
+      CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
   EXPECT_TRUE(cookie->IsHttpOnly());
 
   // Test creating SameSite cookies. SameSite is not checked upon creation.
-  CookieOptions same_site_options;
-  same_site_options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
-                                   same_site_options);
+                                   server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
-                                   same_site_options);
+                                   server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Extended", creation_time,
-                                   same_site_options);
+                                   server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::EXTENDED_MODE, cookie->SameSite());
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
-                                   same_site_options);
+                                   server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
-  cookie =
-      CanonicalCookie::Create(url, "A=2", creation_time, same_site_options);
+  cookie = CanonicalCookie::Create(url, "A=2", creation_time, server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
-
-  same_site_options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Extended", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::EXTENDED_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
-  cookie =
-      CanonicalCookie::Create(url, "A=2", creation_time, same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
-
-  same_site_options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::CROSS_SITE);
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Extended", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::EXTENDED_MODE, cookie->SameSite());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
-                                   same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
-  cookie =
-      CanonicalCookie::Create(url, "A=2", creation_time, same_site_options);
-  ASSERT_TRUE(cookie.get());
-  EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
-
-  // Test the creating cookies using specific parameter instead of a cookie
-  // string.
-  // TODO(chlily): Move this elsewhere. This doesn't test the Create() method.
-  cookie = std::make_unique<CanonicalCookie>(
-      "A", "2", ".www.example.com", "/test", creation_time, base::Time(),
-      base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
-      COOKIE_PRIORITY_DEFAULT);
-  EXPECT_EQ("A", cookie->Name());
-  EXPECT_EQ("2", cookie->Value());
-  EXPECT_EQ(".www.example.com", cookie->Domain());
-  EXPECT_EQ("/test", cookie->Path());
-  EXPECT_FALSE(cookie->IsSecure());
-  EXPECT_FALSE(cookie->IsHttpOnly());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
-
-  cookie = std::make_unique<CanonicalCookie>(
-      "A", "2", ".www.example.com", "/test", creation_time, base::Time(),
-      base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
-      COOKIE_PRIORITY_DEFAULT);
-  EXPECT_EQ("A", cookie->Name());
-  EXPECT_EQ("2", cookie->Value());
-  EXPECT_EQ(".www.example.com", cookie->Domain());
-  EXPECT_EQ("/test", cookie->Path());
-  EXPECT_FALSE(cookie->IsSecure());
-  EXPECT_FALSE(cookie->IsHttpOnly());
-  EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
 }
 
 TEST(CanonicalCookieTest, CreateNonStandardSameSite) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
   std::unique_ptr<CanonicalCookie> cookie;
-  CookieOptions options;
-
-  options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
+  base::Optional<base::Time> server_time = base::nullopt;
 
   // Non-standard value for the SameSite attribute.
-  cookie =
-      CanonicalCookie::Create(url, "A=2; SameSite=NonStandard", now, options);
+  cookie = CanonicalCookie::Create(url, "A=2; SameSite=NonStandard", now,
+                                   server_time);
   EXPECT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
 
   // Omit value for the SameSite attribute.
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, options);
+  cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, server_time);
   EXPECT_TRUE(cookie.get());
   EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
 }
@@ -243,71 +174,43 @@
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
   std::unique_ptr<CanonicalCookie> cookie;
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   // A cookie can be created from any SameSiteContext regardless of SameSite
   // value (it is upon setting the cookie that the SameSiteContext comes into
   // effect).
-  // In SAME_SITE_STRICT contexts, any `SameSite` value can be created:
-  options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, options);
+  cookie =
+      CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, server_time);
   EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, options);
+  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, server_time);
   EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, options);
+  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, server_time);
   EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2;", now, options);
-  EXPECT_TRUE(cookie.get());
-
-  // In SAME_SITE_LAX contexts, any `SameSite` value can be created:
-  options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2;", now, options);
-  EXPECT_TRUE(cookie.get());
-
-  // In CROSS_SITE contexts, any `SameSite` value can be created:
-  options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::CROSS_SITE);
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, options);
-  EXPECT_TRUE(cookie.get());
-  cookie = CanonicalCookie::Create(url, "A=2;", now, options);
+  cookie = CanonicalCookie::Create(url, "A=2;", now, server_time);
   EXPECT_TRUE(cookie.get());
 }
 
-TEST(CanonicalCookieTest, CreateInvalidHttpOnly) {
+TEST(CanonicalCookieTest, CreateHttpOnly) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   CanonicalCookie::CookieInclusionStatus status;
 
-  // An HttpOnly cookie can be created regardless of the CookieOptions. (It is
-  // upon setting the cookie that the exclude_httponly() in the CookieOptions
-  // comes into effect.)
-  options.set_exclude_httponly();
+  // An HttpOnly cookie can be created.
   std::unique_ptr<CanonicalCookie> cookie =
-      CanonicalCookie::Create(url, "A=2; HttpOnly", now, options, &status);
+      CanonicalCookie::Create(url, "A=2; HttpOnly", now, server_time, &status);
   EXPECT_TRUE(cookie->IsHttpOnly());
+  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
 }
 
 TEST(CanonicalCookieTest, CreateWithInvalidDomain) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time now = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   CanonicalCookie::CookieInclusionStatus status;
 
   std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
-      url, "A=2; Domain=wrongdomain.com", now, options, &status);
+      url, "A=2; Domain=wrongdomain.com", now, server_time, &status);
   EXPECT_EQ(nullptr, cookie.get());
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
             status);
@@ -316,28 +219,30 @@
 TEST(CanonicalCookieTest, EmptyExpiry) {
   GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::string cookie_line =
       "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
   std::unique_ptr<CanonicalCookie> cookie(
-      CanonicalCookie::Create(url, cookie_line, creation_time, options));
+      CanonicalCookie::Create(url, cookie_line, creation_time, server_time));
   EXPECT_TRUE(cookie.get());
   EXPECT_FALSE(cookie->IsPersistent());
   EXPECT_FALSE(cookie->IsExpired(creation_time));
   EXPECT_EQ(base::Time(), cookie->ExpiryDate());
 
   // With a stale server time
-  options.set_server_time(creation_time - base::TimeDelta::FromHours(1));
-  cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
+  server_time = creation_time - base::TimeDelta::FromHours(1);
+  cookie =
+      CanonicalCookie::Create(url, cookie_line, creation_time, server_time);
   EXPECT_TRUE(cookie.get());
   EXPECT_FALSE(cookie->IsPersistent());
   EXPECT_FALSE(cookie->IsExpired(creation_time));
   EXPECT_EQ(base::Time(), cookie->ExpiryDate());
 
   // With a future server time
-  options.set_server_time(creation_time + base::TimeDelta::FromHours(1));
-  cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
+  server_time = creation_time + base::TimeDelta::FromHours(1);
+  cookie =
+      CanonicalCookie::Create(url, cookie_line, creation_time, server_time);
   EXPECT_TRUE(cookie.get());
   EXPECT_FALSE(cookie->IsPersistent());
   EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -482,10 +387,10 @@
 TEST(CanonicalCookieTest, IsDomainMatch) {
   GURL url("http://www.example.com/test/foo.html");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::unique_ptr<CanonicalCookie> cookie(
-      CanonicalCookie::Create(url, "A=2", creation_time, options));
+      CanonicalCookie::Create(url, "A=2", creation_time, server_time));
   EXPECT_TRUE(cookie->IsHostCookie());
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -494,7 +399,7 @@
   EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
 
   cookie = CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
-                                   creation_time, options);
+                                   creation_time, server_time);
   EXPECT_TRUE(cookie->IsDomainCookie());
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -503,7 +408,7 @@
   EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
 
   cookie = CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
-                                   creation_time, options);
+                                   creation_time, server_time);
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
   EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
   EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
@@ -513,10 +418,10 @@
 
 TEST(CanonicalCookieTest, IsOnPath) {
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
-      GURL("http://www.example.com"), "A=2", creation_time, options));
+      GURL("http://www.example.com"), "A=2", creation_time, server_time));
   EXPECT_TRUE(cookie->IsOnPath("/"));
   EXPECT_TRUE(cookie->IsOnPath("/test"));
   EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
@@ -525,7 +430,7 @@
   EXPECT_FALSE(cookie->IsOnPath(std::string()));
 
   cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
-                                   "A=2", creation_time, options);
+                                   "A=2", creation_time, server_time);
   EXPECT_FALSE(cookie->IsOnPath("/"));
   EXPECT_TRUE(cookie->IsOnPath("/test"));
   EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
@@ -583,9 +488,10 @@
   GURL url("http://www.example.com");
   base::Time creation_time = base::Time::Now();
   CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::unique_ptr<CanonicalCookie> cookie(
-      CanonicalCookie::Create(url, "A=2", creation_time, options));
+      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"),
@@ -604,7 +510,7 @@
   // 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,
-                                   options);
+                                   server_time);
   EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
             CanonicalCookie::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH);
   EXPECT_EQ(cookie->IncludeForRequestURL(
@@ -614,7 +520,7 @@
   // 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,
-                                   options);
+                                   server_time);
   EXPECT_TRUE(cookie->IsSecure());
   EXPECT_EQ(cookie->IncludeForRequestURL(secure_url, options),
             CanonicalCookie::CookieInclusionStatus::INCLUDE);
@@ -625,7 +531,7 @@
   // is set on the cookie options.
   options.set_include_httponly();
   cookie =
-      CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
+      CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
   EXPECT_TRUE(cookie->IsHttpOnly());
   EXPECT_EQ(cookie->IncludeForRequestURL(url, options),
             CanonicalCookie::CookieInclusionStatus::INCLUDE);
@@ -637,9 +543,7 @@
 TEST(CanonicalCookieTest, IncludeSameSiteForSameSiteURL) {
   GURL url("https://example.test");
   base::Time creation_time = base::Time::Now();
-  CookieOptions creation_options;
-  creation_options.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
+  base::Optional<base::Time> server_time = base::nullopt;
 
   CookieOptions request_options;
   std::unique_ptr<CanonicalCookie> cookie;
@@ -647,7 +551,7 @@
   // `SameSite=Strict` cookies are included for a URL only if the options'
   // SameSiteCookieMode is SAME_SITE_STRICT.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
-                                   creation_options);
+                                   server_time);
   EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
   request_options.set_same_site_cookie_context(
       CookieOptions::SameSiteCookieContext::CROSS_SITE);
@@ -665,7 +569,7 @@
   // `SameSite=Lax` cookies are included for a URL only if the options'
   // SameSiteCookieMode is SAME_SITE_STRICT or SAME_SITE_LAX.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
-                                   creation_options);
+                                   server_time);
   EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
   request_options.set_same_site_cookie_context(
       CookieOptions::SameSiteCookieContext::CROSS_SITE);
@@ -685,7 +589,7 @@
   // TODO(crbug.com/953995): Right now Extended behaves the same as Lax.
   // Implement Extended.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=Extended", creation_time,
-                                   creation_options);
+                                   server_time);
   EXPECT_EQ(CookieSameSite::EXTENDED_MODE, cookie->SameSite());
   request_options.set_same_site_cookie_context(
       CookieOptions::SameSiteCookieContext::CROSS_SITE);
@@ -702,7 +606,7 @@
 
   // `SameSite=None` cookies are included for all URLs.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
-                                   creation_options);
+                                   server_time);
   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
   request_options.set_same_site_cookie_context(
       CookieOptions::SameSiteCookieContext::CROSS_SITE);
@@ -719,7 +623,7 @@
 
   // Cookies with no SameSite attribute are parsed as
   // CookieSameSite::UNSPECIFIED, and inclusion depends on the FeatureList.
-  cookie = CanonicalCookie::Create(url, "A=2", creation_time, creation_options);
+  cookie = CanonicalCookie::Create(url, "A=2", creation_time, server_time);
   EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
   {
     base::test::ScopedFeatureList feature_list;
@@ -766,12 +670,13 @@
 TEST(CanonicalCookieTest, IncludeCookiesWithoutSameSiteMustBeSecure) {
   GURL url("https://www.example.com");
   base::Time creation_time = base::Time::Now();
+  base::Optional<base::Time> server_time = base::nullopt;
   CookieOptions options;
   std::unique_ptr<CanonicalCookie> cookie;
 
   // Create the cookie without the experimental options enabled.
   cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
-                                   options);
+                                   server_time);
   ASSERT_TRUE(cookie.get());
   EXPECT_FALSE(cookie->IsSecure());
   EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
@@ -793,13 +698,14 @@
 TEST(CanonicalCookieTest, PartialCompare) {
   GURL url("http://www.example.com");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   std::unique_ptr<CanonicalCookie> cookie(
-      CanonicalCookie::Create(url, "a=b", creation_time, options));
+      CanonicalCookie::Create(url, "a=b", creation_time, server_time));
   std::unique_ptr<CanonicalCookie> cookie_different_path(
-      CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, options));
+      CanonicalCookie::Create(url, "a=b; path=/foo", creation_time,
+                              server_time));
   std::unique_ptr<CanonicalCookie> cookie_different_value(
-      CanonicalCookie::Create(url, "a=c", creation_time, options));
+      CanonicalCookie::Create(url, "a=c", creation_time, server_time));
 
   // Cookie is equivalent to itself.
   EXPECT_FALSE(cookie->PartialCompare(*cookie));
@@ -821,33 +727,33 @@
   GURL https_url("https://www.example.test");
   GURL http_url("http://www.example.test");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   CanonicalCookie::CookieInclusionStatus status;
 
   // A __Secure- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
-                                       options, &status));
+                                       server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
-                                       creation_time, options, &status));
+                                       creation_time, server_time, &status));
   // (EXCLUDE_HTTP_ONLY would be fine, too)
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
 
   // A typoed prefix does not have to be Secure.
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=C;", creation_time,
-                                      options));
+                                      server_time));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=C;", creation_time,
-                                      options));
+                                      server_time));
 
   // A __Secure- cookie can't be set on a non-secure origin.
   EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
-                                       creation_time, options, &status));
+                                       creation_time, server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
 }
@@ -856,41 +762,41 @@
   GURL https_url("https://www.example.test");
   GURL http_url("http://www.example.test");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   std::string domain = https_url.host();
   CanonicalCookie::CookieInclusionStatus status;
 
   // A __Host- cookie must be Secure.
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
-                                       options, &status));
+                                       server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
-      options, &status));
+      server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
-                                      creation_time, options));
+                                      creation_time, server_time));
 
   // A __Host- cookie must be set from a secure scheme.
   EXPECT_FALSE(CanonicalCookie::Create(
       http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
-      creation_time, options, &status));
+      creation_time, server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
-                                      creation_time, options));
+                                      creation_time, server_time));
 
   // A __Host- cookie can't have a Domain.
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
-      creation_time, options, &status));
+      creation_time, server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_FALSE(CanonicalCookie::Create(
       https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
-      options, &status));
+      server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
 
@@ -899,49 +805,49 @@
   EXPECT_TRUE(
       CanonicalCookie::Create(GURL("https://127.0.0.1"),
                               "__Host-A=B; Domain=127.0.0.1; Path=/; Secure;",
-                              creation_time, options, &status));
+                              creation_time, server_time, &status));
   // A __Host- cookie with an IP address domain does not need the domain
   // attribute specified explicitly (just like a normal domain).
   EXPECT_TRUE(CanonicalCookie::Create(GURL("https://127.0.0.1"),
                                       "__Host-A=B; Domain=; Path=/; Secure;",
-                                      creation_time, options, &status));
+                                      creation_time, server_time, &status));
 
   // A __Host- cookie must have a Path of "/".
   EXPECT_FALSE(CanonicalCookie::Create(https_url,
                                        "__Host-A=B; Path=/foo; Secure;",
-                                       creation_time, options, &status));
+                                       creation_time, server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
-                                       creation_time, options, &status));
+                                       creation_time, server_time, &status));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
             status);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
-                                      creation_time, options));
+                                      creation_time, server_time));
 
   // Rules don't apply for a typoed prefix.
   EXPECT_TRUE(CanonicalCookie::Create(
       http_url, "__host-A=B; Domain=" + domain + "; Path=/;", creation_time,
-      options));
+      server_time));
   EXPECT_TRUE(CanonicalCookie::Create(
       https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time,
-      options));
+      server_time));
 }
 
 TEST(CanonicalCookieTest, CanCreateSecureCookiesFromAnyScheme) {
   GURL http_url("http://www.example.com");
   GURL https_url("https://www.example.com");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   std::unique_ptr<CanonicalCookie> http_cookie_no_secure(
-      CanonicalCookie::Create(http_url, "a=b", creation_time, options));
-  std::unique_ptr<CanonicalCookie> http_cookie_secure(
-      CanonicalCookie::Create(http_url, "a=b; Secure", creation_time, options));
+      CanonicalCookie::Create(http_url, "a=b", creation_time, server_time));
+  std::unique_ptr<CanonicalCookie> http_cookie_secure(CanonicalCookie::Create(
+      http_url, "a=b; Secure", creation_time, server_time));
   std::unique_ptr<CanonicalCookie> https_cookie_no_secure(
-      CanonicalCookie::Create(https_url, "a=b", creation_time, options));
+      CanonicalCookie::Create(https_url, "a=b", creation_time, server_time));
   std::unique_ptr<CanonicalCookie> https_cookie_secure(CanonicalCookie::Create(
-      https_url, "a=b; Secure", creation_time, options));
+      https_url, "a=b; Secure", creation_time, server_time));
 
   EXPECT_TRUE(http_cookie_no_secure.get());
   EXPECT_TRUE(http_cookie_secure.get());
@@ -1210,10 +1116,10 @@
   const char kCookiePrefixBlockedHistogram[] = "Cookie.CookiePrefixBlocked";
   GURL https_url("https://www.example.test");
   base::Time creation_time = base::Time::Now();
-  CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
 
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
-                                       options));
+                                       server_time));
 
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_HOST, 1);
@@ -1221,33 +1127,33 @@
                                CanonicalCookie::COOKIE_PREFIX_HOST, 1);
 
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_HOST, 2);
   histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
                                CanonicalCookie::COOKIE_PREFIX_HOST, 1);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__HostA=B; Path=/; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_HOST, 2);
   histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
                                CanonicalCookie::COOKIE_PREFIX_HOST, 1);
 
   EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B;",
-                                       creation_time, options));
+                                       creation_time, server_time));
 
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
   histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
                                CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Secure-A=B; Path=/; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
   histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
                                CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
   EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Path=/; Secure",
-                                      creation_time, options));
+                                      creation_time, server_time));
   histograms.ExpectBucketCount(kCookiePrefixHistogram,
                                CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
   histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
@@ -1257,25 +1163,25 @@
 TEST(CanonicalCookieTest, BuildCookieLine) {
   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
   GURL url("https://example.com/");
-  CookieOptions options;
   base::Time now = base::Time::Now();
+  base::Optional<base::Time> server_time = base::nullopt;
   MatchCookieLineToVector("", cookies);
 
-  cookies.push_back(CanonicalCookie::Create(url, "A=B", now, options));
+  cookies.push_back(CanonicalCookie::Create(url, "A=B", now, server_time));
   MatchCookieLineToVector("A=B", cookies);
   // Nameless cookies are sent back without a prefixed '='.
-  cookies.push_back(CanonicalCookie::Create(url, "C", now, options));
+  cookies.push_back(CanonicalCookie::Create(url, "C", now, server_time));
   MatchCookieLineToVector("A=B; C", cookies);
   // Cookies separated by ';'.
-  cookies.push_back(CanonicalCookie::Create(url, "D=E", now, options));
+  cookies.push_back(CanonicalCookie::Create(url, "D=E", now, server_time));
   MatchCookieLineToVector("A=B; C; D=E", cookies);
   // BuildCookieLine doesn't reorder the list, it relies on the caller to do so.
   cookies.push_back(CanonicalCookie::Create(
-      url, "F=G", now - base::TimeDelta::FromSeconds(1), options));
+      url, "F=G", now - base::TimeDelta::FromSeconds(1), server_time));
   MatchCookieLineToVector("A=B; C; D=E; F=G", cookies);
   // BuildCookieLine doesn't deduplicate.
   cookies.push_back(CanonicalCookie::Create(
-      url, "D=E", now - base::TimeDelta::FromSeconds(2), options));
+      url, "D=E", now - base::TimeDelta::FromSeconds(2), server_time));
   MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies);
 }
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index e6f1df78..3aaced4 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -413,17 +413,19 @@
       domain);
 }
 
-void CookieMonster::SetCookieWithOptionsAsync(const GURL& url,
-                                              const std::string& cookie_line,
-                                              const CookieOptions& options,
-                                              SetCookiesCallback callback) {
+void CookieMonster::SetCookieWithOptionsAsync(
+    const GURL& url,
+    const std::string& cookie_line,
+    const CookieOptions& options,
+    base::Optional<base::Time> server_time,
+    SetCookiesCallback callback) {
   DoCookieCallbackForURL(
       base::BindOnce(
           // base::Unretained is safe as DoCookieCallbackForURL stores
           // the callback on |*this|, so the callback will not outlive
           // the object.
           &CookieMonster::SetCookieWithOptions, base::Unretained(this), url,
-          cookie_line, options, std::move(callback)),
+          cookie_line, options, server_time, std::move(callback)),
       url);
 }
 
@@ -674,6 +676,7 @@
 void CookieMonster::SetCookieWithOptions(const GURL& url,
                                          const std::string& cookie_line,
                                          const CookieOptions& options,
+                                         base::Optional<base::Time> server_time,
                                          SetCookiesCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
@@ -689,8 +692,8 @@
 
   CanonicalCookie::CookieInclusionStatus status;
 
-  std::unique_ptr<CanonicalCookie> cc(
-      CanonicalCookie::Create(url, cookie_line, Time::Now(), options, &status));
+  std::unique_ptr<CanonicalCookie> cc(CanonicalCookie::Create(
+      url, cookie_line, Time::Now(), server_time, &status));
 
   if (status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
     DCHECK(!cc);
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 913737e..7d253bd 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -23,6 +23,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/strings/string_piece.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
@@ -158,6 +159,7 @@
   void SetCookieWithOptionsAsync(const GURL& url,
                                  const std::string& cookie_line,
                                  const CookieOptions& options,
+                                 base::Optional<base::Time> server_time,
                                  SetCookiesCallback callback) override;
   void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie,
                                std::string source_scheme,
@@ -370,6 +372,7 @@
   void SetCookieWithOptions(const GURL& url,
                             const std::string& cookie_line,
                             const CookieOptions& options,
+                            base::Optional<base::Time> server_time,
                             SetCookiesCallback callback);
 
   void DeleteCanonicalCookie(const CanonicalCookie& cookie,
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index 55e2cc72..228cfcd 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -62,7 +62,7 @@
                  const GURL& gurl,
                  const std::string& cookie) {
     cm->SetCookieWithOptionsAsync(
-        gurl, cookie, options_,
+        gurl, cookie, options_, base::nullopt /* server_time */,
         base::BindOnce(&SetCookieCallback::Run, base::Unretained(this)));
     WaitForCallback();
   }
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index 6315274..13b34f7 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_samples.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/strcat.h"
@@ -152,7 +153,7 @@
     ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cm->SetCanonicalCookieAsync(
         CanonicalCookie::Create(url, cookie_line, creation_time,
-                                CookieOptions()),
+                                base::nullopt /* server_time */),
         url.scheme(), CookieOptions(), callback.MakeCallback());
     callback.WaitUntilDone();
     return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
@@ -955,7 +956,7 @@
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call1;
   cookie_monster_->SetCanonicalCookieAsync(
       CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
-                              CookieOptions()),
+                              base::nullopt /* server_time */),
       http_www_foo_.url().scheme(), CookieOptions(), call1.MakeCallback());
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(call1.was_run());
@@ -968,7 +969,7 @@
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> call2;
   cookie_monster_->SetCanonicalCookieAsync(
       CanonicalCookie::Create(http_www_foo_.url(), "X=Y", base::Time::Now(),
-                              CookieOptions()),
+                              base::nullopt /* server_time */),
       http_www_foo_.url().scheme(), CookieOptions(), call2.MakeCallback());
   ASSERT_TRUE(call2.was_run());
   EXPECT_EQ(call2.result(), CanonicalCookie::CookieInclusionStatus::INCLUDE);
@@ -1224,7 +1225,7 @@
 
   cookie_monster_->SetCanonicalCookieAsync(
       CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
-                              CookieOptions()),
+                              base::nullopt /* server_time */),
       http_www_foo_.url().scheme(), CookieOptions(),
       set_cookies_callback.MakeCallback());
 
@@ -1451,13 +1452,14 @@
   GURL http_url("http://host/path");
 
   base::Time now = base::Time::Now();
+  base::Optional<base::Time> server_time = base::nullopt;
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
             SetCookieReturnStatus(cm.get(), http_url, "x=1"));
-  EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
-            SetCanonicalCookieReturnStatus(
-                cm.get(),
-                CanonicalCookie::Create(http_url, "y=1", now, CookieOptions()),
-                "http", false /*modify_httponly*/));
+  EXPECT_EQ(
+      CanonicalCookie::CookieInclusionStatus::INCLUDE,
+      SetCanonicalCookieReturnStatus(
+          cm.get(), CanonicalCookie::Create(http_url, "y=1", now, server_time),
+          "http", false /*modify_httponly*/));
 
   EXPECT_EQ(
       CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
@@ -1465,16 +1467,15 @@
   EXPECT_EQ(
       CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
       SetCanonicalCookieReturnStatus(
-          cm.get(),
-          CanonicalCookie::Create(foo_url, "y=1", now, CookieOptions()), "foo",
-          false /*modify_httponly*/));
+          cm.get(), CanonicalCookie::Create(foo_url, "y=1", now, server_time),
+          "foo", false /*modify_httponly*/));
 
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
             SetCookieReturnStatus(cm_foo.get(), foo_url, "x=1"));
   EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE,
             SetCanonicalCookieReturnStatus(
                 cm_foo.get(),
-                CanonicalCookie::Create(foo_url, "y=1", now, CookieOptions()),
+                CanonicalCookie::Create(foo_url, "y=1", now, server_time),
                 "foo", false /*modify_httponly*/));
 
   EXPECT_EQ(
@@ -1484,8 +1485,8 @@
       CanonicalCookie::CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
       SetCanonicalCookieReturnStatus(
           cm_foo.get(),
-          CanonicalCookie::Create(http_url, "y=1", now, CookieOptions()),
-          "http", false /*modify_httponly*/));
+          CanonicalCookie::Create(http_url, "y=1", now, server_time), "http",
+          false /*modify_httponly*/));
 }
 
 TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
@@ -2198,6 +2199,7 @@
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
       set_cookie_callback;
   cm->SetCookieWithOptionsAsync(kUrl, "a=b", CookieOptions(),
+                                base::nullopt /* server_time */,
                                 set_cookie_callback.MakeCallback());
 
   GetCookieListCallback get_cookie_list_callback1;
@@ -2256,8 +2258,8 @@
   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
   // When passed to the CookieMonster, it takes ownership of the pointed to
   // cookies.
-  cookies.push_back(
-      CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(), CookieOptions()));
+  cookies.push_back(CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(),
+                                            base::nullopt /* server_time */));
   ASSERT_TRUE(cookies[0]);
   store->TakeCallbackAt(0).Run(std::move(cookies));
 
@@ -2285,6 +2287,7 @@
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
       set_cookie_callback;
   cm->SetCookieWithOptionsAsync(kUrl, "a=b", CookieOptions(),
+                                base::nullopt /* server_time */,
                                 set_cookie_callback.MakeCallback());
 
   GetCookieListCallback get_cookie_list_callback2;
@@ -2335,6 +2338,7 @@
       &RunClosureOnCookieListReceived,
       base::BindOnce(&CookieStore::SetCookieWithOptionsAsync,
                      base::Unretained(cm.get()), kUrl, "a=b", CookieOptions(),
+                     base::nullopt /* server_time */,
                      set_cookie_callback.MakeCallback())));
 
   // Get cookie task. Queued before the delete task is executed, so should not
@@ -2541,8 +2545,9 @@
 TEST_F(CookieMonsterTest, InvalidExpiryTime) {
   std::string cookie_line =
       std::string(kValidCookieLine) + "; expires=Blarg arg arg";
-  std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
-      http_www_foo_.url(), cookie_line, Time::Now(), CookieOptions()));
+  std::unique_ptr<CanonicalCookie> cookie(
+      CanonicalCookie::Create(http_www_foo_.url(), cookie_line, Time::Now(),
+                              base::nullopt /* server_time */));
   ASSERT_FALSE(cookie->IsPersistent());
 }
 
@@ -3130,7 +3135,7 @@
       callback_set;
   cm.SetCanonicalCookieAsync(
       CanonicalCookie::Create(GURL("http://a.com/"), "A=B", base::Time::Now(),
-                              CookieOptions()),
+                              base::nullopt /* server_time */),
       "http", CookieOptions(), callback_set.MakeCallback());
 
   // Get cookies for a different URL.
@@ -3204,10 +3209,11 @@
   GURL url("http://www.example.com");
   std::string cookie_line = "foo=bar";
   CookieOptions options;
+  base::Optional<base::Time> server_time = base::nullopt;
   CookieMonster cm(nullptr, nullptr);
 
   // Write a cookie created at |t1|.
-  auto cookie = CanonicalCookie::Create(url, cookie_line, t1, options);
+  auto cookie = CanonicalCookie::Create(url, cookie_line, t1, server_time);
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
       set_callback_1;
   cm.SetCanonicalCookieAsync(std::move(cookie), url.scheme(), options,
@@ -3215,7 +3221,7 @@
   set_callback_1.WaitUntilDone();
 
   // Overwrite the cookie at |t2|.
-  cookie = CanonicalCookie::Create(url, cookie_line, t2, options);
+  cookie = CanonicalCookie::Create(url, cookie_line, t2, server_time);
   ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus>
       set_callback_2;
   cm.SetCanonicalCookieAsync(std::move(cookie), url.scheme(), options,
@@ -3224,7 +3230,7 @@
 
   // The second cookie overwrites the first one but it will inherit the creation
   // timestamp |t1|. Test that deleting the new cookie still works.
-  cookie = CanonicalCookie::Create(url, cookie_line, t2, options);
+  cookie = CanonicalCookie::Create(url, cookie_line, t2, server_time);
   ResultSavingCookieCallback<unsigned int> delete_callback;
   cm.DeleteCanonicalCookieAsync(*cookie, delete_callback.MakeCallback());
   delete_callback.WaitUntilDone();
@@ -3236,18 +3242,15 @@
   std::string cookie_line = "foo=bar; SameSite=Lax";
 
   CookieMonster cm(nullptr, nullptr);
-  CookieOptions env_same_site;
-  env_same_site.set_same_site_cookie_context(
-      CookieOptions::SameSiteCookieContext::SAME_SITE_LAX);
-
   CookieOptions env_cross_site;
   env_cross_site.set_same_site_cookie_context(
       CookieOptions::SameSiteCookieContext::CROSS_SITE);
 
   CanonicalCookie::CookieInclusionStatus status;
   // Cookie can be created successfully; SameSite is not checked on Creation.
-  auto cookie = CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
-                                        env_same_site, &status);
+  auto cookie =
+      CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
+                              base::nullopt /* server_time */, &status);
   ASSERT_TRUE(cookie != nullptr);
   ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
 
@@ -3268,8 +3271,9 @@
   CanonicalCookie::CookieInclusionStatus status;
   // Cookie can be created successfully from an any url. Secure is not checked
   // on Create.
-  auto cookie = CanonicalCookie::Create(
-      http_url, cookie_line, base::Time::Now(), CookieOptions(), &status);
+  auto cookie =
+      CanonicalCookie::Create(http_url, cookie_line, base::Time::Now(),
+                              base::nullopt /* server_time */, &status);
 
   ASSERT_TRUE(cookie != nullptr);
   ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
@@ -3290,8 +3294,9 @@
   CookieMonster cm(nullptr, nullptr);
   CanonicalCookie::CookieInclusionStatus status;
   // Cookie can be created successfully; HttpOnly is not checked on Create.
-  auto cookie = CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
-                                        CookieOptions(), &status);
+  auto cookie =
+      CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
+                              base::nullopt /* server_time */, &status);
 
   ASSERT_TRUE(cookie != nullptr);
   ASSERT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
diff --git a/net/cookies/cookie_options.cc b/net/cookies/cookie_options.cc
index 135bf6d..c3a06a9 100644
--- a/net/cookies/cookie_options.cc
+++ b/net/cookies/cookie_options.cc
@@ -13,7 +13,6 @@
     : exclude_httponly_(true),
       same_site_cookie_context_(SameSiteCookieContext::CROSS_SITE),
       update_access_time_(true),
-      server_time_(),
       return_excluded_cookies_(false) {}
 
 }  // namespace net
diff --git a/net/cookies/cookie_options.h b/net/cookies/cookie_options.h
index 2633272..a50fe92 100644
--- a/net/cookies/cookie_options.h
+++ b/net/cookies/cookie_options.h
@@ -52,15 +52,6 @@
     return same_site_cookie_context_;
   }
 
-  // |server_time| indicates what the server sending us the Cookie thought the
-  // current time was when the cookie was produced.  This is used to adjust for
-  // clock skew between server and host.
-  void set_server_time(const base::Time& server_time) {
-    server_time_ = server_time;
-  }
-  bool has_server_time() const { return !server_time_.is_null(); }
-  base::Time server_time() const { return server_time_; }
-
   void set_update_access_time() { update_access_time_ = true; }
   void set_do_not_update_access_time() { update_access_time_ = false; }
   bool update_access_time() const { return update_access_time_; }
@@ -73,7 +64,6 @@
   bool exclude_httponly_;
   SameSiteCookieContext same_site_cookie_context_;
   bool update_access_time_;
-  base::Time server_time_;
   bool return_excluded_cookies_;
 };
 
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h
index d6299f5..f550571 100644
--- a/net/cookies/cookie_store.h
+++ b/net/cookies/cookie_store.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
 #include "net/cookies/canonical_cookie.h"
@@ -53,16 +54,21 @@
 
   virtual ~CookieStore();
 
-  // Sets the cookies specified by |cookie_list| returned from |url|
+  // Sets the cookies specified by |cookie_line| returned from |url|
   // with options |options| in effect.  Expects a cookie line, like
   // "a=1; domain=b.com".
   //
+  // |server_time| indicates what the server sending us the Cookie
+  // thought the current time was when the cookie was produced.  This is used to
+  // adjust for clock skew between server and host.
+  //
   // Fails either if the cookie is invalid or if this is a non-HTTPONLY cookie
   // and it would overwrite an existing HTTPONLY cookie.
   // Returns true if the cookie is successfully set.
   virtual void SetCookieWithOptionsAsync(const GURL& url,
                                          const std::string& cookie_line,
                                          const CookieOptions& options,
+                                         base::Optional<base::Time> server_time,
                                          SetCookiesCallback callback) = 0;
 
   // Set the cookie on the cookie store.  |cookie.IsCanonical()| must
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 8467a98..45b2e3f 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -89,10 +89,11 @@
     const GURL& url,
     const std::string& cookie_line,
     const CookieOptions& options,
+    base::Optional<base::Time> server_time,
     CookieMonster::SetCookiesCallback callback) {
   did_run_ = false;
   cookie_monster_->SetCookieWithOptionsAsync(
-      url, cookie_line, options,
+      url, cookie_line, options, server_time,
       base::Bind(&DelayedCookieMonster::SetCookiesInternalCallback,
                  base::Unretained(this)));
   DCHECK_EQ(did_run_, true);
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index 9708821..ca5e355 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -12,7 +12,9 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/synchronization/lock.h"
+#include "base/time/time.h"
 #include "net/cookies/cookie_change_dispatcher.h"
 #include "net/log/net_log_with_source.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,6 +57,7 @@
       const GURL& url,
       const std::string& cookie_line,
       const CookieOptions& options,
+      base::Optional<base::Time> server_time,
       CookieMonster::SetCookiesCallback callback) override;
 
   void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie,
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index 77e4ae8..06ca0740 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -185,13 +185,15 @@
     return callback.cookies();
   }
 
-  bool SetCookieWithOptions(CookieStore* cs,
-                            const GURL& url,
-                            const std::string& cookie_line,
-                            const CookieOptions& options) {
+  bool SetCookieWithOptions(
+      CookieStore* cs,
+      const GURL& url,
+      const std::string& cookie_line,
+      const CookieOptions& options,
+      base::Optional<base::Time> server_time = base::nullopt) {
     DCHECK(cs);
     ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
-    cs->SetCookieWithOptionsAsync(url, cookie_line, options,
+    cs->SetCookieWithOptionsAsync(url, cookie_line, options, server_time,
                                   callback.MakeCallback());
     callback.WaitUntilDone();
     return callback.result() == CanonicalCookie::CookieInclusionStatus::INCLUDE;
@@ -221,8 +223,8 @@
     CookieOptions options;
     if (!CookieStoreTestTraits::supports_http_only)
       options.set_include_httponly();
-    options.set_server_time(server_time);
-    return SetCookieWithOptions(cs, url, cookie_line, options);
+    return SetCookieWithOptions(cs, url, cookie_line, options,
+                                base::make_optional(server_time));
   }
 
   bool SetCookie(CookieStore* cs,
@@ -248,6 +250,7 @@
     DCHECK(cs);
     ResultSavingCookieCallback<CanonicalCookie::CookieInclusionStatus> callback;
     cs->SetCookieWithOptionsAsync(url, cookie_line, options,
+                                  base::nullopt /* server_time */,
                                   callback.MakeCallback());
     callback.WaitUntilDone();
     return callback.result();
@@ -559,9 +562,9 @@
   // A Secure cookie can be created from an insecure URL, but is rejected upon
   // setting.
   CanonicalCookie::CookieInclusionStatus status;
-  auto cookie =
-      CanonicalCookie::Create(this->http_www_foo_.url(), "foo=1; Secure",
-                              base::Time::Now(), CookieOptions(), &status);
+  auto cookie = CanonicalCookie::Create(
+      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,
@@ -600,14 +603,12 @@
                 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT),
             "http", false /* modify_http_only */));
 
-    // A HttpOnly cookie can be created with any CookieOptions, but is rejected
+    // A HttpOnly cookie can be created, but is rejected
     // upon setting if the options do not specify include_httponly.
     CanonicalCookie::CookieInclusionStatus status;
-    CookieOptions options_no_httponly;
-    options_no_httponly.set_exclude_httponly();  // Default, but make explicit.
     auto c = CanonicalCookie::Create(this->http_www_foo_.url(),
                                      "bar=1; HttpOnly", base::Time::Now(),
-                                     options_no_httponly, &status);
+                                     base::nullopt /* server_time */, &status);
     EXPECT_TRUE(c->IsHttpOnly());
     EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::INCLUDE, status);
     EXPECT_EQ(CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
@@ -1188,13 +1189,14 @@
   this->MatchCookieLines(cookie_line,
                          this->GetCookiesWithOptions(cs, url, options));
 
-  options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
-  this->SetCookieWithOptions(cs, url, set_cookie_line, options);
+  base::Optional<base::Time> server_time =
+      base::make_optional(base::Time::Now() - base::TimeDelta::FromHours(1));
+  this->SetCookieWithOptions(cs, url, set_cookie_line, options, server_time);
   this->MatchCookieLines(cookie_line,
                          this->GetCookiesWithOptions(cs, url, options));
 
-  options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
-  this->SetCookieWithOptions(cs, url, set_cookie_line, options);
+  server_time = base::Time::Now() + base::TimeDelta::FromHours(1);
+  this->SetCookieWithOptions(cs, url, set_cookie_line, options, server_time);
   this->MatchCookieLines(cookie_line,
                          this->GetCookiesWithOptions(cs, url, options));
 }
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 250d32d8..072e9a0f 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -1809,11 +1809,11 @@
   callback.WaitUntilDone();
   EXPECT_EQ(0u, callback.cookie_list_size());
   callback.Reset();
-  net::CookieOptions options;
   helper1.request_context()->cookie_store()->SetCookieWithOptionsAsync(
       GURL(GetURLFromTemplateWithoutParameters(
           config_.dns_over_https_servers[0].server_template)),
-      "test-cookie=you-still-fail", options,
+      "test-cookie=you-still-fail", CookieOptions(),
+      base::nullopt /* server_time */,
       base::Bind(&CookieCallback::SetCookieCallback,
                  base::Unretained(&callback)));
   EXPECT_TRUE(helper1.RunUntilDone(transaction_factory_.get()));
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index d99062e..1daf7053 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/stringprintf.h"
@@ -1235,7 +1236,7 @@
       set_cookie_callback;
   cookie_monster->SetCookieWithOptionsAsync(
       GURL("gopher://subdomain.gopheriffic.com/page"), "A=B; max-age=3600",
-      CookieOptions(),
+      CookieOptions(), base::nullopt /* server_time */,
       base::BindOnce(&ResultSavingCookieCallback<
                          CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
@@ -1250,7 +1251,7 @@
         set_cookie_callback2;
     cookie_monster->SetCookieWithOptionsAsync(
         GURL(base::StringPrintf("http://example%d.com/", i)),
-        "A=B; max-age=3600", CookieOptions(),
+        "A=B; max-age=3600", CookieOptions(), base::nullopt /* server_time */,
         base::BindOnce(&ResultSavingCookieCallback<
                            CanonicalCookie::CookieInclusionStatus>::Run,
                        base::Unretained(&set_cookie_callback2)));
@@ -1304,6 +1305,7 @@
       set_cookie_callback;
   cookie_monster->SetCookieWithOptionsAsync(
       GURL("http://www.example.com/"), "A=B; max-age=3600", CookieOptions(),
+      base::nullopt /* server_time */,
       base::BindOnce(&ResultSavingCookieCallback<
                          CanonicalCookie::CookieInclusionStatus>::Run,
                      base::Unretained(&set_cookie_callback)));
@@ -1335,9 +1337,9 @@
       {{Op::kDelete, Op::kAdd, Op::kDelete}, 1u},
       {{Op::kDelete, Op::kAdd, Op::kUpdate, Op::kDelete}, 1u}};
 
-  std::unique_ptr<CanonicalCookie> cookie =
-      CanonicalCookie::Create(GURL("http://www.example.com/path"), "Tasty=Yes",
-                              base::Time::Now(), CookieOptions());
+  std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+      GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
+      base::nullopt /* server_time */);
 
   for (const TestCase& testcase : testcases) {
     Create(false, false, true /* want current thread to invoke the store. */);
@@ -1388,13 +1390,13 @@
                NetLogWithSource());
   run_loop.Run();
 
-  std::unique_ptr<CanonicalCookie> cookie1 =
-      CanonicalCookie::Create(GURL("http://www.example.com/path"), "Tasty=Yes",
-                              base::Time::Now(), CookieOptions());
+  std::unique_ptr<CanonicalCookie> cookie1 = CanonicalCookie::Create(
+      GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
+      base::nullopt /* server_time */);
 
-  std::unique_ptr<CanonicalCookie> cookie2 =
-      CanonicalCookie::Create(GURL("http://not.example.com/path"), "Tasty=No",
-                              base::Time::Now(), CookieOptions());
+  std::unique_ptr<CanonicalCookie> cookie2 = CanonicalCookie::Create(
+      GURL("http://not.example.com/path"), "Tasty=No", base::Time::Now(),
+      base::nullopt /* server_time */);
 
   // Wedge the background thread to make sure that it doesn't start consuming
   // the queue.
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc
index b9b4174..32293fa 100644
--- a/net/reporting/reporting_uploader_unittest.cc
+++ b/net/reporting/reporting_uploader_unittest.cc
@@ -444,6 +444,7 @@
       cookie_callback;
   context_.cookie_store()->SetCookieWithOptionsAsync(
       server_.GetURL("/"), "foo=bar", CookieOptions(),
+      base::nullopt /* server_time */,
       base::BindRepeating(&ResultSavingCookieCallback<
                               CanonicalCookie::CookieInclusionStatus>::Run,
                           base::Unretained(&cookie_callback)));
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 19979888..c6c013b 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -18,6 +18,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
@@ -709,12 +710,12 @@
   }
 
   base::Time response_date;
-  if (!GetResponseHeaders()->GetDateValue(&response_date))
-    response_date = base::Time();
+  base::Optional<base::Time> server_time = base::nullopt;
+  if (GetResponseHeaders()->GetDateValue(&response_date))
+    server_time = base::make_optional(response_date);
 
   CookieOptions options;
   options.set_include_httponly();
-  options.set_server_time(response_date);
   options.set_same_site_cookie_context(
       net::cookie_util::ComputeSameSiteContextForResponse(
           request_->url(), request_->site_for_cookies(),
@@ -744,7 +745,7 @@
     num_cookie_lines_left_++;
 
     std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
-        request_->url(), cookie_string, base::Time::Now(), options,
+        request_->url(), cookie_string, base::Time::Now(), server_time,
         &returned_status);
 
     if (returned_status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
@@ -752,6 +753,7 @@
                         returned_status);
       continue;
     }
+    DCHECK(cookie);
 
     if (!CanSetCookie(*cookie, &options)) {
       OnSetCookieResult(
@@ -762,7 +764,7 @@
     }
 
     request_->context()->cookie_store()->SetCookieWithOptionsAsync(
-        request_->url(), cookie_string, options,
+        request_->url(), cookie_string, options, server_time,
         base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
                        weak_factory_.GetWeakPtr(), options,
                        base::make_optional<CanonicalCookie>(*cookie),
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 7907e95..b37083e 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -2689,12 +2689,12 @@
   replace_scheme.SetSchemeStr("https");
   GURL url = test_server.base_url().ReplaceComponents(replace_scheme);
 
-  delayed_cm->SetCookieWithOptionsAsync(url, "AlreadySetCookie=1;Secure",
-                                        CookieOptions(),
-                                        CookieStore::SetCookiesCallback());
-  cm->SetCookieWithOptionsAsync(url, "AlreadySetCookie=1;Secure",
-                                CookieOptions(),
-                                CookieStore::SetCookiesCallback());
+  delayed_cm->SetCookieWithOptionsAsync(
+      url, "AlreadySetCookie=1;Secure", CookieOptions(),
+      base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
+  cm->SetCookieWithOptionsAsync(
+      url, "AlreadySetCookie=1;Secure", CookieOptions(),
+      base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
 
   std::vector<std::string> cookie_lines(
       {// Fails in SetCanonicalCookie for trying to set a secure cookie
@@ -8747,9 +8747,9 @@
 
     std::unique_ptr<CookieMonster> cm =
         std::make_unique<CookieMonster>(nullptr, nullptr);
-    cm->SetCookieWithOptionsAsync(url_requiring_auth_wo_cookies,
-                                  "another_cookie=true", CookieOptions(),
-                                  CookieStore::SetCookiesCallback());
+    cm->SetCookieWithOptionsAsync(
+        url_requiring_auth_wo_cookies, "another_cookie=true", CookieOptions(),
+        base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
     context.set_cookie_store(cm.get());
     context.Init();
 
@@ -8774,9 +8774,9 @@
     // Check maybe_sent_cookies on second roundtrip.
     request->set_maybe_sent_cookies({});
     cm->DeleteAllAsync(CookieStore::DeleteCallback());
-    cm->SetCookieWithOptionsAsync(url_requiring_auth_wo_cookies,
-                                  "one_more_cookie=true", CookieOptions(),
-                                  CookieStore::SetCookiesCallback());
+    cm->SetCookieWithOptionsAsync(
+        url_requiring_auth_wo_cookies, "one_more_cookie=true", CookieOptions(),
+        base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
 
     request->SetAuth(AuthCredentials(kUser, kSecret));
     delegate.RunUntilComplete();
@@ -9145,9 +9145,9 @@
     context.set_network_delegate(&filtering_network_delegate);
     std::unique_ptr<CookieMonster> cm =
         std::make_unique<CookieMonster>(nullptr, nullptr);
-    cm->SetCookieWithOptionsAsync(original_url, "another_cookie=true",
-                                  CookieOptions(),
-                                  CookieStore::SetCookiesCallback());
+    cm->SetCookieWithOptionsAsync(
+        original_url, "another_cookie=true", CookieOptions(),
+        base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
     context.set_cookie_store(cm.get());
     context.Init();
 
@@ -9171,9 +9171,9 @@
     // Check maybe_sent_cookies on second round trip
     request->set_maybe_sent_cookies({});
     cm->DeleteAllAsync(CookieStore::DeleteCallback());
-    cm->SetCookieWithOptionsAsync(original_url_wo_cookie,
-                                  "one_more_cookie=true", CookieOptions(),
-                                  CookieStore::SetCookiesCallback());
+    cm->SetCookieWithOptionsAsync(
+        original_url_wo_cookie, "one_more_cookie=true", CookieOptions(),
+        base::nullopt /* server_time */, CookieStore::SetCookiesCallback());
 
     request->FollowDeferredRedirect(base::nullopt, base::nullopt);
     delegate.RunUntilComplete();
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
index 65b5645..4c0087b 100644
--- a/net/websockets/websocket_stream_cookie_test.cc
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -150,7 +150,7 @@
 
   base::RunLoop run_loop;
   store->SetCookieWithOptionsAsync(
-      cookie_url, cookie_line, CookieOptions(),
+      cookie_url, cookie_line, CookieOptions(), base::nullopt /* server_time */,
       base::Bind(&SetCookieHelperFunction, run_loop.QuitClosure(),
                  weak_is_called.GetWeakPtr(),
                  weak_set_cookie_result.GetWeakPtr()));
diff --git a/pdf/pdfium/pdfium_permissions.cc b/pdf/pdfium/pdfium_permissions.cc
index 71b32e4..c3faafc 100644
--- a/pdf/pdfium/pdfium_permissions.cc
+++ b/pdf/pdfium/pdfium_permissions.cc
@@ -36,7 +36,7 @@
   // revision 3+. See table 3.20 in the PDF 1.7 spec.
   if (permission == PDFEngine::PERMISSION_PRINT_HIGH_QUALITY &&
       permissions_handler_revision_ >= 3) {
-    return (permission_bits_ & kPDFPermissionPrintLowQualityMask) != 0 &&
+    return (permission_bits_ & kPDFPermissionPrintMask) != 0 &&
            (permission_bits_ & kPDFPermissionPrintHighQualityMask) != 0;
   }
 
@@ -49,7 +49,7 @@
     case PDFEngine::PERMISSION_PRINT_HIGH_QUALITY:
       // With security handler revision 2 rules, check the same bit for high
       // and low quality. See table 3.20 in the PDF 1.7 spec.
-      return (permission_bits_ & kPDFPermissionPrintLowQualityMask) != 0;
+      return (permission_bits_ & kPDFPermissionPrintMask) != 0;
     default:
       return true;
   }
diff --git a/pdf/pdfium/pdfium_permissions.h b/pdf/pdfium/pdfium_permissions.h
index 137bbdd..9f0a7f6 100644
--- a/pdf/pdfium/pdfium_permissions.h
+++ b/pdf/pdfium/pdfium_permissions.h
@@ -12,7 +12,7 @@
 
 // See Table 3.20 in the PDF 1.7 spec for details on how to interpret permission
 // bits. Exposed for use in testing.
-constexpr uint32_t kPDFPermissionPrintLowQualityMask = 1 << 2;
+constexpr uint32_t kPDFPermissionPrintMask = 1 << 2;
 constexpr uint32_t kPDFPermissionPrintHighQualityMask = 1 << 11;
 constexpr uint32_t kPDFPermissionCopyMask = 1 << 4;
 constexpr uint32_t kPDFPermissionCopyAccessibleMask = 1 << 9;
diff --git a/pdf/pdfium/pdfium_permissions_unittest.cc b/pdf/pdfium/pdfium_permissions_unittest.cc
index d1edd19..79fff5f 100644
--- a/pdf/pdfium/pdfium_permissions_unittest.cc
+++ b/pdf/pdfium/pdfium_permissions_unittest.cc
@@ -29,20 +29,18 @@
 static_assert(kPDFPermissionCopyAccessibleMask == 0x200, "Wrong permission");
 static_assert(kPDFPermissionCopyMask == 0x10, "Wrong permission");
 static_assert(kPDFPermissionPrintHighQualityMask == 0x800, "Wrong permission");
-static_assert(kPDFPermissionPrintLowQualityMask == 0x4, "Wrong permission");
+static_assert(kPDFPermissionPrintMask == 0x4, "Wrong permission");
 
 // Sanity check the permission generation functions above do the right thing.
 static_assert(GeneratePermissions2(0) == 0xffffffc0, "Wrong permission");
 static_assert(GeneratePermissions2(kPDFPermissionCopyMask |
-                                   kPDFPermissionPrintLowQualityMask) ==
-                  0xffffffd4,
+                                   kPDFPermissionPrintMask) == 0xffffffd4,
               "Wrong permission");
 static_assert(GeneratePermissions3(0) == 0xfffff0c0, "Wrong permission");
 static_assert(GeneratePermissions3(kPDFPermissionCopyAccessibleMask |
                                    kPDFPermissionCopyMask |
                                    kPDFPermissionPrintHighQualityMask |
-                                   kPDFPermissionPrintLowQualityMask) ==
-                  0xfffffad4,
+                                   kPDFPermissionPrintMask) == 0xfffffad4,
               "Wrong permission");
 
 TEST(PDFiumPermissionTest, InvalidSecurityHandler) {
@@ -73,8 +71,8 @@
   EXPECT_FALSE(no_perms.HasPermission(kPermPrintLow));
   EXPECT_FALSE(no_perms.HasPermission(kPermPrintHigh));
 
-  permissions = GeneratePermissions2(kPDFPermissionCopyMask |
-                                     kPDFPermissionPrintLowQualityMask);
+  permissions =
+      GeneratePermissions2(kPDFPermissionCopyMask | kPDFPermissionPrintMask);
   auto all_known_perms = PDFiumPermissions::CreateForTesting(2, permissions);
   EXPECT_TRUE(all_known_perms.HasPermission(kPermCopy));
   EXPECT_TRUE(all_known_perms.HasPermission(kPermCopya11y));
@@ -88,7 +86,7 @@
   EXPECT_FALSE(no_print_perms.HasPermission(kPermPrintLow));
   EXPECT_FALSE(no_print_perms.HasPermission(kPermPrintHigh));
 
-  permissions = GeneratePermissions2(kPDFPermissionPrintLowQualityMask);
+  permissions = GeneratePermissions2(kPDFPermissionPrintMask);
   auto no_copy_perms = PDFiumPermissions::CreateForTesting(2, permissions);
   EXPECT_FALSE(no_copy_perms.HasPermission(kPermCopy));
   // TODO(crbug.com/989408) Should be the same as |PERMISSION_COPY|.
@@ -107,7 +105,7 @@
 
   permissions = GeneratePermissions3(
       kPDFPermissionCopyAccessibleMask | kPDFPermissionCopyMask |
-      kPDFPermissionPrintHighQualityMask | kPDFPermissionPrintLowQualityMask);
+      kPDFPermissionPrintHighQualityMask | kPDFPermissionPrintMask);
   auto all_known_perms = PDFiumPermissions::CreateForTesting(3, permissions);
   EXPECT_TRUE(all_known_perms.HasPermission(kPermCopy));
   EXPECT_TRUE(all_known_perms.HasPermission(kPermCopya11y));
@@ -123,9 +121,9 @@
   EXPECT_FALSE(copy_no_print_perms.HasPermission(kPermPrintLow));
   EXPECT_FALSE(copy_no_print_perms.HasPermission(kPermPrintHigh));
 
-  permissions = GeneratePermissions3(kPDFPermissionCopyAccessibleMask |
-                                     kPDFPermissionCopyMask |
-                                     kPDFPermissionPrintLowQualityMask);
+  permissions =
+      GeneratePermissions3(kPDFPermissionCopyAccessibleMask |
+                           kPDFPermissionCopyMask | kPDFPermissionPrintMask);
   auto copy_low_print_perms =
       PDFiumPermissions::CreateForTesting(3, permissions);
   EXPECT_TRUE(copy_low_print_perms.HasPermission(kPermCopy));
@@ -134,7 +132,7 @@
   EXPECT_FALSE(copy_low_print_perms.HasPermission(kPermPrintHigh));
 
   permissions = GeneratePermissions3(kPDFPermissionPrintHighQualityMask |
-                                     kPDFPermissionPrintLowQualityMask);
+                                     kPDFPermissionPrintMask);
   auto print_no_copy_perms =
       PDFiumPermissions::CreateForTesting(3, permissions);
   EXPECT_FALSE(print_no_copy_perms.HasPermission(kPermCopy));
@@ -144,7 +142,7 @@
 
   permissions = GeneratePermissions3(kPDFPermissionCopyAccessibleMask |
                                      kPDFPermissionPrintHighQualityMask |
-                                     kPDFPermissionPrintLowQualityMask);
+                                     kPDFPermissionPrintMask);
   auto print_a11y_copy_perms =
       PDFiumPermissions::CreateForTesting(3, permissions);
   EXPECT_FALSE(print_a11y_copy_perms.HasPermission(kPermCopy));
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.cc b/services/network/public/cpp/cookie_manager_mojom_traits.cc
index 1d823f0..371eb5a2 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -270,13 +270,6 @@
   else
     cookie_options->set_do_not_update_access_time();
 
-  base::Optional<base::Time> optional_server_time;
-  if (!mojo_options.ReadServerTime(&optional_server_time))
-    return false;
-  if (optional_server_time) {
-    cookie_options->set_server_time(*optional_server_time);
-  }
-
   if (mojo_options.return_excluded_cookies())
     cookie_options->set_return_excluded_cookies();
   else
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.h b/services/network/public/cpp/cookie_manager_mojom_traits.h
index ebc64a66..a324f71 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -59,11 +59,6 @@
   static bool update_access_time(const net::CookieOptions& o) {
     return o.update_access_time();
   }
-  static base::Optional<base::Time> server_time(const net::CookieOptions& o) {
-    if (!o.has_server_time())
-      return base::nullopt;
-    return base::Optional<base::Time>(o.server_time());
-  }
   static bool return_excluded_cookies(const net::CookieOptions& o) {
     return o.return_excluded_cookies();
   }
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom
index ebe47ed..b75edff 100644
--- a/services/network/public/mojom/cookie_manager.mojom
+++ b/services/network/public/mojom/cookie_manager.mojom
@@ -59,9 +59,6 @@
   bool exclude_httponly = true;
   CookieSameSiteContext same_site_cookie_context = CROSS_SITE;
   bool update_access_time = true;
-  // TODO(rdsmith): Remove this element from the mojo structure?  It's only
-  // used in the underlying net:: structure in CanonicalCookie::Create().
-  mojo_base.mojom.Time? server_time;
   bool return_excluded_cookies = false;
 };
 
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc
index 0cf25a1..3cba583e 100644
--- a/services/network/restricted_cookie_manager.cc
+++ b/services/network/restricted_cookie_manager.cc
@@ -410,9 +410,9 @@
     SetCookieFromStringCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  net::CookieOptions options = MakeOptionsForSet(role_, url, site_for_cookies);
   std::unique_ptr<net::CanonicalCookie> parsed_cookie =
-      net::CanonicalCookie::Create(url, cookie, base::Time::Now(), options);
+      net::CanonicalCookie::Create(url, cookie, base::Time::Now(),
+                                   base::nullopt /* server_time */);
   if (!parsed_cookie) {
     std::move(callback).Run();
     return;
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc
index ce4cca7..844379d 100644
--- a/services/network/restricted_cookie_manager_unittest.cc
+++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -598,9 +598,9 @@
 TEST_P(RestrictedCookieManagerTest, SetCanonicalCookiePolicy) {
   {
     // With default settings object, setting a third-party cookie is OK.
-    auto cookie =
-        net::CanonicalCookie::Create(GURL("http://example.com"), "A=B",
-                                     base::Time::Now(), net::CookieOptions());
+    auto cookie = net::CanonicalCookie::Create(GURL("http://example.com"),
+                                               "A=B", base::Time::Now(),
+                                               base::nullopt /* server_time */);
     EXPECT_TRUE(sync_service_->SetCanonicalCookie(
         *cookie, GURL("http://example.com"), GURL("http://notexample.com")));
   }
@@ -624,9 +624,9 @@
   {
     // Not if third-party cookies are disabled, though.
     cookie_settings_.set_block_third_party_cookies(true);
-    auto cookie =
-        net::CanonicalCookie::Create(GURL("http://example.com"), "A2=B2",
-                                     base::Time::Now(), net::CookieOptions());
+    auto cookie = net::CanonicalCookie::Create(GURL("http://example.com"),
+                                               "A2=B2", base::Time::Now(),
+                                               base::nullopt /* server_time */);
     EXPECT_FALSE(sync_service_->SetCanonicalCookie(
         *cookie, GURL("http://example.com"), GURL("http://otherexample.com")));
   }
@@ -668,12 +668,9 @@
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeature(net::features::kSameSiteByDefaultCookies);
 
-  // Uses different options between create/set here for failure to be at set.
-  net::CookieOptions create_options;
-  create_options.set_same_site_cookie_context(
-      net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
   auto cookie = net::CanonicalCookie::Create(GURL("http://example.com"), "A=B",
-                                             base::Time::Now(), create_options);
+                                             base::Time::Now(),
+                                             base::nullopt /* server_time */);
   EXPECT_FALSE(sync_service_->SetCanonicalCookie(
       *cookie, GURL("http://example.com"), GURL("http://notexample.com")));
 
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 1f922fb..5a7809ff 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -3744,7 +3744,7 @@
 
     context()->cookie_store()->SetCookieWithOptionsAsync(
         test_server()->GetURL("/"), "a=b", net::CookieOptions(),
-        base::DoNothing());
+        base::nullopt /* server_time */, base::DoNothing());
 
     base::RunLoop delete_run_loop;
     mojom::URLLoaderPtr loader;
@@ -3788,7 +3788,8 @@
     // Set the path to an irrelevant url to block the cookie from sending
     context()->cookie_store()->SetCookieWithOptionsAsync(
         test_server()->GetURL("/"), "a=b;Path=/something-else",
-        net::CookieOptions(), base::DoNothing());
+        net::CookieOptions(), base::nullopt /* server_time */,
+        base::DoNothing());
 
     base::RunLoop delete_run_loop;
     mojom::URLLoaderPtr loader;
diff --git a/services/tracing/perfetto/consumer_host.cc b/services/tracing/perfetto/consumer_host.cc
index ce54023..07646373 100644
--- a/services/tracing/perfetto/consumer_host.cc
+++ b/services/tracing/perfetto/consumer_host.cc
@@ -448,7 +448,8 @@
   percent_full = std::min(std::max(0.0, percent_full), 1.0);
   bool data_loss = buf_stats.chunks_overwritten() > 0 ||
                    buf_stats.chunks_discarded() > 0 ||
-                   buf_stats.abi_violations() > 0;
+                   buf_stats.abi_violations() > 0 ||
+                   buf_stats.trace_writer_packet_loss() > 0;
   std::move(request_buffer_usage_callback_).Run(true, percent_full, data_loss);
 }
 
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc
index c9eb290..921877c2 100644
--- a/services/tracing/perfetto/json_trace_exporter.cc
+++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -361,6 +361,8 @@
                          buf_stats.readaheads_succeeded());
     buf_dict->SetInteger("readaheads_failed", buf_stats.readaheads_failed());
     buf_dict->SetInteger("abi_violations", buf_stats.abi_violations());
+    buf_dict->SetInteger("trace_writer_packet_loss",
+                         buf_stats.trace_writer_packet_loss());
     buf_list->GetList().push_back(std::move(buf_value));
   }
   dict->SetList("buffer_stats", std::move(buf_list));
diff --git a/services/tracing/perfetto/system_perfetto_unittest.cc b/services/tracing/perfetto/system_perfetto_unittest.cc
index 5913adc2..19443e8 100644
--- a/services/tracing/perfetto/system_perfetto_unittest.cc
+++ b/services/tracing/perfetto/system_perfetto_unittest.cc
@@ -147,6 +147,11 @@
               .reset();
         }));
     RunUntilIdle();
+    // The producer client will be destroyed in the next iteration of the test,
+    // but the sequence it was used on disappears with the
+    // |scoped_task_environment_|. So we reset the sequence so it can be freely
+    // destroyed.
+    PerfettoTracedProcess::Get()->producer_client()->ResetSequenceForTesting();
     if (old_tmp_dir_) {
       // Restore the old value back to its initial value.
       setenv("TMPDIR", old_tmp_dir_, true);
@@ -236,6 +241,7 @@
         }
       });
   system_data_source_enabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStarted();
 
   // Post a task to ensure we stop the trace after the data is written.
   base::RunLoop stop_tracing;
@@ -248,6 +254,7 @@
 
   system_data_source_disabled_runloop.Run();
   system_no_more_packets_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStopped();
 
   EXPECT_EQ(1u, system_consumer.received_packets());
   PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
@@ -320,6 +327,7 @@
       &system_data_source_disabled_runloop);
 
   system_data_source_enabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStarted();
 
   // Now start the local trace and wait for the system trace to stop first.
   base::RunLoop local_data_source_enabled_runloop;
@@ -343,7 +351,9 @@
       kPerfettoProducerName, kPerfettoTestDataSourceName,
       local_service()->GetService(), local_producer_client.get());
 
+  system_consumer.WaitForAllDataSourcesStopped();
   system_data_source_disabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStarted();
   local_data_source_enabled_runloop.Run();
 
   // Ensures that the Trace data gets written and committed.
@@ -364,11 +374,13 @@
 
   local_consumer.StopTracing();
   local_data_source_disabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStopped();
   local_no_more_packets_runloop.Run();
 
   // Wait for system tracing to return before stopping the trace on the correct
   // sequence to ensure everything is committed.
   system_data_source_reenabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStarted();
   base::RunLoop stop_tracing;
   PerfettoTracedProcess::GetTaskRunner()->PostTask(
       [&system_consumer, &stop_tracing]() {
@@ -378,6 +390,7 @@
   stop_tracing.Run();
 
   system_data_source_redisabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStopped();
   system_no_more_packets_runloop.Run();
 
   // |local_consumer| should have seen one |send_packet_count_| from each data
@@ -414,12 +427,14 @@
       local_service()->GetService(), local_producer_client.get());
 
   local_data_source_enabled_runloop.Run();
+  local_consumer->WaitForAllDataSourcesStarted();
 
   // Ensures that the Trace data gets written and committed.
   RunUntilIdle();
 
   local_consumer->StopTracing();
   local_data_source_disabled_runloop.Run();
+  local_consumer->WaitForAllDataSourcesStopped();
   local_no_more_packets_runloop.Run();
   EXPECT_EQ(7u, local_consumer->received_packets());
 
@@ -457,6 +472,7 @@
   for (auto& loop : data_sources_wrote_data) {
     loop.Run();
   }
+  system_consumer.WaitForAllDataSourcesStarted();
 
   // Wait for system tracing to return before stopping the trace on the correct
   // sequence to ensure everything is committed.
@@ -469,6 +485,7 @@
   stop_tracing.Run();
 
   system_data_source_disabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStopped();
   system_no_more_packets_runloop.Run();
 
   // Once we StopTracing() on the system trace the we want to make sure a new
@@ -485,7 +502,9 @@
   local_consumer->StartTracing();
 
   local_data_source_reenabled_runloop.Run();
+  local_consumer->WaitForAllDataSourcesStarted();
   local_consumer->StopTracing();
+  local_consumer->WaitForAllDataSourcesStopped();
   local_data_source_redisabled_runloop.Run();
 
   // |local_consumer| should have seen one |send_packet_count_| from each data
@@ -522,6 +541,7 @@
       &system_data_source_disabled_runloop);
 
   system_data_source_enabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStarted();
 
   // Now start the local trace and wait for the system trace to stop first.
   base::RunLoop local_data_source_enabled_runloop;
@@ -546,7 +566,9 @@
       });
 
   system_data_source_disabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStopped();
   local_data_source_enabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStarted();
 
   // Ensures that the Trace data gets written and committed.
   RunUntilIdle();
@@ -563,10 +585,12 @@
 
   local_consumer.StopTracing();
   local_data_source_disabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStopped();
   local_no_more_packets_runloop.Run();
 
   // Wait for system tracing to return before stopping.
   system_data_source_reenabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStarted();
 
   base::RunLoop stop_tracing;
   PerfettoTracedProcess::GetTaskRunner()->PostTask(
@@ -624,6 +648,7 @@
       });
 
   local_data_source_enabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStarted();
 
   // Ensures that the Trace data gets written and committed.
   RunUntilIdle();
@@ -661,6 +686,7 @@
   local_stop_tracing.Run();
 
   local_data_source_disabled_runloop.Run();
+  local_consumer.WaitForAllDataSourcesStopped();
   local_no_more_packets_runloop.Run();
 
   // Now the system trace will start.
@@ -668,6 +694,7 @@
   for (auto& loop : data_sources_wrote_data) {
     loop.Run();
   }
+  system_consumer.WaitForAllDataSourcesStarted();
 
   // Wait for system tracing to return before stopping.
   base::RunLoop system_stop_tracing;
@@ -679,6 +706,7 @@
   system_stop_tracing.Run();
 
   system_data_source_disabled_runloop.Run();
+  system_consumer.WaitForAllDataSourcesStopped();
   system_no_more_packets_runloop.Run();
 
   // |local_consumer| & |system_consumer| should have seen one
@@ -734,6 +762,7 @@
     if (!check_sdk_level) {
       system_data_source_enabled_runloop.Run();
       data_source_started_runloop.Run();
+      system_consumer.WaitForAllDataSourcesStarted();
     }
 
     // Post the task to ensure that the data will have been written and
@@ -748,6 +777,7 @@
 
     if (!check_sdk_level) {
       system_data_source_disabled_runloop.Run();
+      system_consumer.WaitForAllDataSourcesStopped();
     }
     system_no_more_packets_runloop.Run();
 
diff --git a/services/tracing/perfetto/system_test_utils.cc b/services/tracing/perfetto/system_test_utils.cc
index df1689f..6dde009 100644
--- a/services/tracing/perfetto/system_test_utils.cc
+++ b/services/tracing/perfetto/system_test_utils.cc
@@ -82,8 +82,8 @@
     const perfetto::DataSourceConfig& data_source_config) {
   AndroidSystemProducer::StartDataSource(id, data_source_config);
   CHECK_LT(num_data_sources_active_, num_data_sources_expected_);
-  if (data_source_enabled_callback_ &&
-      ++num_data_sources_active_ == num_data_sources_expected_) {
+  if (++num_data_sources_active_ == num_data_sources_expected_ &&
+      data_source_enabled_callback_) {
     std::move(data_source_enabled_callback_).Run();
   }
 }
@@ -92,7 +92,7 @@
     perfetto::DataSourceInstanceID id) {
   AndroidSystemProducer::StopDataSource(id);
   CHECK_GT(num_data_sources_active_, 0u);
-  if (data_source_disabled_callback_ && --num_data_sources_active_ == 0) {
+  if (--num_data_sources_active_ == 0 && data_source_disabled_callback_) {
     std::move(data_source_disabled_callback_).Run();
   }
 }
diff --git a/services/tracing/perfetto/test_utils.cc b/services/tracing/perfetto/test_utils.cc
index ffa0e51..11f0dafe 100644
--- a/services/tracing/perfetto/test_utils.cc
+++ b/services/tracing/perfetto/test_utils.cc
@@ -119,8 +119,8 @@
                                   std::move(callback));
 
   CHECK_LT(num_data_sources_active_, num_data_sources_expected_);
-  if (client_enabled_callback_ &&
-      ++num_data_sources_active_ == num_data_sources_expected_) {
+  if (++num_data_sources_active_ == num_data_sources_expected_ &&
+      client_enabled_callback_) {
     std::move(client_enabled_callback_).Run();
   }
 }
@@ -130,7 +130,7 @@
   ProducerClient::StopDataSource(id, std::move(callback));
 
   CHECK_GT(num_data_sources_active_, 0u);
-  if (client_disabled_callback_ && --num_data_sources_active_ == 0) {
+  if (--num_data_sources_active_ == 0 && client_disabled_callback_) {
     std::move(client_disabled_callback_).Run();
   }
 }
@@ -163,9 +163,14 @@
 MockConsumer::MockConsumer(std::vector<std::string> data_source_names,
                            perfetto::TracingService* service,
                            PacketReceivedCallback packet_received_callback)
-    : packet_received_callback_(packet_received_callback),
-      data_source_names_(data_source_names) {
-  CHECK(!data_source_names_.empty());
+    : packet_received_callback_(packet_received_callback) {
+  for (const auto& source : data_source_names) {
+    data_sources_.emplace_back(DataSourceStatus{
+        source,
+        perfetto::ObservableEvents::DataSourceInstanceStateChange::
+            DataSourceInstanceState::DATA_SOURCE_INSTANCE_STATE_STOPPED});
+  }
+  CHECK(!data_sources_.empty());
   consumer_endpoint_ = service->ConnectConsumer(this, /*uid=*/0);
   CHECK(consumer_endpoint_);
 }
@@ -186,9 +191,9 @@
 void MockConsumer::StartTracing() {
   perfetto::TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(1024 * 32);
-  for (const auto& name : data_source_names_) {
+  for (const auto& data_source : data_sources_) {
     auto* ds_config = trace_config.add_data_sources()->mutable_config();
-    ds_config->set_name(name);
+    ds_config->set_name(data_source.name);
     ds_config->set_target_buffer(0);
   }
 
@@ -202,6 +207,8 @@
 }
 
 void MockConsumer::OnConnect() {
+  consumer_endpoint_->ObserveEvents(
+      perfetto::ConsumerEndpoint::kDataSourceInstances);
   StartTracing();
 }
 void MockConsumer::OnDisconnect() {}
@@ -225,6 +232,66 @@
 void MockConsumer::OnTraceStats(bool /*success*/, const perfetto::TraceStats&) {
 }
 
+void MockConsumer::OnObservableEvents(
+    const perfetto::ObservableEvents& events) {
+  for (const auto& change : events.instance_state_changes()) {
+    for (auto& data_source_status : data_sources_) {
+      if (change.data_source_name() != data_source_status.name) {
+        continue;
+      }
+      data_source_status.state = change.state();
+    }
+    CheckForAllDataSourcesStarted();
+    CheckForAllDataSourcesStopped();
+  }
+}
+
+void MockConsumer::WaitForAllDataSourcesStarted() {
+  base::RunLoop on_started;
+  on_started_runloop_ = &on_started;
+  CheckForAllDataSourcesStarted();
+  if (on_started_runloop_) {
+    on_started_runloop_->Run();
+  }
+}
+
+void MockConsumer::WaitForAllDataSourcesStopped() {
+  base::RunLoop on_stopped;
+  on_stopped_runloop_ = &on_stopped;
+  CheckForAllDataSourcesStopped();
+  if (on_stopped_runloop_) {
+    on_stopped_runloop_->Run();
+  }
+}
+
+void MockConsumer::CheckForAllDataSourcesStarted() {
+  for (auto& data_source_status : data_sources_) {
+    if (data_source_status.state !=
+        perfetto::ObservableEvents::DataSourceInstanceStateChange::
+            DATA_SOURCE_INSTANCE_STATE_STARTED) {
+      return;
+    }
+  }
+  if (on_started_runloop_) {
+    on_started_runloop_->Quit();
+    on_started_runloop_ = nullptr;
+  }
+}
+
+void MockConsumer::CheckForAllDataSourcesStopped() {
+  for (auto& data_source_status : data_sources_) {
+    if (data_source_status.state !=
+        perfetto::ObservableEvents::DataSourceInstanceStateChange::
+            DATA_SOURCE_INSTANCE_STATE_STOPPED) {
+      return;
+    }
+  }
+  if (on_stopped_runloop_) {
+    on_stopped_runloop_->Quit();
+    on_stopped_runloop_ = nullptr;
+  }
+}
+
 MockProducerHost::MockProducerHost(
     const std::string& producer_name,
     const std::string& data_source_name,
diff --git a/services/tracing/perfetto/test_utils.h b/services/tracing/perfetto/test_utils.h
index bb70b5c0..1d46942 100644
--- a/services/tracing/perfetto/test_utils.h
+++ b/services/tracing/perfetto/test_utils.h
@@ -14,6 +14,11 @@
 #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
 #include "services/tracing/public/cpp/perfetto/producer_client.h"
 #include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h"
+#include "third_party/perfetto/protos/perfetto/common/observable_events.pb.h"
+
+namespace base {
+class RunLoop;
+}
 
 namespace tracing {
 
@@ -121,14 +126,27 @@
   void OnDetach(bool success) override;
   void OnAttach(bool success, const perfetto::TraceConfig&) override;
   void OnTraceStats(bool success, const perfetto::TraceStats&) override;
-  void OnObservableEvents(const perfetto::ObservableEvents&) override {}
+
+  void OnObservableEvents(const perfetto::ObservableEvents&) override;
+  void WaitForAllDataSourcesStarted();
+  void WaitForAllDataSourcesStopped();
 
  private:
+  void CheckForAllDataSourcesStarted();
+  void CheckForAllDataSourcesStopped();
+
   std::unique_ptr<perfetto::TracingService::ConsumerEndpoint>
       consumer_endpoint_;
   size_t received_packets_ = 0;
   PacketReceivedCallback packet_received_callback_;
-  std::vector<std::string> data_source_names_;
+  struct DataSourceStatus {
+    std::string name;
+    perfetto::ObservableEvents::DataSourceInstanceStateChange::
+        DataSourceInstanceState state;
+  };
+  std::vector<DataSourceStatus> data_sources_;
+  base::RunLoop* on_started_runloop_ = nullptr;
+  base::RunLoop* on_stopped_runloop_ = nullptr;
 };
 
 class MockProducerHost : public ProducerHost {
diff --git a/services/tracing/public/cpp/perfetto/android_system_producer.cc b/services/tracing/public/cpp/perfetto/android_system_producer.cc
index d3f2d482..f7a4249 100644
--- a/services/tracing/public/cpp/perfetto/android_system_producer.cc
+++ b/services/tracing/public/cpp/perfetto/android_system_producer.cc
@@ -45,11 +45,13 @@
 }
 
 bool AndroidSystemProducer::IsTracingActive() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return data_sources_tracing_ > 0;
 }
 
 void AndroidSystemProducer::NewDataSourceAdded(
     const PerfettoTracedProcess::DataSourceBase* const data_source) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (state_ != State::kConnected) {
     return;
   }
@@ -62,53 +64,36 @@
 
 void AndroidSystemProducer::DisconnectWithReply(
     base::OnceClosure on_disconnect_complete) {
-  task_runner()->GetOrCreateTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          [](base::WeakPtr<AndroidSystemProducer> weak_ptr,
-             base::OnceClosure callback) {
-            DCHECK(!callback.is_null());
-            if (!weak_ptr) {
-              // If we aren't around anymore then we're fully disconnected and
-              // the callback is safe to run.
-              std::move(callback).Run();
-              return;
-            }
-            // If we are tracing we need to wait until we're fully disconnected
-            // to run the callback, otherwise we run it immediately (we will
-            // still unregister the data sources but that can happen async in
-            // the background).
-            if (weak_ptr->IsTracingActive() ||
-                !weak_ptr->on_disconnect_callbacks_.empty()) {
-              weak_ptr->on_disconnect_callbacks_.push_back(std::move(callback));
-            } else {
-              std::move(callback).Run();
-            }
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // If we are tracing we need to wait until we're fully disconnected
+  // to run the callback, otherwise we run it immediately (we will
+  // still unregister the data sources but that can happen async in
+  // the background).
+  if (!on_disconnect_complete.is_null()) {
+    if (IsTracingActive() || !on_disconnect_callbacks_.empty()) {
+      on_disconnect_callbacks_.push_back(std::move(on_disconnect_complete));
+    } else {
+      std::move(on_disconnect_complete).Run();
+    }
+  }
 
-            if (weak_ptr->state_ == State::kConnected) {
-              // We are connected and need to unregister the DataSources to
-              // inform the service these data sources are going away. If we
-              // are currently tracing the service will ask for them to shut
-              // down asynchronously.
-              //
-              // Note that the system service may have concurrently posted a
-              // task to request one of these data sources to start. However we
-              // will ignore such requests by verifying that we're allowed to
-              // trace in StartDataSource().
-              for (const auto* const data_source :
-                   PerfettoTracedProcess::Get()->data_sources()) {
-                DCHECK(weak_ptr->service_.get());
-                weak_ptr->service_->UnregisterDataSource(data_source->name());
-              }
-            }
-            weak_ptr->DelayedReconnect();
-          },
-          weak_ptr_factory_.GetWeakPtr(),
-          // This ensures no matter what is passed in the PostTask above can
-          // call the callback which simplifies the branches inside the task.
-          on_disconnect_complete.is_null()
-              ? base::DoNothing().Once()
-              : std::move(on_disconnect_complete)));
+  if (state_ == State::kConnected) {
+    // We are connected and need to unregister the DataSources to
+    // inform the service these data sources are going away. If we
+    // are currently tracing the service will ask for them to shut
+    // down asynchronously.
+    //
+    // Note that the system service may have concurrently posted a
+    // task to request one of these data sources to start. However we
+    // will ignore such requests by verifying that we're allowed to
+    // trace in StartDataSource().
+    for (const auto* const data_source :
+         PerfettoTracedProcess::Get()->data_sources()) {
+      DCHECK(service_.get());
+      service_->UnregisterDataSource(data_source->name());
+    }
+  }
+  DelayedReconnect();
 }
 
 void AndroidSystemProducer::OnConnect() {
@@ -177,7 +162,7 @@
 
   for (auto* const data_source : PerfettoTracedProcess::Get()->data_sources()) {
     if (data_source->name() == config.name()) {
-      PerfettoTracedProcess::Get()->CanStartTracing(
+      auto can_trace = PerfettoTracedProcess::Get()->CanStartTracing(
           this,
           base::BindOnce(
               [](base::WeakPtr<AndroidSystemProducer> weak_ptr,
@@ -194,6 +179,10 @@
                 weak_ptr->service_->NotifyDataSourceStarted(id);
               },
               weak_ptr_factory_.GetWeakPtr(), data_source, id, config));
+      if (!can_trace) {
+        DisconnectWithReply(base::OnceClosure());
+      }
+      return;
     }
   }
 }
@@ -265,6 +254,7 @@
 void AndroidSystemProducer::CommitData(
     const perfetto::CommitDataRequest& commit,
     CommitDataCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(service_);
   service_->CommitData(commit, std::move(callback));
 }
@@ -352,7 +342,8 @@
           {mojom::kPerfettoProducerNamePrefix,
            base::NumberToString(
                base::trace_event::TraceLog::GetInstance()->process_id())}),
-      task_runner());
+      task_runner(),
+      perfetto::TracingService::ProducerSMBScrapingMode::kEnabled);
 }
 
 bool AndroidSystemProducer::SkipIfPreAndroidPie() const {
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
index 5c3b4e1..f9d583f4 100644
--- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
+++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
@@ -187,6 +187,7 @@
 bool PerfettoTracedProcess::CanStartTracing(
     PerfettoProducer* producer,
     base::OnceCallback<void()> start_tracing) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // If the |producer| asking is the local producer_client_ it has priority so
   // even if the other endpoint is tracing shut down the other endpoint and let
   // the |producer_client_| go. The system Producer will periodically attempt to
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc
index e94a4c25..5b98411 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -52,6 +52,10 @@
                      std::move(producer_host_info)));
 }
 
+void ProducerClient::ResetSequenceForTesting() {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
 // The Mojo binding should run on the same sequence as the one we get
 // callbacks from Perfetto on, to avoid additional PostTasks.
 void ProducerClient::BindClientAndHostPipesOnSequence(
@@ -102,6 +106,7 @@
 }
 
 bool ProducerClient::IsTracingActive() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return data_sources_tracing_ > 0;
 }
 
diff --git a/services/tracing/public/cpp/perfetto/producer_client.h b/services/tracing/public/cpp/perfetto/producer_client.h
index 70d5674..7f064c5d 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/services/tracing/public/cpp/perfetto/producer_client.h
@@ -91,6 +91,7 @@
 
   void BindClientAndHostPipesForTesting(mojom::ProducerClientRequest,
                                         mojom::ProducerHostPtrInfo);
+  void ResetSequenceForTesting();
 
  protected:
   perfetto::SharedMemoryArbiter* GetSharedMemoryArbiter() override;
diff --git a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
index adbcfba6..1628ad54 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
+++ b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.cc
@@ -25,7 +25,7 @@
     std::unique_ptr<base::Unwinder> unwinder) {}
 
 void StackSamplerAndroid::RecordStackFrames(
-    StackBuffer* stack_buffer,
+    base::StackBuffer* stack_buffer,
     base::ProfileBuilder* profile_builder) {
   if (!unwinder_.is_initialized()) {
     // May block on disk access. This function is executed on the profiler
diff --git a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
index 0da1e02..7eb7bd8 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
+++ b/services/tracing/public/cpp/stack_sampling/stack_sampler_android.h
@@ -28,7 +28,7 @@
 
   // StackSampler:
   void AddAuxUnwinder(std::unique_ptr<base::Unwinder> unwinder) override;
-  void RecordStackFrames(StackBuffer* stack_buffer,
+  void RecordStackFrames(base::StackBuffer* stack_buffer,
                          base::ProfileBuilder* profile_builder) override;
 
  private:
diff --git a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
index 19290bb2..1004ade 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
+++ b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.cc
@@ -18,6 +18,7 @@
 #include "base/debug/proc_maps_linux.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/profiler/stack_buffer.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/trace_event/cfi_backtrace_android.h"
@@ -92,7 +93,7 @@
                const tracing::StackUnwinderAndroid* unwinder,
                uintptr_t original_sp,
                size_t stack_size,
-               base::StackSampler::StackBuffer* stack_buffer,
+               base::StackBuffer* stack_buffer,
                const void** out_trace,
                size_t max_depth)
       : use_libunwind_(use_libunwind),
@@ -120,7 +121,7 @@
   size_t Unwind(uintptr_t original_sp,
                 unw_context_t* context,
                 const ucontext_t& signal_context,
-                base::StackSampler::StackBuffer* stack_buffer) {
+                base::StackBuffer* stack_buffer) {
     const uintptr_t new_stack_top = initial_sp_;
     // Set the frame to the return frame from signal handler.
     current_ip_ = signal_context.uc_mcontext.arm_pc;
@@ -311,10 +312,9 @@
     return ptr_address;
   }
 
-  void RewritePointersAndGetMarkers(
-      base::StackSampler::StackBuffer* stack_buffer,
-      uintptr_t original_sp,
-      size_t stack_size) {
+  void RewritePointersAndGetMarkers(base::StackBuffer* stack_buffer,
+                                    uintptr_t original_sp,
+                                    size_t stack_size) {
     jni_markers_.clear();
     uintptr_t* new_stack = stack_buffer->buffer();
     constexpr uint32_t marker_l =
@@ -398,7 +398,7 @@
   // The context of the return function from signal context.
   ucontext_t* ucontext;
   // Buffer to copy the stack segment.
-  base::StackSampler::StackBuffer* stack_buffer;
+  base::StackBuffer* stack_buffer;
   size_t* stack_size;
 };
 
@@ -534,11 +534,10 @@
   return helper.Unwind(sp, &context, sigcontext, nullptr);
 }
 
-size_t StackUnwinderAndroid::TraceStack(
-    base::PlatformThreadId tid,
-    base::StackSampler::StackBuffer* stack_buffer,
-    const void** out_trace,
-    size_t max_depth) const {
+size_t StackUnwinderAndroid::TraceStack(base::PlatformThreadId tid,
+                                        base::StackBuffer* stack_buffer,
+                                        const void** out_trace,
+                                        size_t max_depth) const {
   // Stops the thread with given tid with a signal handler. The signal handler
   // copies the stack of the thread and returns. This function tries to unwind
   // stack frames from the copied stack.
@@ -579,7 +578,7 @@
 
 bool StackUnwinderAndroid::SuspendThreadAndRecordStack(
     base::PlatformThreadId tid,
-    base::StackSampler::StackBuffer* stack_buffer,
+    base::StackBuffer* stack_buffer,
     uintptr_t* sp,
     size_t* stack_size,
     unw_context_t* context,
diff --git a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.h b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.h
index a970d1c..ae30180 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.h
+++ b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android.h
@@ -52,7 +52,7 @@
   // Same as above function, but pauses the thread with the given |tid| and then
   // unwinds. |tid| should not be current thread's.
   size_t TraceStack(base::PlatformThreadId tid,
-                    base::StackSampler::StackBuffer* stack_buffer,
+                    base::StackBuffer* stack_buffer,
                     const void** out_trace,
                     size_t max_depth) const;
 
@@ -69,18 +69,17 @@
   // Sends a SIGURG signal to the thread with id |tid| and copies the stack
   // segment of the thread, along with register context. Returns true on
   // success.
-  bool SuspendThreadAndRecordStack(
-      base::PlatformThreadId tid,
-      base::StackSampler::StackBuffer* stack_buffer,
-      uintptr_t* sp,
-      size_t* stack_size,
-      unw_context_t* context,
-      ucontext_t* signal_context) const;
+  bool SuspendThreadAndRecordStack(base::PlatformThreadId tid,
+                                   base::StackBuffer* stack_buffer,
+                                   uintptr_t* sp,
+                                   size_t* stack_size,
+                                   unw_context_t* context,
+                                   ucontext_t* signal_context) const;
 
   // Replaces any pointers to the old stack to point to the new stack segment.
   // Returns the jni markers found on stack while scanning stack for pointers.
   std::vector<const JniMarker*> RewritePointersAndGetMarkers(
-      base::StackSampler::StackBuffer* stack_buffer,
+      base::StackBuffer* stack_buffer,
       uintptr_t sp,
       size_t stack_size) const;
 
diff --git a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android_unittest.cc b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android_unittest.cc
index 1a03dfe71..7222fab 100644
--- a/services/tracing/public/cpp/stack_sampling/stack_unwinder_android_unittest.cc
+++ b/services/tracing/public/cpp/stack_sampling/stack_unwinder_android_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/android/jni_generator/jni_generator_helper.h"
 #include "base/bind.h"
+#include "base/profiler/stack_buffer.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_task_environment.h"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 1f05e4b..8429987 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -8187,6 +8187,32 @@
         },
         "test": "unit_tests"
       }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-features=BackForwardCache"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webkit_layout_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04"
+            }
+          ],
+          "shards": 12
+        }
+      }
     ]
   },
   "linux-blink-animation-use-time-delta": {
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json
index 6f7533e..e658664 100644
--- a/testing/buildbot/client.v8.fyi.json
+++ b/testing/buildbot/client.v8.fyi.json
@@ -1271,8 +1271,7 @@
             {
               "os": "Ubuntu-16.04"
             }
-          ],
-          "hard_timeout": 900
+          ]
         },
         "test": "blink_unittests"
       }
@@ -1298,7 +1297,6 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "hard_timeout": 900,
           "shards": 12
         }
       }
@@ -1321,8 +1319,7 @@
             {
               "os": "Ubuntu-16.04"
             }
-          ],
-          "hard_timeout": 900
+          ]
         },
         "test": "blink_unittests"
       }
@@ -1330,7 +1327,8 @@
     "isolated_scripts": [
       {
         "args": [
-          "--num-retries=3"
+          "--num-retries=3",
+          "--debug"
         ],
         "isolate_name": "blink_web_tests_exparchive",
         "merge": {
@@ -1348,7 +1346,6 @@
               "os": "Ubuntu-16.04"
             }
           ],
-          "hard_timeout": 900,
           "shards": 12
         }
       }
@@ -1419,10 +1416,9 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13"
             }
-          ],
-          "hard_timeout": 900
+          ]
         },
         "test": "blink_unittests"
       }
@@ -1445,10 +1441,9 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Mac-10.13.6"
+              "os": "Mac-10.13"
             }
           ],
-          "hard_timeout": 900,
           "shards": 12
         }
       }
@@ -1469,10 +1464,9 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-15063"
+              "os": "Windows-7-SP1"
             }
-          ],
-          "hard_timeout": 900
+          ]
         },
         "test": "blink_unittests"
       }
@@ -1495,10 +1489,9 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Windows-10-15063"
+              "os": "Windows-7-SP1"
             }
           ],
-          "hard_timeout": 900,
           "shards": 12
         }
       }
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index d60ceb0..494a181 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1763,6 +1763,11 @@
           'shards': 1,
         },
       },
+      'linux-bfcache-rel': {
+        'args': [
+          '--additional-driver-flag=--enable-features=BackForwardCache',
+        ],
+      },
       'linux-blink-animation-use-time-delta': {
         'args': [
           '--debug',
@@ -2006,6 +2011,12 @@
           '--additional-driver-flag=--use-gpu-in-tests',
         ],
       },
+      # client.v8.fyi
+      'V8 Blink Linux Debug': {
+        'args': [
+          '--debug',
+        ],
+      },
     },
   },
   'webkit_unit_tests': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 2611a588..fd5371e 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1720,6 +1720,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'bfcache_gtests',
+          'isolated_scripts': 'chromium_webkit_isolated_scripts',
         },
       },
       'linux-blink-animation-use-time-delta': {
@@ -4148,28 +4149,18 @@
         ],
       },
       'V8 Blink Linux': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'os': 'Ubuntu-16.04',
-            },
-          ],
-          'hard_timeout': 900,
-        },
+        'mixins': [
+          'linux-xenial',
+        ],
         'test_suites': {
           'gtest_tests': 'layout_ng_gtests',
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
         },
       },
       'V8 Blink Linux Debug': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'os': 'Ubuntu-16.04',
-            },
-          ],
-          'hard_timeout': 900,
-        },
+        'mixins': [
+          'linux-xenial',
+        ],
         'test_suites': {
           'gtest_tests': 'layout_ng_gtests',
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
@@ -4193,10 +4184,9 @@
         'swarming': {
           'dimension_sets': [
             {
-              'os': 'Mac-10.13.6',
+              'os': 'Mac-10.13',
             },
           ],
-          'hard_timeout': 900,
         },
         'test_suites': {
           'gtest_tests': 'layout_ng_gtests',
@@ -4204,14 +4194,9 @@
         },
       },
       'V8 Blink Win': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'os': 'Windows-10-15063',
-            },
-          ],
-          'hard_timeout': 900,
-        },
+        'mixins': [
+          'win7',
+        ],
         'test_suites': {
           'gtest_tests': 'layout_ng_gtests',
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 2116cb6..9235e92 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4200,6 +4200,25 @@
             ]
         }
     ],
+    "ProactivelySwapBrowsingInstance": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "ProactivelySwapBrowsingInstance"
+                    ]
+                }
+            ]
+        }
+    ],
     "ProgressBarAnimationAndroid": [
         {
             "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore
index c21d7d8..e1b200c7 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -13,6 +13,7 @@
 /android_build_tools/art/profman
 /android_build_tools/bundletool/*.jar
 /android_ndk/
+/android_sdk/androidx_browser/src
 /android_sdk/public/
 /android_sdk/sources/
 /android_protobuf/src
diff --git a/third_party/android_sdk/androidx_browser/BUILD.gn b/third_party/android_sdk/androidx_browser/BUILD.gn
new file mode 100644
index 0000000..6077716
--- /dev/null
+++ b/third_party/android_sdk/androidx_browser/BUILD.gn
@@ -0,0 +1,54 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_resources("androidx_browser_resources") {
+  resource_dirs = [ "src/browser/src/main/res" ]
+  custom_package = "android.support.customtabs"
+}
+
+android_library("androidx_browser_java") {
+  java_files = [
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabColorSchemeParams.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsSessionToken.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/PostMessageService.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/PostMessageServiceConnection.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsServiceConnection.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsCallback.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/PostMessageBackend.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsService.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/CustomTabsClient.java",
+    "./src/browser/src/main/java/androidx/browser/customtabs/TrustedWebUtils.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForM.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/NotificationApiHelperForO.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceWrapper.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityServiceConnectionManager.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityService.java",
+    "./src/browser/src/main/java/androidx/browser/trusted/TrustedWebActivityBuilder.java",
+
+  ]
+  deps = [
+    ":androidx_browser_resources",
+    "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
+    "//third_party/android_deps:com_android_support_support_compat_java",
+  ]
+  srcjar_deps = [ ":androidx_browser_service_aidl" ]
+  android_manifest_for_lint = "src/browser/src/main/AndroidManifest.xml"
+  chromium_code = false
+}
+
+android_aidl("androidx_browser_service_aidl") {
+  interface_file = "common.aidl"
+
+  sources = [
+    "./src/browser/src/main/aidl/android/support/customtabs/ICustomTabsService.aidl",
+    "./src/browser/src/main/aidl/android/support/customtabs/IPostMessageService.aidl",
+    "./src/browser/src/main/aidl/android/support/customtabs/trusted/ITrustedWebActivityService.aidl",
+    "./src/browser/src/main/aidl/android/support/customtabs/ICustomTabsCallback.aidl",
+  ]
+}
diff --git a/third_party/android_sdk/androidx_browser/LICENSE b/third_party/android_sdk/androidx_browser/LICENSE
new file mode 100644
index 0000000..67db858
--- /dev/null
+++ b/third_party/android_sdk/androidx_browser/LICENSE
@@ -0,0 +1,175 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
diff --git a/third_party/android_sdk/androidx_browser/OWNERS b/third_party/android_sdk/androidx_browser/OWNERS
new file mode 100644
index 0000000..f728cfa
--- /dev/null
+++ b/third_party/android_sdk/androidx_browser/OWNERS
@@ -0,0 +1,6 @@
+lizeb@chromium.org
+peconn@chromium.org
+yusufo@chromium.org
+
+per-file *.aidl=set noparent
+per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/third_party/android_sdk/androidx_browser/README.chromium b/third_party/android_sdk/androidx_browser/README.chromium
new file mode 100644
index 0000000..27f4bb86
--- /dev/null
+++ b/third_party/android_sdk/androidx_browser/README.chromium
@@ -0,0 +1,28 @@
+Name: AndroidX Browser
+Short Name: AndroidX Browser
+URL: https://chromium.googlesource.com/external/gob/android/platform/frameworks/support/browser
+Version: 226da6c0dfb265404d3a67305802ab70a9ca6c80
+License: Apache 2.0
+Security Critical: yes
+License Android Compatible: yes
+
+Description:
+This is a copy of the files from androidx.browser to be used in Chromium.
+This covers Custom Tabs and Trusted Web Activities. The original code (not the
+Chromium hosted modified copy) can be found at:
+https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/browser/
+
+Local Modifications:
+Since Chromium does not yet rely on AndroidX (it still relies on the Android
+Support Library), various parts of androidx.browser have been omitted:
+- Browser Actions, which rely on androidx.concurrent.futures.ResolvableFuture.
+  Chromium has dropped support for Browser Actions so we don't need this code.
+- Tests, which rely on androidx.testutils.PollingCheck. New development on
+  the code in androidx.browser should happen in the AndroidX repository
+  (and will be automatically copied to the Chromium one).
+
+In addition, we don't compile with the included AndroidManifest.xml because
+in the AndroidX the minSdkVersion is set in build.gradle. Chromium's tooling
+can't read this and expects the minSdkVersion to be present in the manifest
+(which conversely Android's tooling complains about). If we omit the
+AndroidManifest, Chromium's tooling chooses a sensible default.
diff --git a/third_party/android_sdk/androidx_browser/common.aidl b/third_party/android_sdk/androidx_browser/common.aidl
new file mode 100644
index 0000000..0eb2a8a
--- /dev/null
+++ b/third_party/android_sdk/androidx_browser/common.aidl
@@ -0,0 +1,8 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+interface android.support.customtabs.ICustomTabsService;
+interface android.support.customtabs.ICustomTabsCallback;
+interface android.support.customtabs.IPostMessageService;
+interface android.support.customtabs.trusted.ITrustedWebActivityService;
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 4bb74d1c..8ab9037 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -61,12 +61,14 @@
     "messaging/cloneable_message.cc",
     "messaging/cloneable_message_mojom_traits.cc",
     "messaging/message_port_channel.cc",
+    "messaging/message_port_descriptor.cc",
+    "messaging/message_port_descriptor_mojom_traits.cc",
     "messaging/string_message_codec.cc",
     "messaging/transferable_message.cc",
     "messaging/transferable_message_mojom_traits.cc",
     "mime_util/mime_util.cc",
-    "notifications/notification_resources.cc",
     "notifications/notification_mojom_traits.cc",
+    "notifications/notification_resources.cc",
     "notifications/platform_notification_data.cc",
     "origin_policy/origin_policy.cc",
     "origin_policy/origin_policy_parser.cc",
@@ -153,6 +155,7 @@
     "manifest/manifest_icon_selector_unittest.cc",
     "manifest/manifest_util_unittest.cc",
     "mediastream/media_devices_unittest.cc",
+    "messaging/message_port_descriptor_unittest.cc",
     "mime_util/mime_util_unittest.cc",
     "notifications/notification_mojom_traits_unittest.cc",
     "origin_policy/origin_policy_unittest.cc",
@@ -169,6 +172,7 @@
     "//mojo/core/embedder",
     "//net",
     "//skia/public/mojom",
+    "//testing/gmock",
     "//testing/gtest",
     "//third_party/blink/public/common:headers",
     "//third_party/boringssl",
diff --git a/third_party/blink/common/messaging/message_port_descriptor.cc b/third_party/blink/common/messaging/message_port_descriptor.cc
new file mode 100644
index 0000000..445dce4
--- /dev/null
+++ b/third_party/blink/common/messaging/message_port_descriptor.cc
@@ -0,0 +1,232 @@
+// 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/public/common/messaging/message_port_descriptor.h"
+
+#include <utility>
+
+namespace blink {
+
+namespace {
+
+MessagePortDescriptor::InstrumentationDelegate* g_instrumentation_delegate =
+    nullptr;
+
+}  // namespace
+
+// static
+const size_t MessagePortDescriptor::kInvalidSequenceNumber;
+
+// static
+const size_t MessagePortDescriptor::kFirstValidSequenceNumber;
+
+// static
+void MessagePortDescriptor::SetInstrumentationDelegate(
+    InstrumentationDelegate* delegate) {
+  // There should only ever be one delegate, and this only should toggle from
+  // being set to not being set and vice-versa. The toggling only ever occurs
+  // during tests; in production a single instrumentation delegate is installed
+  // early during Blink startup and left in place forever afterwards.
+  DCHECK(!delegate ^ !g_instrumentation_delegate);
+  g_instrumentation_delegate = delegate;
+}
+
+MessagePortDescriptor::MessagePortDescriptor() = default;
+
+MessagePortDescriptor::MessagePortDescriptor(
+    MessagePortDescriptor&& message_port)
+    : handle_(std::move(message_port.handle_)),
+#if DCHECK_IS_ON()
+      raw_handle_(
+          std::exchange(message_port.raw_handle_, mojo::MessagePipeHandle())),
+#endif
+      id_(std::exchange(message_port.id_, base::UnguessableToken::Null())),
+      sequence_number_(std::exchange(message_port.sequence_number_,
+                                     kInvalidSequenceNumber)) {
+#if DCHECK_IS_ON()
+  DCHECK_EQ(raw_handle_.value(), handle_.get().value());
+#endif
+}
+
+MessagePortDescriptor::~MessagePortDescriptor() {
+  Reset();
+}
+
+MessagePortDescriptor& MessagePortDescriptor::operator=(
+    MessagePortDescriptor&& message_port) {
+  Reset();
+
+  handle_ = std::move(message_port.handle_);
+#if DCHECK_IS_ON()
+  raw_handle_ =
+      std::exchange(message_port.raw_handle_, mojo::MessagePipeHandle());
+  DCHECK_EQ(raw_handle_.value(), handle_.get().value());
+#endif
+  id_ = std::exchange(message_port.id_, base::UnguessableToken::Null());
+  sequence_number_ =
+      std::exchange(message_port.sequence_number_, kInvalidSequenceNumber);
+
+  return *this;
+}
+
+bool MessagePortDescriptor::IsValid() const {
+  // |handle_| can be valid or invalid, depending on if we're entangled or
+  // not. But everything else should be consistent.
+#if DCHECK_IS_ON()
+  DCHECK_EQ(id_.is_empty(), !raw_handle_.is_valid());
+  DCHECK_EQ(sequence_number_ == kInvalidSequenceNumber,
+            !raw_handle_.is_valid());
+  return raw_handle_.is_valid();
+#else
+  DCHECK_EQ(id_.is_empty(), sequence_number_ == kInvalidSequenceNumber);
+  return !id_.is_empty() && sequence_number_ != kInvalidSequenceNumber;
+#endif
+}
+
+bool MessagePortDescriptor::IsEntangled() const {
+  // This descriptor is entangled if it's valid, but its handle has been loaned
+  // out.
+  return IsValid() && !handle_.is_valid();
+}
+
+bool MessagePortDescriptor::IsDefault() const {
+  if (IsValid())
+    return false;
+
+  // This is almost the converse of IsValid, except that we additionally expect
+  // the |handle_| to be empty as well (which IsValid doesn't verify).
+  DCHECK(!handle_.is_valid());
+  return true;
+}
+
+void MessagePortDescriptor::Reset() {
+  if (IsValid()) {
+    // Call NotifyDestroyed before clearing members, as the notification needs
+    // to access them.
+    NotifyDestroyed();
+
+    // Ensure that MessagePipeDescriptor-wrapped handles are fully accounted for
+    // over their entire lifetime.
+    DCHECK(handle_.is_valid());
+#if DCHECK_IS_ON()
+    DCHECK(raw_handle_.is_valid());
+    DCHECK_EQ(raw_handle_.value(), handle_.get().value());
+    raw_handle_ = mojo::MessagePipeHandle();
+#endif
+
+    handle_.reset();
+    id_ = base::UnguessableToken::Null();
+    sequence_number_ = kInvalidSequenceNumber;
+  }
+}
+
+void MessagePortDescriptor::Init(mojo::ScopedMessagePipeHandle handle,
+                                 base::UnguessableToken id,
+                                 uint64_t sequence_number) {
+  // Init is only called by deserialization code and thus should only be called
+  // on a default initialized descriptor.
+  DCHECK(IsDefault());
+
+  handle_ = std::move(handle);
+#if DCHECK_IS_ON()
+  raw_handle_ = handle_.get();
+#endif
+  id_ = id;
+  sequence_number_ = sequence_number;
+
+  // Init should only create a valid not-entangled descriptor, or a default
+  // descriptor.
+  DCHECK((IsValid() && !IsEntangled()) || IsDefault());
+}
+
+mojo::ScopedMessagePipeHandle MessagePortDescriptor::TakeHandle() {
+  DCHECK(handle_.is_valid());
+#if DCHECK_IS_ON()
+  DCHECK(raw_handle_.is_valid());
+  DCHECK_EQ(raw_handle_.value(), handle_.get().value());
+  raw_handle_ = mojo::MessagePipeHandle();
+#endif
+  return std::move(handle_);
+}
+
+base::UnguessableToken MessagePortDescriptor::TakeId() {
+  DCHECK(!id_.is_empty());
+  return std::exchange(id_, base::UnguessableToken::Null());
+}
+
+uint64_t MessagePortDescriptor::TakeSequenceNumber() {
+  DCHECK_NE(kInvalidSequenceNumber, sequence_number_);
+  return std::exchange(sequence_number_, kInvalidSequenceNumber);
+}
+
+mojo::ScopedMessagePipeHandle MessagePortDescriptor::TakeHandleToEntangle(
+    const base::UnguessableToken& execution_context_id) {
+  DCHECK(handle_.is_valid());
+  NotifyAttached(execution_context_id);
+  // Do not use TakeHandle, because it also resets |raw_handle_|. In DCHECK
+  // builds we use |raw_handle_| to ensure that the same handle is given back to
+  // us via "GiveDisentangledHandle".
+  return std::move(handle_);
+}
+
+void MessagePortDescriptor::GiveDisentangledHandle(
+    mojo::ScopedMessagePipeHandle handle) {
+  // We should only ever be given back the same handle that was taken from us.
+  DCHECK(!handle_.is_valid());
+#if DCHECK_IS_ON()
+  DCHECK_EQ(raw_handle_.value(), handle.get().value());
+#endif
+  handle_ = std::move(handle);
+  NotifyDetached();
+}
+
+MessagePortDescriptor::MessagePortDescriptor(
+    mojo::ScopedMessagePipeHandle handle)
+    : handle_(std::move(handle)),
+#if DCHECK_IS_ON()
+      raw_handle_(handle_.get()),
+#endif
+      id_(base::UnguessableToken::Create()),
+      sequence_number_(kFirstValidSequenceNumber) {
+}
+
+void MessagePortDescriptor::NotifyAttached(
+    const base::UnguessableToken& execution_context_id) {
+  DCHECK(!id_.is_empty());
+  if (g_instrumentation_delegate) {
+    g_instrumentation_delegate->NotifyMessagePortAttached(
+        id_, sequence_number_++, execution_context_id);
+  }
+}
+
+void MessagePortDescriptor::NotifyDetached() {
+  DCHECK(!id_.is_empty());
+  if (g_instrumentation_delegate) {
+    g_instrumentation_delegate->NotifyMessagePortDetached(id_,
+                                                          sequence_number_++);
+  }
+}
+
+void MessagePortDescriptor::NotifyDestroyed() {
+  DCHECK(!id_.is_empty());
+  if (g_instrumentation_delegate) {
+    g_instrumentation_delegate->NotifyMessagePortDestroyed(id_,
+                                                           sequence_number_++);
+  }
+}
+
+MessagePortDescriptorPair::MessagePortDescriptorPair() {
+  mojo::MessagePipe pipe;
+  port0_ = MessagePortDescriptor(std::move(pipe.handle0));
+  port1_ = MessagePortDescriptor(std::move(pipe.handle1));
+
+  // Notify the instrumentation that these ports are newly created and peers of
+  // each other.
+  if (g_instrumentation_delegate)
+    g_instrumentation_delegate->NotifyMessagePortPairCreated(*this);
+}
+
+MessagePortDescriptorPair::~MessagePortDescriptorPair() = default;
+
+}  // namespace blink
diff --git a/third_party/blink/common/messaging/message_port_descriptor_mojom_traits.cc b/third_party/blink/common/messaging/message_port_descriptor_mojom_traits.cc
new file mode 100644
index 0000000..5a26d94
--- /dev/null
+++ b/third_party/blink/common/messaging/message_port_descriptor_mojom_traits.cc
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h"
+
+#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+
+namespace blink {
+
+// Helper class that provides access to blink::MessagePortDescriptor internals.
+class MessagePortSerializationAccess {
+ public:
+  static void Init(blink::MessagePortDescriptor* output,
+                   mojo::ScopedMessagePipeHandle&& handle,
+                   base::UnguessableToken id,
+                   uint64_t sequence_number) {
+    output->Init(std::move(handle), id, sequence_number);
+  }
+
+  static mojo::ScopedMessagePipeHandle TakeHandle(
+      blink::MessagePortDescriptor& input) {
+    return input.TakeHandle();
+  }
+
+  static base::UnguessableToken TakeId(blink::MessagePortDescriptor& input) {
+    return input.TakeId();
+  }
+
+  static uint64_t TakeSequenceNumber(blink::MessagePortDescriptor& input) {
+    return input.TakeSequenceNumber();
+  }
+};
+
+}  // namespace blink
+
+namespace mojo {
+
+// static
+bool StructTraits<blink::mojom::MessagePortDescriptorDataView,
+                  blink::MessagePortDescriptor>::
+    Read(blink::mojom::MessagePortDescriptorDataView data,
+         blink::MessagePortDescriptor* output) {
+  mojo::ScopedMessagePipeHandle handle = data.TakePipeHandle();
+  uint64_t sequence_number = data.sequence_number();
+  base::UnguessableToken id;
+  if (!data.ReadId(&id))
+    return false;
+
+  blink::MessagePortSerializationAccess::Init(output, std::move(handle), id,
+                                              sequence_number);
+  return true;
+}
+
+// static
+mojo::ScopedMessagePipeHandle StructTraits<
+    blink::mojom::MessagePortDescriptorDataView,
+    blink::MessagePortDescriptor>::pipe_handle(blink::MessagePortDescriptor&
+                                                   input) {
+  return blink::MessagePortSerializationAccess::TakeHandle(input);
+}
+
+// static
+base::UnguessableToken StructTraits<
+    blink::mojom::MessagePortDescriptorDataView,
+    blink::MessagePortDescriptor>::id(blink::MessagePortDescriptor& input) {
+  return blink::MessagePortSerializationAccess::TakeId(input);
+}
+
+// static
+uint64_t StructTraits<blink::mojom::MessagePortDescriptorDataView,
+                      blink::MessagePortDescriptor>::
+    sequence_number(blink::MessagePortDescriptor& input) {
+  return blink::MessagePortSerializationAccess::TakeSequenceNumber(input);
+}
+
+}  // namespace mojo
diff --git a/third_party/blink/common/messaging/message_port_descriptor_unittest.cc b/third_party/blink/common/messaging/message_port_descriptor_unittest.cc
new file mode 100644
index 0000000..02f3d54ed
--- /dev/null
+++ b/third_party/blink/common/messaging/message_port_descriptor_unittest.cc
@@ -0,0 +1,264 @@
+// 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/public/common/messaging/message_port_descriptor.h"
+
+#include "base/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+namespace {
+
+class LenientMockInstrumentationDelegate
+    : public MessagePortDescriptor::InstrumentationDelegate {
+ public:
+  LenientMockInstrumentationDelegate() {
+    MessagePortDescriptor::SetInstrumentationDelegate(this);
+  }
+
+  ~LenientMockInstrumentationDelegate() override {
+    MessagePortDescriptor::SetInstrumentationDelegate(nullptr);
+  }
+
+  MOCK_METHOD1(NotifyMessagePortPairCreated,
+               void(const MessagePortDescriptorPair& pair));
+
+  MOCK_METHOD3(NotifyMessagePortAttached,
+               void(const base::UnguessableToken& port_id,
+                    uint64_t sequence_number,
+                    const base::UnguessableToken& execution_context_id));
+
+  MOCK_METHOD2(NotifyMessagePortDetached,
+               void(const base::UnguessableToken& port_id,
+                    uint64_t sequence_number));
+
+  MOCK_METHOD2(NotifyMessagePortDestroyed,
+               void(const base::UnguessableToken& port_id,
+                    uint64_t sequence_number));
+};
+
+using MockInstrumentationDelegate =
+    testing::StrictMock<LenientMockInstrumentationDelegate>;
+
+using testing::_;
+using testing::Invoke;
+
+}  // namespace
+
+class MessagePortDescriptorTestHelper {
+ public:
+  static void Init(MessagePortDescriptor* port,
+                   mojo::ScopedMessagePipeHandle handle,
+                   base::UnguessableToken id,
+                   uint64_t sequence_number) {
+    return port->Init(std::move(handle), id, sequence_number);
+  }
+
+  static mojo::ScopedMessagePipeHandle TakeHandle(MessagePortDescriptor* port) {
+    return port->TakeHandle();
+  }
+
+  static base::UnguessableToken TakeId(MessagePortDescriptor* port) {
+    return port->TakeId();
+  }
+
+  static uint64_t TakeSequenceNumber(MessagePortDescriptor* port) {
+    return port->TakeSequenceNumber();
+  }
+
+  static mojo::ScopedMessagePipeHandle TakeHandleToEntangle(
+      MessagePortDescriptor* port,
+      const base::UnguessableToken& execution_context_id) {
+    return port->TakeHandleToEntangle(execution_context_id);
+  }
+
+  static void GiveDisentangledHandle(MessagePortDescriptor* port,
+                                     mojo::ScopedMessagePipeHandle handle) {
+    return port->GiveDisentangledHandle(std::move(handle));
+  }
+};
+
+TEST(MessagePortDescriptorTest, InstrumentationAndSerializationWorks) {
+  MockInstrumentationDelegate delegate;
+
+  // A small struct for holding information gleaned about ports during their
+  // creation event. Allows verifying that other events are appropriately
+  // sequenced.
+  struct {
+    base::UnguessableToken token0;
+    base::UnguessableToken token1;
+    uint64_t seq0 = 1;
+    uint64_t seq1 = 1;
+  } created_data;
+
+  // Create a message handle descriptor pair and expect a notification.
+  EXPECT_CALL(delegate, NotifyMessagePortPairCreated(_))
+      .WillOnce(Invoke([&created_data](const MessagePortDescriptorPair& pair) {
+        created_data.token0 = pair.port0().id();
+        created_data.token1 = pair.port1().id();
+        EXPECT_EQ(1u, pair.port0().sequence_number());
+        EXPECT_EQ(1u, pair.port1().sequence_number());
+      }));
+  MessagePortDescriptorPair pair;
+
+  MessagePortDescriptor port0;
+  MessagePortDescriptor port1;
+  EXPECT_FALSE(port0.IsValid());
+  EXPECT_FALSE(port1.IsValid());
+  EXPECT_FALSE(port0.IsEntangled());
+  EXPECT_FALSE(port1.IsEntangled());
+  EXPECT_TRUE(port0.IsDefault());
+  EXPECT_TRUE(port1.IsDefault());
+  port0 = pair.TakePort0();
+  port1 = pair.TakePort1();
+  EXPECT_TRUE(port0.IsValid());
+  EXPECT_TRUE(port1.IsValid());
+  EXPECT_FALSE(port0.IsEntangled());
+  EXPECT_FALSE(port1.IsEntangled());
+  EXPECT_FALSE(port0.IsDefault());
+  EXPECT_FALSE(port1.IsDefault());
+
+  // Expect that the data received at creation matches the actual ports.
+  EXPECT_EQ(created_data.token0, port0.id());
+  EXPECT_EQ(created_data.seq0, port0.sequence_number());
+  EXPECT_EQ(created_data.token1, port1.id());
+  EXPECT_EQ(created_data.seq1, port1.sequence_number());
+
+  // Simulate that a handle is attached by taking the pipe handle.
+  base::UnguessableToken dummy_ec = base::UnguessableToken::Create();
+  EXPECT_CALL(delegate,
+              NotifyMessagePortAttached(created_data.token0,
+                                        created_data.seq0++, dummy_ec));
+  auto handle0 =
+      MessagePortDescriptorTestHelper::TakeHandleToEntangle(&port0, dummy_ec);
+  EXPECT_TRUE(port0.IsValid());
+  EXPECT_TRUE(port0.IsEntangled());
+  EXPECT_FALSE(port0.IsDefault());
+
+  // Simulate that the handle is detached by giving the pipe handle back.
+  EXPECT_CALL(delegate, NotifyMessagePortDetached(created_data.token0,
+                                                  created_data.seq0++));
+  MessagePortDescriptorTestHelper::GiveDisentangledHandle(&port0,
+                                                          std::move(handle0));
+  EXPECT_TRUE(port0.IsValid());
+  EXPECT_FALSE(port0.IsEntangled());
+  EXPECT_FALSE(port0.IsDefault());
+
+  // Tear down a handle explicitly.
+  EXPECT_CALL(delegate, NotifyMessagePortDestroyed(created_data.token1,
+                                                   created_data.seq1++));
+  port1.Reset();
+
+  // And leave the other handle to be torn down in the destructor.
+  EXPECT_CALL(delegate, NotifyMessagePortDestroyed(created_data.token0,
+                                                   created_data.seq0++));
+}
+
+TEST(MessagePortDescriptorTest, InvalidUsageDeathTest) {
+  static MessagePortDescriptor::InstrumentationDelegate* kDummyDelegate1 =
+      reinterpret_cast<MessagePortDescriptor::InstrumentationDelegate*>(
+          0xBAADF00D);
+  static MessagePortDescriptor::InstrumentationDelegate* kDummyDelegate2 =
+      reinterpret_cast<MessagePortDescriptor::InstrumentationDelegate*>(
+          0xDEADBEEF);
+  EXPECT_DCHECK_DEATH(
+      MessagePortDescriptor::SetInstrumentationDelegate(nullptr));
+  MessagePortDescriptor::SetInstrumentationDelegate(kDummyDelegate1);
+  // Setting the same or another delegate should explode.
+  EXPECT_DCHECK_DEATH(
+      MessagePortDescriptor::SetInstrumentationDelegate(kDummyDelegate1));
+  EXPECT_DCHECK_DEATH(
+      MessagePortDescriptor::SetInstrumentationDelegate(kDummyDelegate2));
+  // Unset the dummy delegate we installed so we don't receive notifications in
+  // the rest of the test.
+  MessagePortDescriptor::SetInstrumentationDelegate(nullptr);
+
+  // Trying to take properties of a default port descriptor should explode.
+  MessagePortDescriptor port0;
+  EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::TakeHandle(&port0));
+  EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::TakeId(&port0));
+  EXPECT_DCHECK_DEATH(
+      MessagePortDescriptorTestHelper::TakeSequenceNumber(&port0));
+
+  MessagePortDescriptorPair pair;
+  port0 = pair.TakePort0();
+  MessagePortDescriptor port1 = pair.TakePort1();
+
+  {
+    // Dismantle the port as if for serialization.
+    auto handle = MessagePortDescriptorTestHelper::TakeHandle(&port0);
+    auto id = MessagePortDescriptorTestHelper::TakeId(&port0);
+    auto sequence_number =
+        MessagePortDescriptorTestHelper::TakeSequenceNumber(&port0);
+
+    // Reserializing with inconsistent state should explode.
+
+    // First try with any 1 of the 3 fields being invalid.
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, mojo::ScopedMessagePipeHandle(), id, sequence_number));
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, std::move(handle), base::UnguessableToken::Null(),
+        sequence_number));
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, std::move(handle), id, 0));
+
+    // Next try with any 2 of the 3 fields being invalid.
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, std::move(handle), base::UnguessableToken::Null(), 0));
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, mojo::ScopedMessagePipeHandle(), id, 0));
+    EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::Init(
+        &port0, mojo::ScopedMessagePipeHandle(), base::UnguessableToken::Null(),
+        sequence_number));
+
+    // Restoring the port with default state should work (all 3 fields invalid).
+    MessagePortDescriptorTestHelper::Init(&port0,
+                                          mojo::ScopedMessagePipeHandle(),
+                                          base::UnguessableToken::Null(), 0);
+    EXPECT_TRUE(port0.IsDefault());
+
+    // Restoring the port with full state should work (all 3 fields valid).
+    MessagePortDescriptorTestHelper::Init(&port0, std::move(handle), id,
+                                          sequence_number);
+  }
+
+  // Entangle the port.
+  base::UnguessableToken dummy_ec = base::UnguessableToken::Create();
+  auto handle0 =
+      MessagePortDescriptorTestHelper::TakeHandleToEntangle(&port0, dummy_ec);
+
+  // Trying to entangle a second time should explode.
+  EXPECT_DCHECK_DEATH(
+      MessagePortDescriptorTestHelper::TakeHandleToEntangle(&port0, dummy_ec));
+
+  // Destroying a port descriptor that has been entangled should explode. The
+  // handle needs to be given back to the descriptor before its death, ensuring
+  // descriptors remain fully accounted for over their entire lifecycle.
+  EXPECT_DCHECK_DEATH(port0.Reset());
+
+  // Trying to assign while the handle is entangled should explode, as it
+  // amounts to destroying the existing descriptor.
+  EXPECT_DCHECK_DEATH(port0 = MessagePortDescriptor());
+
+  // Trying to disentangle with an empty port should explode.
+  mojo::ScopedMessagePipeHandle handle1;
+  EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::GiveDisentangledHandle(
+      &port0, std::move(handle1)));
+
+  // Trying to disentangle with the wrong port should explode.
+  handle1 =
+      MessagePortDescriptorTestHelper::TakeHandleToEntangle(&port1, dummy_ec);
+  EXPECT_DCHECK_DEATH(MessagePortDescriptorTestHelper::GiveDisentangledHandle(
+      &port0, std::move(handle1)));
+
+  // Disentangle the ports properly.
+  MessagePortDescriptorTestHelper::GiveDisentangledHandle(&port0,
+                                                          std::move(handle0));
+  MessagePortDescriptorTestHelper::GiveDisentangledHandle(&port1,
+                                                          std::move(handle1));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index d81ee950..72b7010 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -86,6 +86,8 @@
     "messaging/cloneable_message.h",
     "messaging/cloneable_message_mojom_traits.h",
     "messaging/message_port_channel.h",
+    "messaging/message_port_descriptor.h",
+    "messaging/message_port_descriptor_mojom_traits.h",
     "messaging/string_message_codec.h",
     "messaging/transferable_message.h",
     "messaging/transferable_message_mojom_traits.h",
diff --git a/third_party/blink/public/common/messaging/message_port_descriptor.h b/third_party/blink/public/common/messaging/message_port_descriptor.h
new file mode 100644
index 0000000..7c238ec
--- /dev/null
+++ b/third_party/blink/public/common/messaging/message_port_descriptor.h
@@ -0,0 +1,218 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_H_
+
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+
+// Defines a message port descriptor, which is a mojo::MessagePipeHandle and
+// some associated state which follows the handle around as it is passed from
+// one execution context to another. This can be serialized into a
+// mojom::MessagePortDescriptor using MessagePortDescriptorStructTraits. Since
+// this class uses only POD and Mojo types the same serialization logic is fine
+// for use both inside and outside of Blink. This type is move-only so that only
+// a single representation of an endpoint can exist at any moment in time.
+// This class is not thread-safe, but a MessagePortDescriptor is only ever owned
+// by a single thread at a time.
+//
+// A MessagePortDescriptor should never be created in isolation, but rather they
+// should only be created in pairs via MessagePortDescriptorPair.
+//
+// To enforce that a Mojo pipe isn't left dangling, MessagePortDescriptors
+// enforce that they are only destroyed while holding onto their pipe.
+//
+// This class is intended to be used as follows:
+//
+//   MessagePortDescriptorPair port_pair;
+//   MessagePortDescriptor port0 = port_pair.TakePort0();
+//   MessagePortDescriptor port1 = port_pair.TakePort1();
+//
+//   ... pass around the port descriptors in TransferableMessages as desired ...
+//
+//   // Pass this into a MessagePortChannel for reference-counted safe-keeping.
+//   MessagePortChannel channel0(port0);
+//
+//   // Entangle into a MessagePort for use in sending messages.
+//   MessagePort message_port;
+//   message_port.Entangle(channel0)
+//   message_port.postMessage(...);
+//   channel0 = message_port.Disentangle();
+class BLINK_COMMON_EXPORT MessagePortDescriptor {
+ public:
+  // Delegate used to provide information about the state of message ports.
+  // See full class declaration below.
+  class InstrumentationDelegate;
+
+  // Allows setting a singleton instrumentation delegate. This is not
+  // thread-safe and should be set in early Blink initialization.
+  static void SetInstrumentationDelegate(InstrumentationDelegate* delegate);
+
+  MessagePortDescriptor();
+
+  // Disallow copying, and enforce move-only semantics.
+  MessagePortDescriptor(const MessagePortDescriptor& message_port) = delete;
+  MessagePortDescriptor(MessagePortDescriptor&& message_port);
+  MessagePortDescriptor& operator=(const MessagePortDescriptor& message_port) =
+      delete;
+  MessagePortDescriptor& operator=(MessagePortDescriptor&& message_port);
+
+  ~MessagePortDescriptor();
+
+  // Simple accessors.
+  const mojo::ScopedMessagePipeHandle& handle() const { return handle_; }
+  const base::UnguessableToken& id() const { return id_; }
+  uint64_t sequence_number() const { return sequence_number_; }
+
+  // Returns true if this is a valid descriptor.
+  bool IsValid() const;
+
+  // Returns true if this descriptor is currently entangled (meaning that the
+  // handle has been vended out via "TakeHandleToEntangle").
+  bool IsEntangled() const;
+
+  // Returns true if this is a default initialized descriptor.
+  bool IsDefault() const;
+
+  void Reset();
+
+ protected:
+  friend class MessagePort;
+  friend class MessagePortSerializationAccess;
+  friend class MessagePortDescriptorTestHelper;
+
+  // These are only meant to be used for serialization, and as such the values
+  // should always be non-default initialized when they are called. Intended for
+  // use via MessagePortSerializationAccess. These should only be called for
+  // descriptors that actually host non-default values.
+  void Init(mojo::ScopedMessagePipeHandle handle,
+            base::UnguessableToken id,
+            uint64_t sequence_number);
+  mojo::ScopedMessagePipeHandle TakeHandle();
+  base::UnguessableToken TakeId();
+  uint64_t TakeSequenceNumber();
+
+  // Intended for use by MessagePort, for binding/unbinding the handle to/from a
+  // mojo::Connector. The handle must be bound directly to a mojo::Connector in
+  // order for messages to be sent or received. MessagePort::Entangle is passed
+  // a MessagePortDescriptor, and takes the handle from the descriptor in order
+  // to bind it to the mojo::Connector. Similarly, MessagePort::Disentangle
+  // takes the handle back from the mojo::Connector, gives it back to the
+  // MessagePortDescriptor, and releases the MessagePortDescriptor to the
+  // caller. See MessagePort::Entangle and MessagePort::Disentangle.
+  mojo::ScopedMessagePipeHandle TakeHandleToEntangle(
+      const base::UnguessableToken& execution_context_id);
+  void GiveDisentangledHandle(mojo::ScopedMessagePipeHandle handle);
+
+ private:
+  // For access to NotifyPeer and the following constructor.
+  friend class MessagePortDescriptorPair;
+
+  // Creates a new MessagePortDescriptor that wraps the provided brand new
+  // handle. A unique id and starting sequence number will be generated. Only
+  // meant to be called from MessagePortDescriptorPair.
+  explicit MessagePortDescriptor(mojo::ScopedMessagePipeHandle handle);
+
+  // Helper functions for forwarding notifications to the
+  // InstrumentationDelegate if it exists.
+  void NotifyAttached(const base::UnguessableToken& execution_context_id);
+  void NotifyDetached();
+  void NotifyDestroyed();
+
+  static constexpr size_t kInvalidSequenceNumber = 0;
+  static constexpr size_t kFirstValidSequenceNumber = 1;
+
+  // The handle to the underlying pipe.
+  mojo::ScopedMessagePipeHandle handle_;
+
+#if DCHECK_IS_ON()
+  // The underlying handle, unmanaged. This is used to enforce that the same
+  // handle is given back to this descriptor when it is unentangled. This value
+  // is not part of the corresponding Mojo type, as it need not be transferred.
+  // It is treated as an extension of |handle_| as far as "TakeHandle*"" is
+  // concerned.
+  mojo::MessagePipeHandle raw_handle_;
+#endif
+
+  // The randomly generated ID of this message handle. The ID follows this
+  // MessagePortDescriptor around as it is passed between execution contexts,
+  // and allows for bookkeeping across the various contexts. When an execution
+  // context entangles itself with a handle, it will report back to the browser
+  // the ID of the handle and the execution context as well. This allows for the
+  // browser to know who is talking to who.
+  base::UnguessableToken id_;
+
+  // The sequence number of the instrumentation message related to this handle.
+  // Since these messages can arrive out of order in the browser process, this
+  // is used to reorder them so that consistent state can be maintained. This
+  // will never be zero for a valid port descriptor.
+  uint64_t sequence_number_ = kInvalidSequenceNumber;
+};
+
+// Defines a wrapped mojo::MessagePipe, containing 2 MessagePortDescriptors that
+// are peers of each other.
+class BLINK_COMMON_EXPORT MessagePortDescriptorPair {
+ public:
+  MessagePortDescriptorPair();
+  ~MessagePortDescriptorPair();
+
+  const MessagePortDescriptor& port0() const { return port0_; }
+  const MessagePortDescriptor& port1() const { return port1_; }
+
+  MessagePortDescriptor TakePort0() { return std::move(port0_); }
+  MessagePortDescriptor TakePort1() { return std::move(port1_); }
+
+ private:
+  MessagePortDescriptor port0_;
+  MessagePortDescriptor port1_;
+};
+
+// A delegate used for instrumenting operations on message handle descriptors.
+// These messages allow the observing entity to follow the handle endpoints as
+// they travel from one execution context to another, and to know when they are
+// bound. If no instrumentation delegate is provided the instrumentation is
+// disabled. The implementation needs to be thread-safe.
+//
+// Note that the sequence numbers associated with each port will never be
+// reused, and increment by exactly one for each message received. This allows
+// the receiver to order incoming messages and know if a message is missing.
+// NotifyMessagePortsCreated is special in that it introduces new ports and
+// starts new sequence numbers. The next message received (either a PortAttached
+// or PortDestroyed message) will use the subsequent sequence number.
+//
+// TODO(chrisha): Kill this delegate entirely and move these functions into
+// dedicated interfaces, with the MessagePortDescriptor impl directly invoking
+// them.
+class BLINK_COMMON_EXPORT MessagePortDescriptor::InstrumentationDelegate {
+ public:
+  virtual ~InstrumentationDelegate() = default;
+
+  // Notifies the instrumentation that a pair of matching ports was created.
+  virtual void NotifyMessagePortPairCreated(
+      const MessagePortDescriptorPair& pair) = 0;
+
+  // Notifies the instrumentation that a handle has been attached to an
+  // execution context.
+  virtual void NotifyMessagePortAttached(
+      const base::UnguessableToken& port_id,
+      uint64_t sequence_number,
+      const base::UnguessableToken& execution_context_id) = 0;
+
+  // Notifies the instrumentation that a handle has been detached from an
+  // execution context.
+  virtual void NotifyMessagePortDetached(const base::UnguessableToken& port_id,
+                                         uint64_t sequence_number) = 0;
+
+  // Notifies the instrumentation that a handle has been destroyed.
+  virtual void NotifyMessagePortDestroyed(const base::UnguessableToken& port_id,
+                                          uint64_t sequence_number) = 0;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_H_
diff --git a/third_party/blink/public/common/messaging/message_port_descriptor.typemap b/third_party/blink/public/common/messaging/message_port_descriptor.typemap
new file mode 100644
index 0000000..50a81d7
--- /dev/null
+++ b/third_party/blink/public/common/messaging/message_port_descriptor.typemap
@@ -0,0 +1,12 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom =
+    "//third_party/blink/public/mojom/messaging/message_port_descriptor.mojom"
+public_headers =
+    [ "//third_party/blink/public/common/messaging/message_port_descriptor.h" ]
+traits_headers = [ "//third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h" ]
+type_mappings = [
+  "blink.mojom.MessagePortDescriptor=::blink::MessagePortDescriptor[move_only]",
+]
diff --git a/third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h b/third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h
new file mode 100644
index 0000000..bca51db
--- /dev/null
+++ b/third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_MOJOM_TRAITS_H_
+
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
+#include "third_party/blink/public/mojom/messaging/message_port_descriptor.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT
+    StructTraits<blink::mojom::MessagePortDescriptorDataView,
+                 blink::MessagePortDescriptor> {
+  // For converting a blink::mojom::MessagePortDescriptor to a
+  // blink::MessagePortDescriptor.
+  static bool Read(blink::mojom::MessagePortDescriptorDataView data,
+                   blink::MessagePortDescriptor* output);
+
+  // For converting a blink::MessagePortDescriptor to a
+  // blink::mojom::MessagePortDescriptor.
+  static mojo::ScopedMessagePipeHandle pipe_handle(
+      blink::MessagePortDescriptor& input);
+  static base::UnguessableToken id(blink::MessagePortDescriptor& input);
+  static uint64_t sequence_number(blink::MessagePortDescriptor& input);
+};
+
+}  // namespace mojo
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_MESSAGE_PORT_DESCRIPTOR_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index f1a525d..3b687520 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -263,6 +263,7 @@
 mojom("mojom_core") {
   sources = [
     "messaging/cloneable_message.mojom",
+    "messaging/message_port_descriptor.mojom",
     "messaging/transferable_message.mojom",
     "messaging/user_activation_snapshot.mojom",
     "portal/portal.mojom",
diff --git a/third_party/blink/public/mojom/messaging/message_port_descriptor.mojom b/third_party/blink/public/mojom/messaging/message_port_descriptor.mojom
new file mode 100644
index 0000000..ff3a0c5
--- /dev/null
+++ b/third_party/blink/public/mojom/messaging/message_port_descriptor.mojom
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+import "mojo/public/mojom/base/unguessable_token.mojom";
+
+// A MessagePortDescriptor represents one end of a message channel. It
+// encompasses a small bit of state used to uniquely identify a message handle
+// and to provide information about it to the browser. Otherwise, this is a
+// simple wrapper around a Mojo message_pipe. Messages being sent over this pipe
+// are serialized versions of a TransferableMessage struct.
+//
+// The corresponding public Blink type for this object is a move-only type,
+// ensuring that there can only ever be a single handle to a pipe endpoint (and
+// its associated state) at any moment in time.
+//
+// TODO(crbug.com/750468): Consider using an actual Mojo interface for message
+// ports.
+struct MessagePortDescriptor {
+  // The actual handle. Simply called |handle| on the C++ counterpart, but
+  // that's a reserved name in Mojo.
+  handle<message_pipe> pipe_handle;
+
+  // The name of the handle, so that it can be tracked as it is passed along
+  // from one execution context to another.
+  mojo_base.mojom.UnguessableToken id;
+
+  // The sequence number of the instrumentation messages related to this handle.
+  // Since these messages can arrive out of order in the browser process (the
+  // messages can be sent from multiple distinct renderer processes if the
+  // endpoint is passed around), this is used to reorder them so that consistent
+  // state can be maintained in the browser.
+  uint64 sequence_number;
+};
diff --git a/third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h b/third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h
index 72fc658..8f02af1 100644
--- a/third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h
+++ b/third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h
@@ -6,13 +6,16 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_SCHEDULER_TEST_WEB_MOCK_THREAD_SCHEDULER_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 
+namespace base {
+class TaskObserver;
+}
+
 namespace blink {
 namespace scheduler {
 
@@ -52,8 +55,8 @@
 #endif
   MOCK_METHOD0(OnNavigate, void());
   MOCK_METHOD0(IsHighPriorityWorkAnticipated, bool());
-  MOCK_METHOD1(AddTaskObserver, void(base::MessageLoop::TaskObserver*));
-  MOCK_METHOD1(RemoveTaskObserver, void(base::MessageLoop::TaskObserver*));
+  MOCK_METHOD1(AddTaskObserver, void(base::TaskObserver*));
+  MOCK_METHOD1(RemoveTaskObserver, void(base::TaskObserver*));
   MOCK_METHOD0(Shutdown, void());
   MOCK_METHOD0(VirtualTimePaused, void());
   MOCK_METHOD0(VirtualTimeResumed, void());
diff --git a/third_party/blink/public/public_typemaps.gni b/third_party/blink/public/public_typemaps.gni
index 396c5dc..6080830 100644
--- a/third_party/blink/public/public_typemaps.gni
+++ b/third_party/blink/public/public_typemaps.gni
@@ -12,6 +12,7 @@
   "//third_party/blink/public/common/manifest/manifest.typemap",
   "//third_party/blink/public/common/mediastream/media_devices.typemap",
   "//third_party/blink/public/common/mediastream/media_stream.typemap",
+  "//third_party/blink/public/common/messaging/message_port_descriptor.typemap",
   "//third_party/blink/public/common/notifications/notification_types.typemap",
   "//third_party/blink/public/common/screen_orientation/screen_orientation_lock_types.typemap",
   "//third_party/blink/public/common/user_agent/user_agent_metadata.typemap",
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 528efcd..2c8b6e7 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -782,6 +782,10 @@
                                                    const WebNode& end_node,
                                                    int end_offset) {}
 
+  // Provides accessibility information about the termination of a find
+  // in page operation.
+  virtual void HandleAccessibilityFindInPageTermination() {}
+
   // Fullscreen ----------------------------------------------------------
 
   // Called to enter/exit fullscreen mode.
diff --git a/third_party/blink/renderer/bindings/BUILD.gn b/third_party/blink/renderer/bindings/BUILD.gn
index b77255a..ead3cd0 100644
--- a/third_party/blink/renderer/bindings/BUILD.gn
+++ b/third_party/blink/renderer/bindings/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/python.gni")
 import("//third_party/blink/renderer/bindings/scripts/scripts.gni")
 import("//third_party/blink/renderer/build/scripts/scripts.gni")
 import("//third_party/blink/renderer/core/core_idl_files.gni")
@@ -48,21 +49,16 @@
 }
 
 template("collect_idl_files") {
-  action(target_name) {
+  action_with_pydeps(target_name) {
     script = "${bindings_scripts_dir}/collect_idl_files.py"
-    sources = invoker.sources
+
+    inputs = invoker.inputs
     outputs = [
       invoker.output,
     ]
-    deps = [
-      "${bindings_scripts_dir}:web_idl_pylib",
-    ]
-    if (defined(invoker.deps)) {
-      deps += invoker.deps
-    }
 
     # List input file names in a temporary file.
-    response_file_contents = rebase_path(sources, root_build_dir)
+    response_file_contents = rebase_path(inputs, root_build_dir)
     args = [
       "--idl-list-file",
       "{{response_file_name}}",
@@ -71,17 +67,25 @@
       "--output",
       rebase_path(invoker.output, root_build_dir),
     ]
+
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    }
   }
 }
 
 collect_idl_files("web_idl_in_core") {
   # all IDL files in 'core' component
-  sources = core_static_interface_idl_files +
-            core_generated_interface_idl_files + core_all_dependency_idl_files
+  inputs = core_static_interface_idl_files +
+           core_generated_interface_idl_files + core_all_dependency_idl_files
+
+  # We exclude |core_global_constructors_generated_idl_files| to avoid
+  # unnecessary dependencies.
+  inputs -= core_global_constructors_generated_idl_files
+
   component = "core"
   output = "${bindings_output_dir}/web_idl_in_core.pickle"
   deps = [
-    "core:core_global_constructors_idls",
     "//third_party/blink/renderer/core:generated_testing_idls_internal_runtime_flags",
     "//third_party/blink/renderer/core:generated_testing_idls_settings",
   ]
@@ -89,8 +93,8 @@
 
 collect_idl_files("web_idl_in_modules") {
   # all IDL files in 'modules' component
-  sources = modules_definition_idl_files + modules_static_interface_idl_files +
-            modules_static_dependency_idl_files
+  inputs = modules_definition_idl_files + modules_static_interface_idl_files +
+           modules_static_dependency_idl_files
   component = "modules"
   output = "${bindings_output_dir}/web_idl_in_modules.pickle"
 }
@@ -100,22 +104,30 @@
 
   input_data_files = get_target_outputs(":web_idl_in_core") +
                      get_target_outputs(":web_idl_in_modules")
-  inputs = input_data_files
 
+  # List pydeps's content to |pydeps|
+  pydeps_file = "${bindings_scripts_dir}/build_web_idl_database.pydeps"
+  pydeps_dir = get_path_info(pydeps_file, "dir")
+  pydeps_raw = read_file(pydeps_file, "list lines")
+  set_sources_assignment_filter([ "#*" ])
+  sources = pydeps_raw
+  pydeps = sources
+  sources = []
+
+  inputs = input_data_files + rebase_path(pydeps, ".", pydeps_dir)
   output_data_file = "${bindings_output_dir}/web_idl_database.pickle"
   outputs = [
     output_data_file,
   ]
 
-  deps = [
-    ":web_idl_in_core",
-    ":web_idl_in_modules",
-    "${bindings_scripts_dir}:web_idl_pylib",
-  ]
-
   args = [
            "--output",
            rebase_path(output_data_file, root_build_dir),
            "--",
          ] + rebase_path(input_data_files, root_build_dir)
+
+  deps = [
+    ":web_idl_in_core",
+    ":web_idl_in_modules",
+  ]
 }
diff --git a/third_party/blink/renderer/bindings/scripts/BUILD.gn b/third_party/blink/renderer/bindings/scripts/BUILD.gn
index 9dab258..8868829 100644
--- a/third_party/blink/renderer/bindings/scripts/BUILD.gn
+++ b/third_party/blink/renderer/bindings/scripts/BUILD.gn
@@ -46,51 +46,3 @@
     rebase_path(stamp_file, root_build_dir),
   ]
 }
-
-# Python library that supports Web IDL compiler and database
-group("web_idl_pylib") {
-  data = [
-    "web_idl/argument.py",
-    "web_idl/ast_group.py",
-    "web_idl/attribute.py",
-    "web_idl/callback_function.py",
-    "web_idl/callback_interface.py",
-    "web_idl/composition_parts.py",
-    "web_idl/constant.py",
-    "web_idl/constructor.py",
-    "web_idl/database.py",
-    "web_idl/dictionary.py",
-    "web_idl/enumeration.py",
-    "web_idl/exposure.py",
-    "web_idl/extended_attribute.py",
-    "web_idl/identifier_ir_map.py",
-    "web_idl/idl_compiler.py",
-    "web_idl/idl_member.py",
-    "web_idl/idl_type.py",
-    "web_idl/includes.py",
-    "web_idl/interface.py",
-    "web_idl/ir_builder.py",
-    "web_idl/namespace.py",
-    "web_idl/operation.py",
-    "web_idl/reference.py",
-    "web_idl/typedef.py",
-    "web_idl/user_defined_type.py",
-    "web_idl/values.py",
-  ]
-  data += [  # dependencies to Python libraries
-    "//third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py",
-
-    # PLY (Python Lex-Yacc)
-    "//third_party/ply/lex.py",
-    "//third_party/ply/yacc.py",
-
-    # Web IDL lexer/parser (base parser)
-    "//tools/idl_parser/idl_lexer.py",
-    "//tools/idl_parser/idl_node.py",
-    "//tools/idl_parser/idl_parser.py",
-
-    # Blink IDL lexer/parser/constructor
-    "blink_idl_lexer.py",
-    "blink_idl_parser.py",
-  ]
-}
diff --git a/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
new file mode 100644
index 0000000..058c70d
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
@@ -0,0 +1,34 @@
+# Generated by running:
+#   build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
+../../build/scripts/blinkbuild/__init__.py
+../../build/scripts/blinkbuild/name_style_converter.py
+build_web_idl_database.py
+utilities.py
+web_idl/__init__.py
+web_idl/argument.py
+web_idl/ast_group.py
+web_idl/attribute.py
+web_idl/callback_function.py
+web_idl/callback_interface.py
+web_idl/composition_parts.py
+web_idl/constant.py
+web_idl/database.py
+web_idl/database_builder.py
+web_idl/dictionary.py
+web_idl/enumeration.py
+web_idl/exposure.py
+web_idl/extended_attribute.py
+web_idl/identifier_ir_map.py
+web_idl/idl_compiler.py
+web_idl/idl_member.py
+web_idl/idl_type.py
+web_idl/includes.py
+web_idl/interface.py
+web_idl/ir_builder.py
+web_idl/namespace.py
+web_idl/operation.py
+web_idl/reference.py
+web_idl/typedef.py
+web_idl/union.py
+web_idl/user_defined_type.py
+web_idl/values.py
diff --git a/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
new file mode 100644
index 0000000..0fe734d
--- /dev/null
+++ b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
@@ -0,0 +1,43 @@
+# Generated by running:
+#   build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps third_party/blink/renderer/bindings/scripts/collect_idl_files.py
+../../../../../tools/idl_parser/__init__.py
+../../../../../tools/idl_parser/idl_lexer.py
+../../../../../tools/idl_parser/idl_node.py
+../../../../../tools/idl_parser/idl_parser.py
+../../../../ply/__init__.py
+../../../../ply/lex.py
+../../../../ply/yacc.py
+../../build/scripts/blinkbuild/__init__.py
+../../build/scripts/blinkbuild/name_style_converter.py
+blink_idl_lexer.py
+blink_idl_parser.py
+collect_idl_files.py
+utilities.py
+web_idl/__init__.py
+web_idl/argument.py
+web_idl/ast_group.py
+web_idl/attribute.py
+web_idl/callback_function.py
+web_idl/callback_interface.py
+web_idl/composition_parts.py
+web_idl/constant.py
+web_idl/database.py
+web_idl/database_builder.py
+web_idl/dictionary.py
+web_idl/enumeration.py
+web_idl/exposure.py
+web_idl/extended_attribute.py
+web_idl/identifier_ir_map.py
+web_idl/idl_compiler.py
+web_idl/idl_member.py
+web_idl/idl_type.py
+web_idl/includes.py
+web_idl/interface.py
+web_idl/ir_builder.py
+web_idl/namespace.py
+web_idl/operation.py
+web_idl/reference.py
+web_idl/typedef.py
+web_idl/union.py
+web_idl/user_defined_type.py
+web_idl/values.py
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 1e33576..2ec75f7 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1431,6 +1431,7 @@
     "loader/threaded_icon_loader_test.cc",
     "loader/web_associated_url_loader_impl_test.cc",
     "messaging/blink_transferable_message_mojom_traits_test.cc",
+    "messaging/message_port_descriptor_mojom_traits_test.cc",
     "origin_trials/origin_trial_context_test.cc",
     "page/autoscroll_controller_test.cc",
     "page/chrome_client_impl_test.cc",
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 583152f..fea9526 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -38,7 +38,6 @@
 #include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
 #include "third_party/blink/renderer/core/animation/transition_interpolation.h"
-#include "third_party/blink/renderer/core/css/css_color_value.h"
 #include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
 #include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
 #include "third_party/blink/renderer/core/css/css_font_selector.h"
@@ -54,7 +53,6 @@
 #include "third_party/blink/renderer/core/css/css_selector_watch.h"
 #include "third_party/blink/renderer/core/css/css_style_declaration.h"
 #include "third_party/blink/renderer/core/css/css_style_rule.h"
-#include "third_party/blink/renderer/core/css/css_unset_value.h"
 #include "third_party/blink/renderer/core/css/css_value_list.h"
 #include "third_party/blink/renderer/core/css/element_rule_collector.h"
 #include "third_party/blink/renderer/core/css/font_face.h"
@@ -541,7 +539,8 @@
 
   // If the system is in forced colors mode, match rules from the forced colors
   // style sheet.
-  if (IsForcedColorsModeEnabled())
+  if (blink::RuntimeEnabledFeatures::ForcedColorsEnabled() &&
+      GetDocument().GetSettings()->GetForcedColors() != ForcedColors::kNone)
     MatchRuleSet(collector, default_style_sheets.DefaultForcedColorStyle());
 
   collector.FinishAddingUARules();
@@ -1558,8 +1557,7 @@
                                     bool inherited_only,
                                     NeedsApplyPass& needs_apply_pass,
                                     ValidPropertyFilter valid_property_filter,
-                                    unsigned apply_mask,
-                                    ForcedColorFilter forced_colors) {
+                                    unsigned apply_mask) {
   unsigned property_count = properties->PropertyCount();
   for (unsigned i = 0; i < property_count; ++i) {
     CSSPropertyValueSet::PropertyReference current = properties->PropertyAt(i);
@@ -1588,9 +1586,6 @@
                               GetDocument()))
       continue;
 
-    if (!CSSPropertyPriorityData<priority>::PropertyHasPriority(property_id))
-      continue;
-
     if (inherited_only && !current.IsInherited()) {
       // If the property value is explicitly inherited, we need to apply further
       // non-inherited properties as they might override the value inherited
@@ -1603,11 +1598,8 @@
       continue;
     }
 
-    if (IsForcedColorsModeEnabled() &&
-        forced_colors == ForcedColorFilter::kEnabled &&
-        !current.Property().IsAffectedByForcedColors()) {
+    if (!CSSPropertyPriorityData<priority>::PropertyHasPriority(property_id))
       continue;
-    }
 
     ApplyProperty<priority>(current, state, apply_mask);
   }
@@ -1633,8 +1625,7 @@
                                            const MatchedPropertiesRange& range,
                                            bool is_important,
                                            bool inherited_only,
-                                           NeedsApplyPass& needs_apply_pass,
-                                           ForcedColorFilter forced_colors) {
+                                           NeedsApplyPass& needs_apply_pass) {
   if (range.IsEmpty())
     return;
 
@@ -1649,7 +1640,7 @@
         inherited_only, needs_apply_pass,
         static_cast<ValidPropertyFilter>(
             matched_properties.types_.valid_property_filter),
-        apply_mask, forced_colors);
+        apply_mask);
   }
 }
 
@@ -1674,48 +1665,6 @@
   was_viewport_resized_ = false;
 }
 
-template <CSSPropertyPriority priority>
-void StyleResolver::ApplyForcedColors(StyleResolverState& state,
-                                      const MatchResult& match_result,
-                                      bool apply_inherited_only,
-                                      NeedsApplyPass& needs_apply_pass) {
-  if (!IsForcedColorsModeEnabled())
-    return;
-  if (state.Style()->ForcedColorAdjust() == EForcedColorAdjust::kNone)
-    return;
-
-  const CSSValue* unset = cssvalue::CSSUnsetValue::Create();
-  unsigned apply_mask = kApplyMaskRegular | kApplyMaskVisited;
-
-  // This simulates 'revert !important' in the user origin.
-  // https://drafts.csswg.org/css-color-adjust-1/#forced-colors-properties
-  if (priority == kHighPropertyPriority) {
-    ApplyProperty(GetCSSPropertyColor(), state, *unset, apply_mask);
-  } else {
-    DCHECK(priority == kLowPropertyPriority);
-    ApplyProperty(GetCSSPropertyBackgroundColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyBorderBottomColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyBorderLeftColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyBorderRightColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyBorderTopColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyBoxShadow(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyOutlineColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyTextShadow(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyColumnRuleColor(), state, *unset, apply_mask);
-    ApplyProperty(GetCSSPropertyWebkitTapHighlightColor(), state, *unset,
-                  apply_mask);
-    ApplyProperty(GetCSSPropertyOutlineColor(), state, *unset, apply_mask);
-  }
-
-  auto force_colors = ForcedColorFilter::kEnabled;
-  ApplyMatchedProperties<priority, kCheckNeedsApplyPass>(
-      state, match_result.UaRules(), false, apply_inherited_only,
-      needs_apply_pass, force_colors);
-  ApplyMatchedProperties<priority, kCheckNeedsApplyPass>(
-      state, match_result.UaRules(), true, apply_inherited_only,
-      needs_apply_pass, force_colors);
-}
-
 StyleResolver::CacheSuccess StyleResolver::ApplyMatchedCache(
     StyleResolverState& state,
     const MatchResult& match_result) {
@@ -1866,12 +1815,6 @@
       state, match_result.UaRules(), true, apply_inherited_only,
       needs_apply_pass);
 
-  if (IsForcedColorsModeEnabled() &&
-      state.Style()->ForcedColorAdjust() != EForcedColorAdjust::kNone) {
-    ApplyForcedColors<kHighPropertyPriority>(
-        state, match_result, apply_inherited_only, needs_apply_pass);
-  }
-
   if (cache_success.cached_matched_properties &&
       cache_success.cached_matched_properties->computed_style
               ->EffectiveZoom() != state.Style()->EffectiveZoom()) {
@@ -1925,12 +1868,6 @@
       state, match_result.UaRules(), true, apply_inherited_only,
       needs_apply_pass);
 
-  if (IsForcedColorsModeEnabled() &&
-      state.Style()->ForcedColorAdjust() != EForcedColorAdjust::kNone) {
-    ApplyForcedColors<kLowPropertyPriority>(
-        state, match_result, apply_inherited_only, needs_apply_pass);
-  }
-
   if (state.Style()->HasAppearance() && !apply_inherited_only) {
     // Check whether the final border and background differs from the cached UA
     // ones.  When there is a partial match in the MatchedPropertiesCache, these
@@ -2286,9 +2223,4 @@
   visitor->Trace(tracker_);
 }
 
-bool StyleResolver::IsForcedColorsModeEnabled() const {
-  return RuntimeEnabledFeatures::ForcedColorsEnabled() &&
-         GetDocument().GetSettings()->GetForcedColors() != ForcedColors::kNone;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h
index 8809350e..31ff3a5 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -215,8 +215,6 @@
     bool flags_[kPropertyPriorityCount * 2] = {0};
   };
 
-  enum class ForcedColorFilter { kEnabled, kDisabled };
-
   enum ShouldUpdateNeedsApplyPass {
     kCheckNeedsApplyPass = false,
     kUpdateNeedsApplyPass = true,
@@ -242,11 +240,6 @@
                                          bool& apply_inherited_only,
                                          NeedsApplyPass&);
   void ApplyMatchedProperties(StyleResolverState&, const MatchResult&);
-  template <CSSPropertyPriority priority>
-  void ApplyForcedColors(StyleResolverState& state,
-                         const MatchResult& match_result,
-                         bool apply_inherited_only,
-                         NeedsApplyPass& needs_apply_pass);
 
   void CascadeAndApplyMatchedProperties(StyleResolverState&,
                                         const MatchResult&);
@@ -270,23 +263,19 @@
   void ApplyCallbackSelectors(StyleResolverState&);
 
   template <CSSPropertyPriority priority, ShouldUpdateNeedsApplyPass>
-  void ApplyMatchedProperties(
-      StyleResolverState&,
-      const MatchedPropertiesRange&,
-      bool important,
-      bool inherited_only,
-      NeedsApplyPass&,
-      ForcedColorFilter forced_colors = ForcedColorFilter::kDisabled);
+  void ApplyMatchedProperties(StyleResolverState&,
+                              const MatchedPropertiesRange&,
+                              bool important,
+                              bool inherited_only,
+                              NeedsApplyPass&);
   template <CSSPropertyPriority priority, ShouldUpdateNeedsApplyPass>
-  void ApplyProperties(
-      StyleResolverState&,
-      const CSSPropertyValueSet* properties,
-      bool is_important,
-      bool inherited_only,
-      NeedsApplyPass&,
-      ValidPropertyFilter,
-      unsigned apply_mask,
-      ForcedColorFilter forced_colors = ForcedColorFilter::kDisabled);
+  void ApplyProperties(StyleResolverState&,
+                       const CSSPropertyValueSet* properties,
+                       bool is_important,
+                       bool inherited_only,
+                       NeedsApplyPass&,
+                       ValidPropertyFilter,
+                       unsigned apply_mask);
   template <CSSPropertyPriority priority>
   void ApplyAnimatedStandardProperties(StyleResolverState&,
                                        const ActiveInterpolationsMap&);
@@ -305,8 +294,6 @@
   Document& GetDocument() const { return *document_; }
   bool WasViewportResized() const { return was_viewport_resized_; }
 
-  bool IsForcedColorsModeEnabled() const;
-
   MatchedPropertiesCache matched_properties_cache_;
   Member<Document> document_;
   SelectorFilter selector_filter_;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index f9fad92..e8f2022c 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1564,9 +1564,6 @@
   ScopedForcedColorsForTest scoped_feature(true);
   GetDocument().body()->SetInnerHTMLFromString(R"HTML(
     <style>
-      body {
-        forced-color-adjust: none;
-      }
       @media (forced-colors: none) {
         body { color: red }
       }
@@ -1593,9 +1590,6 @@
   ScopedForcedColorsForTest scoped_feature(true);
   GetDocument().body()->SetInnerHTMLFromString(R"HTML(
     <style>
-      body {
-        forced-color-adjust: none;
-      }
       @media (forced-colors: none) and (prefers-color-scheme: light) {
         body { color: red }
       }
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index acc3828..d41cee01 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -1110,7 +1110,7 @@
 
 bool IsHTMLListElement(const Node* n) {
   return (n && (IsHTMLUListElement(*n) || IsHTMLOListElement(*n) ||
-                IsHTMLDListElement(*n)));
+                IsA<HTMLDListElement>(*n)));
 }
 
 bool IsListItem(const Node* n) {
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc
index b91291a..4882a6c 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder.cc
+++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -321,6 +321,14 @@
 
   // Let the frame know that we don't want tickmarks anymore.
   InvalidatePaintForTickmarks();
+
+  ReportFindInPageTerminationToAccessibility();
+}
+
+void TextFinder::ReportFindInPageTerminationToAccessibility() {
+  if (OwnerFrame().Client()) {
+    OwnerFrame().Client()->HandleAccessibilityFindInPageTermination();
+  }
 }
 
 void TextFinder::ReportFindInPageResultToAccessibility(int identifier) {
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.h b/third_party/blink/renderer/core/editing/finder/text_finder.h
index ae2e8d6..63b260b 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder.h
+++ b/third_party/blink/renderer/core/editing/finder/text_finder.h
@@ -149,6 +149,7 @@
                                  int identifier);
 
   void ReportFindInPageResultToAccessibility(int identifier);
+  void ReportFindInPageTerminationToAccessibility();
 
   // Clear the find-in-page matches cache forcing rects to be fully
   // calculated again next time updateFindMatchRects is called.
diff --git a/third_party/blink/renderer/core/execution_context/agent.cc b/third_party/blink/renderer/core/execution_context/agent.cc
index f7893f5..7f72d76 100644
--- a/third_party/blink/renderer/core/execution_context/agent.cc
+++ b/third_party/blink/renderer/core/execution_context/agent.cc
@@ -9,8 +9,11 @@
 
 namespace blink {
 
-Agent::Agent(v8::Isolate* isolate, const base::UnguessableToken& cluster_id)
-    : event_loop_(base::AdoptRef(new scheduler::EventLoop(isolate))),
+Agent::Agent(v8::Isolate* isolate,
+             const base::UnguessableToken& cluster_id,
+             std::unique_ptr<v8::MicrotaskQueue> microtask_queue)
+    : event_loop_(base::AdoptRef(
+          new scheduler::EventLoop(isolate, std::move(microtask_queue)))),
       cluster_id_(cluster_id) {}
 
 Agent::~Agent() = default;
diff --git a/third_party/blink/renderer/core/execution_context/agent.h b/third_party/blink/renderer/core/execution_context/agent.h
index fa870ff..17682f5 100644
--- a/third_party/blink/renderer/core/execution_context/agent.h
+++ b/third_party/blink/renderer/core/execution_context/agent.h
@@ -34,14 +34,18 @@
  public:
   static Agent* CreateForWorkerOrWorklet(
       v8::Isolate* isolate,
-      const base::UnguessableToken& cluster_id) {
-    return MakeGarbageCollected<Agent>(isolate, cluster_id);
+      const base::UnguessableToken& cluster_id,
+      std::unique_ptr<v8::MicrotaskQueue> microtask_queue = nullptr) {
+    return MakeGarbageCollected<Agent>(isolate, cluster_id,
+                                       std::move(microtask_queue));
   }
 
   // Do not create the instance directly.
   // Use Agent::CreateForWorkerOrWorklet() or
   // WindowAgentFactory::GetAgentForOrigin().
-  Agent(v8::Isolate* isolate, const base::UnguessableToken& cluster_id);
+  Agent(v8::Isolate* isolate,
+        const base::UnguessableToken& cluster_id,
+        std::unique_ptr<v8::MicrotaskQueue> microtask_queue = nullptr);
   virtual ~Agent();
 
   const scoped_refptr<scheduler::EventLoop>& event_loop() const {
diff --git a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
index 4614c91a..8b96ced8 100644
--- a/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
@@ -33,10 +33,15 @@
   // Enable a separate microtask queue for LayoutWorklet.
   // TODO(yutak): Set agent for all worklets and workers,
   // not just LayoutWorklet.
+  auto* isolate = ToIsolate(frame);
+  auto microtask_queue =
+      v8::MicrotaskQueue::New(isolate, v8::MicrotasksPolicy::kScoped);
   auto* agent = Agent::CreateForWorkerOrWorklet(
-      ToIsolate(frame), creation_params->agent_cluster_id.is_empty()
-                            ? base::UnguessableToken::Create()
-                            : creation_params->agent_cluster_id);
+      isolate,
+      creation_params->agent_cluster_id.is_empty()
+          ? base::UnguessableToken::Create()
+          : creation_params->agent_cluster_id,
+      std::move(microtask_queue));
   auto* global_scope = MakeGarbageCollected<LayoutWorkletGlobalScope>(
       frame, std::move(creation_params), reporting_proxy,
       pending_layout_registry, agent);
diff --git a/third_party/blink/renderer/core/messaging/DEPS b/third_party/blink/renderer/core/messaging/DEPS
new file mode 100644
index 0000000..c28265b
--- /dev/null
+++ b/third_party/blink/renderer/core/messaging/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+  ".*_test.cc": [
+    "+mojo/public/cpp/test_support",
+  ],
+}
diff --git a/third_party/blink/renderer/core/messaging/message_port_descriptor_mojom_traits_test.cc b/third_party/blink/renderer/core/messaging/message_port_descriptor_mojom_traits_test.cc
new file mode 100644
index 0000000..1b31b6f4
--- /dev/null
+++ b/third_party/blink/renderer/core/messaging/message_port_descriptor_mojom_traits_test.cc
@@ -0,0 +1,41 @@
+// 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/public/common/messaging/message_port_descriptor.h"
+
+#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h"
+#include "third_party/blink/public/mojom/messaging/message_port_descriptor.mojom-blink.h"
+
+namespace blink {
+
+// This test lives in renderer/core because the serialization depends on other
+// things in renderer/core. The main functionality of MessagePortDescriptor is
+// tested in blink_common_unittests. For details, see
+// blink/common/messaging/message_port_descriptor_unittest.cc
+TEST(MessagePortDescriptorTest, SerializationWorks) {
+  MessagePortDescriptorPair pair;
+  MessagePortDescriptor port0 = pair.TakePort0();
+  EXPECT_TRUE(port0.IsValid());
+
+  base::UnguessableToken id = port0.id();
+  uint64_t sequence_number = port0.sequence_number();
+
+  // Do a round-trip through serialization and deserialization. This exercises
+  // the custom StructTraits.
+  MessagePortDescriptor port;
+  mojo::test::SerializeAndDeserialize<mojom::blink::MessagePortDescriptor,
+                                      MessagePortDescriptor>(&port0, &port);
+  EXPECT_TRUE(port0.IsDefault());
+  EXPECT_TRUE(port.IsValid());
+
+  // Handles themselves can change IDs as they go through serialization, so we
+  // don't explicitly test |raw_handle_|.
+  EXPECT_EQ(id, port.id());
+  EXPECT_EQ(sequence_number, port.sequence_number());
+}
+
+}  // namespace blink
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 d256866..5658e0c9 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -366,7 +366,7 @@
 
 static bool IsListElement(Node* node) {
   return IsHTMLUListElement(*node) || IsHTMLOListElement(*node) ||
-         IsHTMLDListElement(*node);
+         IsA<HTMLDListElement>(*node);
 }
 
 static bool IsRequiredOwnedElement(AXObject* parent,
@@ -596,7 +596,7 @@
   if (IsHTMLRubyElement(*GetNode()))
     return ax::mojom::Role::kRuby;
 
-  if (IsHTMLDListElement(*GetNode()))
+  if (IsA<HTMLDListElement>(*GetNode()))
     return ax::mojom::Role::kDescriptionList;
 
   if (IsA<HTMLAudioElement>(*GetNode()))
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index 404d0b5..275a1b3 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -361,7 +361,7 @@
   if (NodeHasRole(node, "list") || NodeHasRole(node, "directory") ||
       (NodeHasRole(node, g_null_atom) &&
        (IsHTMLUListElement(node) || IsHTMLOListElement(node) ||
-        IsHTMLDListElement(node))))
+        IsA<HTMLDListElement>(node))))
     return MakeGarbageCollected<AXList>(layout_object, *this);
 
   // media element
diff --git a/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc b/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc
index 08a9c874..ca867911 100644
--- a/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc
+++ b/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/optional.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_constants.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -102,9 +103,9 @@
     const WebURL& url,
     const WebString& cookie_line,
     base::Time creation_time) {
-  net::CookieOptions options;
   std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
-      ToGURL(url), cookie_line.Utf8(), creation_time, options);
+      ToGURL(url), cookie_line.Utf8(), creation_time,
+      base::nullopt /* server_time */);
   if (!cookie)
     return base::nullopt;
   return WebCanonicalCookie(
diff --git a/third_party/blink/renderer/platform/fonts/font_cache_key.h b/third_party/blink/renderer/platform/fonts/font_cache_key.h
index 0efc8fb9..90063cb 100644
--- a/third_party/blink/renderer/platform/fonts/font_cache_key.h
+++ b/third_party/blink/renderer/platform/fonts/font_cache_key.h
@@ -133,6 +133,10 @@
 
 struct FontCacheKeyTraits : WTF::SimpleClassHashTraits<FontCacheKey> {
   STATIC_ONLY(FontCacheKeyTraits);
+
+  // std::string's empty state need not be zero in all implementations,
+  // and it is held within FontFaceCreationParams.
+  static const bool kEmptyValueIsZero = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index a84f9e7..0c0fb6cb 100644
--- a/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -6,8 +6,6 @@
   "//media/capture/mojom/video_capture_types_for_blink.typemap",
   "//media/mojo/mojom/audio_parameters.typemap",
   "//mojo/public/cpp/base/values.typemap",
-  "//ui/gfx/mojom/color_space_for_blink.typemap",
-  "//ui/gfx/mojom/transform.typemap",
   "//services/network/public/cpp/http_request_headers.typemap",
   "//third_party/blink/renderer/core/messaging/blink_cloneable_message.typemap",
   "//third_party/blink/renderer/core/messaging/blink_transferable_message.typemap",
@@ -27,4 +25,6 @@
   "//third_party/blink/public/common/mediastream/media_stream.typemap",
   "//third_party/blink/public/common/screen_orientation/screen_orientation_lock_types.typemap",
   "//third_party/blink/public/mojom/bluetooth/bluetooth.typemap",
+  "//ui/gfx/mojom/color_space_for_blink.typemap",
+  "//ui/gfx/mojom/transform.typemap",
 ]
diff --git a/third_party/blink/renderer/platform/scheduler/common/DEPS b/third_party/blink/renderer/platform/scheduler/common/DEPS
index 3a4f0ed..57cac95 100644
--- a/third_party/blink/renderer/platform/scheduler/common/DEPS
+++ b/third_party/blink/renderer/platform/scheduler/common/DEPS
@@ -1,7 +1,13 @@
 specific_include_rules = {
+ "idle_helper.h": [
+  "+base/task/task_observer.h",
+ ],
  "scheduler_helper.cc": [
   "+base/task/sequence_manager/sequence_manager_impl.h",
  ],
+ "scheduler_helper_unittest.cc": [
+  "+base/task/task_observer.h",
+ ],
  "web_thread_scheduler.cc": [
   "+base/message_loop/message_pump_type.h",
  ],
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 2f1c9879..7242f7f7 100644
--- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -191,8 +191,8 @@
   base::TimeTicks MonotonicallyIncreasingVirtualTime() override {
     return base::TimeTicks::Now();
   }
-  void AddTaskObserver(base::MessageLoop::TaskObserver*) override {}
-  void RemoveTaskObserver(base::MessageLoop::TaskObserver*) override {}
+  void AddTaskObserver(base::TaskObserver*) override {}
+  void RemoveTaskObserver(base::TaskObserver*) override {}
   NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
     return nullptr;
   }
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 ddf2750..a9eaba8 100644
--- a/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
@@ -13,17 +13,16 @@
 namespace blink {
 namespace scheduler {
 
-EventLoop::EventLoop(v8::Isolate* isolate)
+EventLoop::EventLoop(v8::Isolate* isolate,
+                     std::unique_ptr<v8::MicrotaskQueue> microtask_queue)
     : isolate_(isolate),
       // TODO(keishi): Create MicrotaskQueue to enable per-EventLoop microtask
       // queue.
-      microtask_queue_(nullptr) {
+      microtask_queue_(std::move(microtask_queue)) {
   DCHECK(isolate_);
 }
 
-EventLoop::~EventLoop() {
-  microtask_queue_ = nullptr;
-}
+EventLoop::~EventLoop() = default;
 
 void EventLoop::EnqueueMicrotask(base::OnceClosure task) {
   pending_microtasks_.push_back(std::move(task));
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
index 9d48e10..49c8611 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/task/task_observer.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
@@ -41,7 +41,7 @@
 //
 // Idle tasks are supplied a deadline, and should endeavor to finished before it
 // ends to avoid jank.
-class PLATFORM_EXPORT IdleHelper : public base::MessageLoop::TaskObserver,
+class PLATFORM_EXPORT IdleHelper : public base::TaskObserver,
                                    public SingleThreadIdleTaskRunner::Delegate {
  public:
   // Used to by scheduler implementations to customize idle behaviour.
@@ -145,7 +145,7 @@
   void DidProcessIdleTask() override;
   base::TimeTicks NowTicks() override;
 
-  // base::MessageLoop::TaskObserver implementation:
+  // base::TaskObserver implementation:
   void WillProcessTask(const base::PendingTask& pending_task) override;
   void DidProcessTask(const base::PendingTask& pending_task) override;
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
index 3a29b803..78dbcab 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -72,8 +72,7 @@
   return sequence_manager_->GetAndClearSystemIsQuiescentBit();
 }
 
-void SchedulerHelper::AddTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+void SchedulerHelper::AddTaskObserver(base::TaskObserver* task_observer) {
   CheckOnValidThread();
   if (sequence_manager_) {
     static_cast<base::sequence_manager::internal::SequenceManagerImpl*>(
@@ -82,8 +81,7 @@
   }
 }
 
-void SchedulerHelper::RemoveTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+void SchedulerHelper::RemoveTaskObserver(base::TaskObserver* task_observer) {
   CheckOnValidThread();
   if (sequence_manager_) {
     static_cast<base::sequence_manager::internal::SequenceManagerImpl*>(
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
index 6f4d8c3d..c28535f 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -9,13 +9,16 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/task/sequence_manager/sequence_manager.h"
 #include "base/time/tick_clock.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/scheduler/common/ukm_task_sampler.h"
 
+namespace base {
+class TaskObserver;
+}
+
 namespace blink {
 namespace scheduler {
 
@@ -54,8 +57,8 @@
   // Adds or removes a task observer from the scheduler. The observer will be
   // notified before and after every executed task. These functions can only be
   // called on the thread this class was created on.
-  void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer);
-  void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer);
+  void AddTaskObserver(base::TaskObserver* task_observer);
+  void RemoveTaskObserver(base::TaskObserver* task_observer);
 
   void AddTaskTimeObserver(
       base::sequence_manager::TaskTimeObserver* task_time_observer);
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
index c01f067..bee56594 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
@@ -7,11 +7,11 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task/sequence_manager/lazy_now.h"
 #include "base/task/sequence_manager/task_queue.h"
 #include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/task_observer.h"
 #include "base/test/scoped_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -139,7 +139,7 @@
 }
 
 namespace {
-class MockTaskObserver : public base::MessageLoop::TaskObserver {
+class MockTaskObserver : public base::TaskObserver {
  public:
   MOCK_METHOD1(DidProcessTask, void(const base::PendingTask& task));
   MOCK_METHOD1(WillProcessTask, void(const base::PendingTask& task));
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
index bebfede..920153dc 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
@@ -75,11 +75,11 @@
   return base::TimeTicks::Now();
 }
 
-void SimpleThreadScheduler::AddTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {}
+void SimpleThreadScheduler::AddTaskObserver(base::TaskObserver* task_observer) {
+}
 
 void SimpleThreadScheduler::RemoveTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {}
+    base::TaskObserver* task_observer) {}
 
 NonMainThreadSchedulerImpl* SimpleThreadScheduler::AsNonMainThreadScheduler() {
   return nullptr;
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
index ea5e8ad..35c83b2 100644
--- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -70,8 +70,8 @@
 
   // Unsupported. The observer won't get called. May break some functionalities
   // that rely on the task observer.
-  void AddTaskObserver(base::MessageLoop::TaskObserver*) override;
-  void RemoveTaskObserver(base::MessageLoop::TaskObserver*) override;
+  void AddTaskObserver(base::TaskObserver*) override;
+  void RemoveTaskObserver(base::TaskObserver*) override;
 
   // Return nullptr.
   NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/DEPS b/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
index 974a9f93..2838e10 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
@@ -6,6 +6,12 @@
 ]
 
 specific_include_rules = {
+  "auto_advancing_virtual_time_domain.h": [
+    "+base/task/task_observer.h",
+  ],
+  "idle_time_estimator.h": [
+    "+base/task/task_observer.h",
+  ],
   "main_thread_task_queue.h": [
     "+base/task/sequence_manager/task_queue_impl.h",
     "+net/base/request_priority.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
index c5b2af5..5e03128 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
@@ -6,8 +6,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_AUTO_ADVANCING_VIRTUAL_TIME_DOMAIN_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/task/sequence_manager/time_domain.h"
+#include "base/task/task_observer.h"
 #include "base/time/time_override.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
@@ -26,7 +26,7 @@
 // |-----------------------------> time
 class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
     : public base::sequence_manager::TimeDomain,
-      public base::MessageLoop::TaskObserver {
+      public base::TaskObserver {
  public:
   enum class BaseTimeOverridePolicy { OVERRIDE, DO_NOT_OVERRIDE };
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
index 1f72d60..1d726c3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
@@ -6,8 +6,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_IDLE_TIME_ESTIMATOR_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/task/sequence_manager/task_queue.h"
+#include "base/task/task_observer.h"
 #include "base/time/tick_clock.h"
 #include "cc/base/rolling_time_delta_history.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
@@ -16,8 +16,7 @@
 namespace scheduler {
 
 // Estimates how much idle time there is available.  Ignores nested tasks.
-class PLATFORM_EXPORT IdleTimeEstimator
-    : public base::MessageLoop::TaskObserver {
+class PLATFORM_EXPORT IdleTimeEstimator : public base::TaskObserver {
  public:
   IdleTimeEstimator(const scoped_refptr<base::sequence_manager::TaskQueue>&
                         compositor_task_runner,
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 22e50c07..df6b08ab 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -789,12 +789,12 @@
 }
 
 void MainThreadSchedulerImpl::AddTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+    base::TaskObserver* task_observer) {
   helper_.AddTaskObserver(task_observer);
 }
 
 void MainThreadSchedulerImpl::RemoveTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+    base::TaskObserver* task_observer) {
   helper_.RemoveTaskObserver(task_observer);
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index 6e0e0463..5375d28 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -14,7 +14,6 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/single_sample_metrics.h"
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
@@ -52,6 +51,9 @@
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace base {
+
+class TaskObserver;
+
 namespace trace_event {
 class ConvertableToTraceFormat;
 }
@@ -196,9 +198,8 @@
   bool IsHighPriorityWorkAnticipated() override;
   bool ShouldYieldForHighPriorityWork() override;
   bool CanExceedIdleDeadlineIfRequired() const override;
-  void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
-  void RemoveTaskObserver(
-      base::MessageLoop::TaskObserver* task_observer) override;
+  void AddTaskObserver(base::TaskObserver* task_observer) override;
+  void RemoveTaskObserver(base::TaskObserver* task_observer) override;
   void Shutdown() override;
   void SetTopLevelBlameContext(
       base::trace_event::BlameContext* blame_context) 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 8d4decb..00190e8 100644
--- a/third_party/blink/renderer/platform/scheduler/public/event_loop.h
+++ b/third_party/blink/renderer/platform/scheduler/public/event_loop.h
@@ -80,7 +80,8 @@
   friend class WTF::RefCounted<EventLoop>;
   friend blink::Agent;
 
-  explicit EventLoop(v8::Isolate* isolate);
+  EventLoop(v8::Isolate* isolate,
+            std::unique_ptr<v8::MicrotaskQueue> microtask_queue = nullptr);
   ~EventLoop();
 
   static void RunPendingMicrotask(void* data);
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread.h b/third_party/blink/renderer/platform/scheduler/public/thread.h
index ca86e06..9926c722 100644
--- a/third_party/blink/renderer/platform/scheduler/public/thread.h
+++ b/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -84,7 +84,7 @@
   using IdleTask = base::OnceCallback<void(base::TimeTicks deadline)>;
 
   // TaskObserver is an observer fired before and after a task is executed.
-  using TaskObserver = base::MessageLoop::TaskObserver;
+  using TaskObserver = base::TaskObserver;
 
   // Creates a new thread. This may be called from a non-main thread (e.g.
   // nested Web workers).
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
index 4c55334..182fe536 100644
--- a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
@@ -20,6 +19,10 @@
 class Isolate;
 }
 
+namespace base {
+class TaskObserver;
+}
+
 namespace blink {
 namespace scheduler {
 class NonMainThreadSchedulerImpl;
@@ -121,10 +124,8 @@
   // Adds or removes a task observer from the scheduler. The observer will be
   // notified before and after every executed task. These functions can only be
   // called on the thread this scheduler was created on.
-  virtual void AddTaskObserver(
-      base::MessageLoop::TaskObserver* task_observer) = 0;
-  virtual void RemoveTaskObserver(
-      base::MessageLoop::TaskObserver* task_observer) = 0;
+  virtual void AddTaskObserver(base::TaskObserver* task_observer) = 0;
+  virtual void RemoveTaskObserver(base::TaskObserver* task_observer) = 0;
 
   virtual scheduler::PendingUserInputInfo GetPendingUserInputInfo() const {
     return scheduler::PendingUserInputInfo();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
index 5e6a501..ef04e64 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "base/message_loop/message_loop.h"
 #include "base/task/sequence_manager/task_queue.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -119,12 +118,12 @@
 }
 
 void CompositorThreadScheduler::AddTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+    base::TaskObserver* task_observer) {
   helper()->AddTaskObserver(task_observer);
 }
 
 void CompositorThreadScheduler::RemoveTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+    base::TaskObserver* task_observer) {
   helper()->RemoveTaskObserver(task_observer);
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
index 0a84afd..dbf2da6 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_THREAD_SCHEDULER_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "components/scheduling_metrics/task_duration_metric_reporter.h"
 #include "third_party/blink/public/platform/web_thread_type.h"
@@ -15,6 +14,10 @@
 #include "third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
 
+namespace base {
+class TaskObserver;
+}
+
 namespace blink {
 namespace scheduler {
 
@@ -42,9 +45,8 @@
   scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
   bool ShouldYieldForHighPriorityWork() override;
   bool CanExceedIdleDeadlineIfRequired() const override;
-  void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
-  void RemoveTaskObserver(
-      base::MessageLoop::TaskObserver* task_observer) override;
+  void AddTaskObserver(base::TaskObserver* task_observer) override;
+  void RemoveTaskObserver(base::TaskObserver* task_observer) override;
   void AddRAILModeObserver(RAILModeObserver*) override {}
   void RemoveRAILModeObserver(RAILModeObserver const*) override {}
   void Shutdown() override;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
index 4b9caf1..256670a5 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -160,14 +160,13 @@
   return false;
 }
 
-void WorkerThreadScheduler::AddTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+void WorkerThreadScheduler::AddTaskObserver(base::TaskObserver* task_observer) {
   DCHECK(initialized_);
   helper()->AddTaskObserver(task_observer);
 }
 
 void WorkerThreadScheduler::RemoveTaskObserver(
-    base::MessageLoop::TaskObserver* task_observer) {
+    base::TaskObserver* task_observer) {
   DCHECK(initialized_);
   helper()->RemoveTaskObserver(task_observer);
 }
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
index 32e1adf..9e3b42a 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "components/scheduling_metrics/task_duration_metric_reporter.h"
 #include "third_party/blink/public/platform/web_thread_type.h"
@@ -17,6 +16,7 @@
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h"
 
 namespace base {
+class TaskObserver;
 namespace sequence_manager {
 class SequenceManager;
 }
@@ -56,9 +56,8 @@
   scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
   bool ShouldYieldForHighPriorityWork() override;
   bool CanExceedIdleDeadlineIfRequired() const override;
-  void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
-  void RemoveTaskObserver(
-      base::MessageLoop::TaskObserver* task_observer) override;
+  void AddTaskObserver(base::TaskObserver* task_observer) override;
+  void RemoveTaskObserver(base::TaskObserver* task_observer) override;
   void AddRAILModeObserver(RAILModeObserver*) override {}
   void RemoveRAILModeObserver(RAILModeObserver const*) override {}
   void Shutdown() override;
diff --git a/third_party/blink/renderer/platform/timer_test.cc b/third_party/blink/renderer/platform/timer_test.cc
index ccf248e5..0c6df2ca 100644
--- a/third_party/blink/renderer/platform/timer_test.cc
+++ b/third_party/blink/renderer/platform/timer_test.cc
@@ -673,7 +673,7 @@
 
 namespace {
 
-class TaskObserver : public base::MessageLoop::TaskObserver {
+class TaskObserver : public base::TaskObserver {
  public:
   TaskObserver(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
                Vector<scoped_refptr<base::SingleThreadTaskRunner>>* run_order)
diff --git a/third_party/blink/renderer/platform/wtf/linked_hash_set.h b/third_party/blink/renderer/platform/wtf/linked_hash_set.h
index b35b6e95..77e524c 100644
--- a/third_party/blink/renderer/platform/wtf/linked_hash_set.h
+++ b/third_party/blink/renderer/platform/wtf/linked_hash_set.h
@@ -146,6 +146,11 @@
                     LinkedHashSetNodeBase* next)
       : LinkedHashSetNodeBase(prev, next), value_(value) {}
 
+  LinkedHashSetNode(ValueArg&& value,
+                    LinkedHashSetNodeBase* prev,
+                    LinkedHashSetNodeBase* next)
+      : LinkedHashSetNodeBase(prev, next), value_(std::move(value)) {}
+
   LinkedHashSetNode(LinkedHashSetNode&& other)
       : LinkedHashSetNodeBase(std::move(other)),
         value_(std::move(other.value_)) {}
@@ -445,10 +450,13 @@
 
   // The slot is empty when the next_ field is zero so it's safe to zero
   // the backing.
-  static const bool kEmptyValueIsZero = true;
+  static const bool kEmptyValueIsZero = ValueTraits::kEmptyValueIsZero;
 
   static const bool kHasIsEmptyValueFunction = true;
   static bool IsEmptyValue(const Node& node) { return !node.next_; }
+  static Node EmptyValue() {
+    return Node(ValueTraits::EmptyValue(), nullptr, nullptr);
+  }
 
   static const int kDeletedValue = -1;
 
diff --git a/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc b/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
index 4c3f899..cd1be00 100644
--- a/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
+++ b/third_party/blink/renderer/platform/wtf/list_hash_set_test.cc
@@ -487,6 +487,7 @@
 };
 
 struct Complicated {
+  Complicated() : Complicated(0) {}
   Complicated(int value) : simple_(value) { objects_constructed_++; }
 
   Complicated(const Complicated& other) : simple_(other.simple_) {
@@ -495,9 +496,6 @@
 
   Simple simple_;
   static int objects_constructed_;
-
- private:
-  Complicated() = delete;
 };
 
 int Complicated::objects_constructed_ = 0;
@@ -731,4 +729,45 @@
 
 }  // anonymous namespace
 
+// A unit type which objects to its state being initialized wrong.
+struct InvalidZeroValue {
+  InvalidZeroValue() = default;
+  InvalidZeroValue(WTF::HashTableDeletedValueType) : deleted_(true) {}
+  ~InvalidZeroValue() { CHECK(ok_); }
+  bool IsHashTableDeletedValue() const { return deleted_; }
+
+  bool ok_ = true;
+  bool deleted_ = false;
+};
+
+template <>
+struct HashTraits<InvalidZeroValue> : SimpleClassHashTraits<InvalidZeroValue> {
+  static const bool kEmptyValueIsZero = false;
+};
+
+template <>
+struct DefaultHash<InvalidZeroValue> {
+  struct Hash {
+    static unsigned GetHash(const InvalidZeroValue&) { return 0; }
+    static bool Equal(const InvalidZeroValue&, const InvalidZeroValue&) {
+      return true;
+    }
+  };
+};
+
+template <typename Set>
+class ListOrLinkedHashSetInvalidZeroTest : public testing::Test {};
+
+using InvalidZeroValueSetTypes =
+    testing::Types<ListHashSet<InvalidZeroValue>,
+                   ListHashSet<InvalidZeroValue, 1>,
+                   LinkedHashSet<InvalidZeroValue>>;
+TYPED_TEST_SUITE(ListOrLinkedHashSetInvalidZeroTest, InvalidZeroValueSetTypes);
+
+TYPED_TEST(ListOrLinkedHashSetInvalidZeroTest, InvalidZeroValue) {
+  using Set = TypeParam;
+  Set set;
+  set.insert(InvalidZeroValue());
+}
+
 }  // namespace WTF
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index 7bb1906..a8ebc39db 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -206,7 +206,7 @@
             # PartitionAlloc
             'base::PartitionFree',
 
-            # For MessageLoop::TaskObserver.
+            # For TaskObserver.
             'base::PendingTask',
 
             # Time
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
index c4721b14..79f9842 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -71,6 +71,7 @@
 _PLATFORM_TOKENS_LIST = [
     'Android',
     'Fuchsia',
+    'IOS', 'IOS12.2', 'IOS13.0',
     'Linux',
     'Mac', 'Mac10.10', 'Mac10.11', 'Retina', 'Mac10.12', 'Mac10.13',
     'Win', 'Win7', 'Win10'
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py
index a677c7a8..7c4c79e 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -134,6 +134,9 @@
         ('trusty', 'x86_64'),
 
         ('fuchsia', 'x86_64'),
+
+        ('ios12.2', 'x86_64'),
+        ('ios13.0', 'x86_64'),
     )
 
     CONFIGURATION_SPECIFIER_MACROS = {
@@ -141,6 +144,7 @@
         'win': ['win7', 'win10'],
         'linux': ['trusty'],
         'fuschia': ['fuchsia'],
+        'ios': ['ios12.2', 'ios13.0'],
     }
 
     # List of ports open on the host that the tests will connect to. When tests
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/factory.py b/third_party/blink/tools/blinkpy/web_tests/port/factory.py
index fb58b9e1..a0ef139 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/factory.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/factory.py
@@ -39,6 +39,7 @@
     PORT_CLASSES = (
         'android.AndroidPort',
         'fuchsia.FuchsiaPort',
+        'ios.IOSPort',
         'linux.LinuxPort',
         'mac.MacPort',
         'mock_drt.MockDRTPort',
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/ios.py b/third_party/blink/tools/blinkpy/web_tests/port/ios.py
new file mode 100644
index 0000000..86c93ef
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/web_tests/port/ios.py
@@ -0,0 +1,55 @@
+# Copyright (C) 2019 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Chromium iOS implementation of the Port interface."""
+
+import logging
+
+from blinkpy.web_tests.port import base
+
+
+_log = logging.getLogger(__name__)
+
+
+class IOSPort(base.Port):
+    SUPPORTED_VERSIONS = ('ios12.2', 'ios13.0')
+    port_name = 'ios'
+
+    FALLBACK_PATHS = {}
+
+    FALLBACK_PATHS['ios13.0'] = ['ios']
+    FALLBACK_PATHS['ios12.2'] = ['ios12.2', 'ios']
+
+    def __init__(self, host, port_name, **kwargs):
+        super(IOSPort, self).__init__(host, port_name, **kwargs)
+        self._architecture = 'x86_64'
+        self._version = port_name[port_name.index('ios-') + len('ios-'):]
+        assert self._version in self.SUPPORTED_VERSIONS
+
+    def operating_system(self):
+        return 'ios'
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations
index c1a04876..65f8ec2 100644
--- a/third_party/blink/web_tests/LeakExpectations
+++ b/third_party/blink/web_tests/LeakExpectations
@@ -78,6 +78,7 @@
 crbug.com/862029 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-window-filter.js [ Pass Leak ]
 
 crbug.com/733494 [ Linux ] media/autoplay/document-user-activation.html [ Pass Leak ]
+crbug.com/733494 [ Linux ] virtual/audio-service/media/autoplay/document-user-activation.html [ Pass Leak ]
 
 # Sheriff 2019-01-04
 crbug.com/919117 [ Linux ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-drag.html [ Pass Leak ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index 1827043..7392c1e 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -130,6 +130,7 @@
 crbug.com/856601 [ Linux ] external/wpt/media-capabilities/idlharness.any.worker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/mediacapture-image/idlharness.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/mediacapture-streams/idlharness.https.window.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/audio-service/external/wpt/mediacapture-streams/idlharness.https.window.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/netinfo/idlharness.any.worker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/notifications/idlharness.https.any.html [ Pass Failure Timeout ]
 crbug.com/856601 [ Linux ] external/wpt/notifications/idlharness.https.any.serviceworker.html [ Timeout Pass ]
@@ -337,3 +338,7 @@
 crbug.com/856601 [ Linux ] virtual/omt-worker-fetch/external/wpt/xhr/idlharness.any.sharedworker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] virtual/omt-worker-fetch/external/wpt/xhr/idlharness.any.worker.html [ Pass Timeout ]
 crbug.com/856601 [ Linux ] wpt_internal/std-switch/tentative/interface.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] http/tests/devtools/a11y-axe-core/elements/main-tool-test.js [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/not-omt-sw-fetch/external/wpt/resource-timing/idlharness.any.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] virtual/not-omt-sw-fetch/external/wpt/resource-timing/idlharness.any.worker.html [ Pass Timeout ]
+crbug.com/856601 [ Linux ] webaudio/Analyser/realtimeanalyser-freq-data.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 853e56b6..8be032d 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -1622,6 +1622,7 @@
 
 # Requires --use-fake-ui-for-media-stream to run.
 external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ WontFix ]
+virtual/audio-service/external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ WontFix ]
 
 # These directories have manual tests that don't have to run with
 # run_web_tests.py; see https://crbug.com/359838.
@@ -2137,6 +2138,8 @@
 virtual/blink-cors/external/wpt/xhr/send-authentication-prompt-2-manual.htm [ WontFix ]
 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-MediaElement-preload-none-manual.https.html [ WontFix ]
 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStreamTrack-end-manual.https.html [ WontFix ]
+virtual/audio-service/external/wpt/mediacapture-streams/MediaStream-MediaElement-preload-none-manual.https.html [ WontFix ]
+virtual/audio-service/external/wpt/mediacapture-streams/MediaStreamTrack-end-manual.https.html [ WontFix ]
 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/fetch-event-is-history-backward-navigation-manual.https.html [ WontFix ]
 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/fetch-event-is-history-forward-navigation-manual.https.html [ WontFix ]
 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/fetch-event-is-reload-navigation-manual.https.html [ WontFix ]
@@ -2248,6 +2251,7 @@
 crbug.com/946022 [ Win7 ] images/image-zoom-to-25.html [ WontFix ]
 crbug.com/946022 [ Win7 ] images/image-zoom-to-500.html [ WontFix ]
 crbug.com/946022 [ Win7 ] media/controls/overflow-menu-hide-on-resize.html [ WontFix ]
+crbug.com/946022 [ Win7 ] virtual/audio-service/media/controls/overflow-menu-hide-on-resize.html [ WontFix ]
 crbug.com/946022 [ Win7 ] paint/invalidation/resize-iframe-text.html [ WontFix ]
 crbug.com/946022 [ Win7 ] paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint.html [ WontFix ]
 crbug.com/946022 [ Win7 ] paint/invalidation/window-resize/ [ WontFix ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 535532bb..3ea40c6d 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -44,6 +44,8 @@
 crbug.com/24182 jquery/traversing.html [ Slow ]
 crbug.com/24182 media/controls/controls-cast-do-not-fade-out.html [ Slow ]
 crbug.com/24182 media/controls/controls-cast-overlay-slow-fade.html [ Slow ]
+crbug.com/24182 virtual/audio-service/media/controls/controls-cast-do-not-fade-out.html [ Slow ]
+crbug.com/24182 virtual/audio-service/media/controls/controls-cast-overlay-slow-fade.html [ Slow ]
 crbug.com/24182 svg/filters/big-sized-filter.svg [ Slow ]
 crbug.com/24182 tables/mozilla/other/slashlogo.html [ Slow ]
 crbug.com/24182 fast/canvas/color-space/canvas-colorManaged-toBlob-toDataURL.html [ Slow ]
@@ -117,6 +119,10 @@
 crbug.com/73609 http/tests/media/video-preload-metadata.html [ Slow ]
 crbug.com/869829 http/tests/media/video-cancel-load.html [ Slow ]
 crbug.com/870259 http/tests/media/video-throttled-load-metadata.html [ Slow ]
+crbug.com/73609 virtual/audio-service/http/tests/media/video-play-stall.html [ Slow ]
+crbug.com/73609 virtual/audio-service/http/tests/media/video-preload-metadata.html [ Slow ]
+crbug.com/869829 virtual/audio-service/http/tests/media/video-cancel-load.html [ Slow ]
+crbug.com/870259 virtual/audio-service/http/tests/media/video-throttled-load-metadata.html [ Slow ]
 
 # Many of the virtual animations tests are slow.
 crbug.com/243871 virtual/threaded/fast/scroll-behavior/ [ Slow ]
@@ -150,6 +156,7 @@
 crbug.com/346259 http/tests/websocket/no-crash-on-cookie-flood.html [ Slow ]
 
 crbug.com/522646 http/tests/media/encrypted-media/encrypted-media-encrypted-event-different-origin.html [ Slow ]
+crbug.com/522646 virtual/audio-service/http/tests/media/encrypted-media/encrypted-media-encrypted-event-different-origin.html [ Slow ]
 crbug.com/411164 [ Win ] http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Slow ]
 crbug.com/411164 [ Win ] virtual/blink-cors/http/tests/security/powerfulFeatureRestrictions/serviceworker-on-insecure-origin.html [ Slow ]
 crbug.com/510337 http/tests/devtools/console/console-format.js [ Slow ]
@@ -216,6 +223,7 @@
 
 # Media controls tests have to wait for panel to fade out.
 crbug.com/722825 media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Slow ]
+crbug.com/722825 virtual/audio-service/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Slow ]
 
 crbug.com/719298 fast/dnd/dropEffect-for-effectAllowed.html [ Slow ]
 
@@ -229,6 +237,7 @@
 crbug.com/451577 [ Linux ] http/tests/devtools/layers/layer-canvas-log.js [ Slow ]
 
 crbug.com/793771 media/controls/scrubbing.html [ Slow ]
+crbug.com/793771 virtual/audio-service/media/controls/scrubbing.html [ Slow ]
 
 # These tests need to do many iterations and so can't be fast.
 crbug.com/748418 http/tests/streams/chromium/deep-recursion-getwriter.html [ Slow ]
@@ -269,8 +278,10 @@
 crbug.com/864887 [ Mac ] fast/scroll-snap/snaps-after-scrollbar-scrolling.html [ Slow ]
 
 crbug.com/865262 [ Mac ] media/controls/text-track-menu-pointer-selection.html [ Slow ]
+crbug.com/865262 [ Mac ] virtual/audio-service/media/controls/text-track-menu-pointer-selection.html [ Slow ]
 
 crbug.com/942951 media/controls/controls-layout-in-different-size.html [ Slow ]
+crbug.com/942951 virtual/audio-service/media/controls/controls-layout-in-different-size.html [ Slow ]
 
 crbug.com/910627 webexposed/global-interface-listing-shared-worker.html [ Slow ]
 crbug.com/910627 virtual/stable/webexposed/global-interface-listing-shared-worker.html [ Slow ]
@@ -435,6 +446,11 @@
 crbug.com/874695 http/tests/media/video-buffered.html [ Slow ]
 crbug.com/874695 http/tests/media/video-load-metadata-decode-error.html [ Slow ]
 crbug.com/874695 http/tests/media/video-play-stall-before-meta-data.html [ Slow ]
+crbug.com/874695 virtual/audio-service/http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Slow ]
+crbug.com/874695 virtual/audio-service/http/tests/media/preload-conditions.html [ Slow ]
+crbug.com/874695 virtual/audio-service/http/tests/media/video-buffered.html [ Slow ]
+crbug.com/874695 virtual/audio-service/http/tests/media/video-load-metadata-decode-error.html [ Slow ]
+crbug.com/874695 virtual/audio-service/http/tests/media/video-play-stall-before-meta-data.html [ Slow ]
 crbug.com/874695 http/tests/misc/adopt-iframe-src-attr-after-remove.html [ Slow ]
 crbug.com/874695 http/tests/misc/async-script-removed.html [ Slow ]
 crbug.com/874695 http/tests/misc/client-hints-accept-meta-preloader.html [ Slow ]
@@ -493,6 +509,27 @@
 crbug.com/874695 media/video-controls-visibility-multimodal-mouse-after-touch.html [ Slow ]
 crbug.com/874695 media/video-controls-visibility-multimodal-touch-after-mouse.html [ Slow ]
 crbug.com/874695 media/video-played-collapse.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/audio-controls-do-not-fade-out.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/autoplay-muted.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/color-profile-video-seek-filter.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/encrypted-media/encrypted-media-onencrypted.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/encrypted-media/encrypted-media-setmediakeys-at-same-time.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/media-controls-tap-show-controls-without-activating.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/media-ended.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/remoteplayback/prompt-twice-throws.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/track/track-cue-gc-wrapper.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/unsupported-rtsp.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-always-visible-when-control-hovered.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-auto-hide-after-play-by-touch.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-dont-show-on-focus-when-disabled.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-focus-movement-on-hide.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-hide-after-touch-on-control.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-hide-on-move-outside-controls.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-show-on-focus.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-visibility-multimodal-mouse-after-touch.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-controls-visibility-multimodal-touch-after-mouse.html [ Slow ]
+crbug.com/874695 virtual/audio-service/media/video-played-collapse.html [ Slow ]
 crbug.com/874695 paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html [ Slow ]
 crbug.com/874695 paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html [ Slow ]
 crbug.com/874695 paint/invalidation/filters/filter-repaint-on-accelerated-layer.html [ Slow ]
@@ -603,6 +640,7 @@
 crbug.com/893015 [ Linux ] virtual/streaming-preload/http/tests/fetch/chromium/response-text-gc-crash.html [ Slow ]
 
 crbug.com/914981 [ Mac ] media/controls/overflow-menu-pointer-selection.html [ Slow ]
+crbug.com/914981 [ Mac ] virtual/audio-service/media/controls/overflow-menu-pointer-selection.html [ Slow ]
 crbug.com/914981 [ Mac ] virtual/mouseevent_fractional/fast/events/no-fake-mousemove.html [ Slow ]
 crbug.com/914981 [ Mac ] fast/events/no-fake-mousemove.html [ Slow ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a53f925..dcb25bc9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -39,6 +39,7 @@
 # These two are left over from crbug.com/881040, I rebaselined them twice and
 # they continue to fail.
 crbug.com/881040 media/controls/lazy-loaded-style.html [ Failure Pass ]
+crbug.com/881040 virtual/audio-service/media/controls/lazy-loaded-style.html [ Failure Pass ]
 
 # With --enable-display-compositor-pixel-dump enabled by default, these three
 # tests fail. See crbug.com/887140 for more info.
@@ -75,8 +76,10 @@
 crbug.com/801992 http/tests/misc/iframe-script-modify-attr.html [ Pass Crash ]
 crbug.com/819800 external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest-timing.https.sub.html [ Failure ]
 crbug.com/872952 http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html [ Failure Pass Timeout ]
+crbug.com/872952 virtual/audio-service/http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html [ Failure Pass Timeout ]
 crbug.com/895001 external/wpt/html/user-activation/message-event-activation-api-iframe-cross-origin.sub.tentative.html [ Timeout Pass ]
 crbug.com/895001 http/tests/media/autoplay/webaudio-autoplay-iframe-with-gesture.html [ Timeout Pass ]
+crbug.com/895001 virtual/audio-service/http/tests/media/autoplay/webaudio-autoplay-iframe-with-gesture.html [ Timeout Pass ]
 crbug.com/901502 http/tests/devtools/oopif/oopif-storage.js [ Pass Failure ]
 crbug.com/906879 http/tests/inspector-protocol/network/navigation-blocking-xorigin-iframe.js [ Pass Failure ]
 crbug.com/949003 http/tests/printing/cross-site-frame-scrolled.html [ Pass Failure ]
@@ -537,11 +540,13 @@
 crbug.com/949909 external/wpt/css/css-text-decor/text-decoration-040-manual.html [ Skip ]
 
 crbug.com/722825 media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Timeout Pass ]
+crbug.com/722825 virtual/audio-service/media/controls/video-enter-exit-fullscreen-while-hovering-shows-controls.html [ Timeout Pass ]
 
 #### crbug.com/783229 overflow
 crbug.com/724701 overflow/overflow-basic-004.html [ Failure ]
 
 crbug.com/846753 [ Mac ] http/tests/media/reload-after-dialog.html [ Failure Pass Timeout ]
+crbug.com/846753 [ Mac ] virtual/audio-service/http/tests/media/reload-after-dialog.html [ Failure Pass Timeout ]
 
 ### external/wpt/css/css-tables/
 crbug.com/598134 external/wpt/css/css-tables/table-has-box-sizing-border-box-002.html [ Failure ]
@@ -865,6 +870,7 @@
 crbug.com/591099 [ Mac ] images/feature-policy-oversized-images-resize.html [ Failure ]
 crbug.com/974717 [ Linux ] images/feature-policy-oversized-images-resize.html [ Failure Pass ]
 # crbug.com/591099 [ Mac10.11 ] media/track/track-cue-rendering-position-auto-rtl.html [ Failure ]
+crbug.com/591099 [ Mac10.11 ] virtual/audio-service/media/track/track-cue-rendering-position-auto-rtl.html [ Failure ]
 crbug.com/591099 [ Mac10.11 ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] compositing/geometry/root-layer-update.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] compositing/overlap-blending/reflection-opacity-huge.html [ Failure ]
@@ -1172,7 +1178,9 @@
 crbug.com/591099 [ Mac10.13 ] images/imagemap-focus-ring.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] images/imagemap-overflowing-polygon-focus-ring.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] media/video-colorspace-yuv420.html [ Failure ]
+crbug.com/591099 [ Mac10.13 ] virtual/audio-service/media/video-colorspace-yuv420.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] media/video-empty-source.html [ Failure ]
+crbug.com/591099 [ Mac10.13 ] virtual/audio-service/media/video-empty-source.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] paint/invalidation/background/background-misaligned.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] paint/invalidation/block-no-inflow-children.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] paint/invalidation/bugzilla-7235.html [ Failure ]
@@ -1459,6 +1467,8 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-groove-000.xht [ Failure ]
 crbug.com/792437 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-inset-000.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-large-001.xht [ Failure ]
+crbug.com/990240 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-nested-balancing-001.html [ Failure ]
+crbug.com/990240 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-nested-balancing-002.html [ Failure ]
 crbug.com/792437 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-outset-000.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-percent-001.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-px-001.xht [ Failure ]
@@ -1487,6 +1497,10 @@
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-001.html [ Failure ]
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-002.html [ Failure ]
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-003.html [ Failure ]
+crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-004a.html [ Failure ]
+crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-004b.html [ Failure ]
+crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-005.html [ Failure ]
+crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-006.html [ Failure ]
 crbug.com/924142 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-dynamic-add-010.html [ Crash Pass ]
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-dynamic-add-012.html [ Failure Crash ]
 crbug.com/829028 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-dynamic-add-013.html [ Failure Crash ]
@@ -1500,6 +1514,7 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-margin-nested-001.xht [ Failure ]
 crbug.com/636055 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-margin-nested-002.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht [ Failure ]
+crbug.com/990240 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-rule-001.html [ Failure ]
 crbug.com/792446 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-none-001.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-under-vertical-rl-scroll.html [ Failure ]
@@ -2269,10 +2284,14 @@
 crbug.com/280342 [ Mac ] http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
 crbug.com/280342 [ Linux ] http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
 crbug.com/280342 [ Win ] http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
+crbug.com/280342 [ Mac ] virtual/audio-service/http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
+crbug.com/280342 [ Linux ] virtual/audio-service/http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
+crbug.com/280342 [ Win ] virtual/audio-service/http/tests/media/progress-events-generated-correctly.html [ Failure Pass ]
 
 crbug.com/520736 [ Win7 ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
 crbug.com/520736 [ Linux ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
 crbug.com/909095 [ Mac ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
+crbug.com/909095 virtual/audio-service/media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
 
 crbug.com/862716 [ Mac ] css3/filters/effect-brightness-clamping-hw.html [ Failure Pass Timeout ]
 crbug.com/862716 [ Linux ] css3/filters/effect-brightness-clamping-hw.html [ Failure Pass Timeout ]
@@ -2341,6 +2360,7 @@
 
 crbug.com/432129 html/marquee/marquee-scroll.html [ Failure Pass ]
 crbug.com/326139 crbug.com/390125 media/video-frame-accurate-seek.html [ Failure Pass ]
+crbug.com/326139 crbug.com/390125 virtual/audio-service/media/video-frame-accurate-seek.html [ Failure Pass ]
 crbug.com/421283 html/marquee/marquee-scrollamount.html [ Pass Failure ]
 
 # TODO(oshima): Mac Android are currently not supported.
@@ -2422,6 +2442,7 @@
 
 crbug.com/688613 external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
 crbug.com/688613 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
+crbug.com/688613 virtual/audio-service/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
 
 
 crbug.com/766135 fast/dom/Window/redirect-with-timer.html [ Timeout Pass ]
@@ -2568,6 +2589,7 @@
 crbug.com/467635 fast/dom/HTMLImageElement/image-sizes-meta-viewport.html [ Skip ]
 
 crbug.com/636239 [ Win7 ] media/video-zoom-controls.html [ Failure ]
+crbug.com/636239 [ Win7 ] virtual/audio-service/media/video-zoom-controls.html [ Failure ]
 
 # The spec for "Propagation to the Initial Containing Block" was changed.
 # https://drafts.csswg.org/css-writing-modes-4/#icb
@@ -2625,11 +2647,13 @@
 crbug.com/658305 css3/filters/filter-effect-removed.html [ Failure Pass ]
 
 crbug.com/524160 [ Debug ] http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Timeout ]
+crbug.com/524160 [ Debug ] virtual/audio-service/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Timeout ]
 
 # Run the tests with the default MSE buffer sizes in the main test suite and the tests for 1MB buffers set via command line in a virtual test suite
 # with the --mse-audio-buffer-size-limit=1048576 and --mse-video-buffer-size-limit=1048576 command-line parameters.
 crbug.com/630342 virtual/mse-1mb-buffers/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Skip ]
 crbug.com/630342 http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-1mb-buffers.html [ Skip ]
+crbug.com/630342 virtual/audio-service/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-1mb-buffers.html [ Skip ]
 
 # On these platforms (all but Android) media tests don't currently use gpu-accelerated (proprietary) codecs, so no
 # benefit to running them again with gpu acceleration enabled.
@@ -2641,7 +2665,9 @@
 crbug.com/467477 fast/multicol/vertical-rl/nested-columns.html [ Failure ]
 
 crbug.com/400841 media/video-canvas-draw.html [ Failure ]
+crbug.com/400841 virtual/audio-service/media/video-canvas-draw.html [ Failure ]
 crbug.com/400829 virtual/stable/media/stable/video-object-fit-stable.html [ Failure ]
+crbug.com/400829 virtual/audio-service/media/stable/video-object-fit-stable.html [ Failure ]
 
 # These contain faulty expectations. https://chromium-review.googlesource.com/c/v8/v8/+/1350790 should fix the
 # faulty return values but to allow landing that patch, the tests have to be deactivated in the meanwhile.
@@ -3012,12 +3038,18 @@
 crbug.com/654477 fast/layers/video-layer.html [ Failure ]
 # These could likely be removed - see https://chromium-review.googlesource.com/c/chromium/src/+/1252141
 crbug.com/654477 media/controls-focus-ring.html [ Failure ]
+crbug.com/654477 virtual/audio-service/media/controls-focus-ring.html [ Failure ]
 crbug.com/654477 [ Mac10.10 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 crbug.com/654477 [ Mac10.11 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 crbug.com/654477 [ Retina ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 crbug.com/638621 [ Win7 ] http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
+crbug.com/654477 [ Mac10.10 ] virtual/audio-service/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
+crbug.com/654477 [ Mac10.11 ] virtual/audio-service/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
+crbug.com/654477 [ Retina ] virtual/audio-service/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
+crbug.com/638621 [ Win7 ] virtual/audio-service/http/tests/media/video-buffered-range-contains-currentTime.html [ Failure ]
 
 crbug.com/637930 http/tests/media/video-buffered.html [ Pass Failure ]
+crbug.com/637930 virtual/audio-service/http/tests/media/video-buffered.html [ Pass Failure ]
 
 crbug.com/613659 external/wpt/quirks/percentage-height-calculation.html [ Failure ]
 crbug.com/613661 external/wpt/quirks/table-cell-nowrap-minimum-width-calculation.html [ Failure ]
@@ -3321,25 +3353,9 @@
 crbug.com/626703 external/wpt/css/css-text/white-space/trailing-other-space-separators-break-spaces-005.html [ Failure ]
 crbug.com/626703 [ Win7 ] virtual/blink-cors/external/wpt/referrer-policy/unsafe-url/attr-referrer/same-origin/http-http/img-tag/swap-origin-redirect/generic.http.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-text/white-space/trailing-other-space-separators-003.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-nested-balancing-002.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-breaking-000.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-breaking-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-breaking-nobackground-000.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-span-all-rule-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-breaking-nobackground-001.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-rule-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-rule-nested-balancing-002.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-rule-nested-balancing-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-multicol/multicol-rule-nested-balancing-001.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-005.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-004a.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-004b.html [ Failure ]
-crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-children-height-006.html [ Failure ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/mediacapture-fromelement/ended.html [ Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html [ Timeout ]
-crbug.com/626703 [ Mac10.13 ] external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Timeout ]
-crbug.com/626703 [ Retina ] external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/workers/data-url-shared.html [ Crash ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/webaudio/the-audio-api/the-convolvernode-interface/realtime-conv.html [ Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-svg-none-test_touch.html [ Timeout ]
@@ -3603,6 +3619,7 @@
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/bidi/start_alignment.html [ Failure ]
 crbug.com/626703 [ Retina ] external/wpt/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/open-features-tokenization-top-left.html [ Timeout ]
 crbug.com/626703 external/wpt/mediacapture-streams/MediaStream-MediaElement-srcObject.https.html [ Timeout ]
+crbug.com/626703 virtual/audio-service/external/wpt/mediacapture-streams/MediaStream-MediaElement-srcObject.https.html [ Timeout ]
 crbug.com/626703 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-MediaElement-srcObject.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/html/cross-origin/anonymous.tentative.html [ Failure Crash ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/html/cross-origin/anonymous.tentative.html [ Failure Crash ]
@@ -4674,9 +4691,15 @@
 
 crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-001.html [ Failure ]
 crbug.com/967329 external/wpt/css/css-multicol/columnfill-auto-max-height-002.html [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-000.html [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-001.html [ Failure ]
 crbug.com/481431 external/wpt/css/css-multicol/multicol-breaking-004.html [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-000.html [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-001.html [ Failure ]
 crbug.com/792435 external/wpt/css/css-multicol/multicol-rule-004.xht [ Failure ]
 crbug.com/792437 external/wpt/css/css-multicol/multicol-rule-inset-000.xht [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-rule-nested-balancing-001.html [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-rule-nested-balancing-002.html [ Failure ]
 crbug.com/792437 external/wpt/css/css-multicol/multicol-rule-outset-000.xht [ Failure ]
 crbug.com/963109 external/wpt/css/css-multicol/multicol-span-all-button-001.html [ Failure ]
 crbug.com/963109 external/wpt/css/css-multicol/multicol-span-all-button-002.html [ Failure ]
@@ -4693,6 +4716,7 @@
 crbug.com/915204 external/wpt/css/css-multicol/multicol-span-all-011.html [ Failure ]
 crbug.com/892817 external/wpt/css/css-multicol/multicol-span-all-margin-bottom-001.xht [ Failure ]
 crbug.com/636055 external/wpt/css/css-multicol/multicol-span-all-margin-nested-002.xht [ Failure ]
+crbug.com/990240 external/wpt/css/css-multicol/multicol-span-all-rule-001.html [ Failure ]
 crbug.com/792446 external/wpt/css/css-multicol/multicol-span-float-001.xht [ Failure ]
 crbug.com/964183 external/wpt/css/css-multicol/multicol-width-005.html [ Failure ]
 
@@ -4874,6 +4898,8 @@
 #crbug.com/765738 [ Linux Win Mac ] http/tests/wasm/wasm_remote_postMessage_test.https.html [ Pass Timeout ]
 crbug.com/892212 http/tests/wasm/wasm_remote_postMessage_test.https.html [ Pass Failure Timeout ]
 
+crbug.com/990331 virtual/audio-service/http/tests/media/media-source/mediasource-play.html [ Pass Timeout ]
+
 # ====== Random order flaky tests from here ======
 # These tests are flaky when run in random order, which is the default on Linux & Mac since since 2016-12-16.
 
@@ -4954,6 +4980,7 @@
 
 crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ]
 crbug.com/689781 [ Win Mac ] http/tests/media/media-source/mediasource-duration.html [ Failure Pass ]
+crbug.com/689781 [ Win Mac ] virtual/audio-service/http/tests/media/media-source/mediasource-duration.html [ Failure Pass ]
 
 crbug.com/681468 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom125.html [ Failure Pass ]
 crbug.com/681468 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom200.html [ Failure Pass ]
@@ -4998,6 +5025,7 @@
 
 # Sheriff failures 2017-02-21
 crbug.com/73609 http/tests/media/video-play-stall.html [ Pass Timeout ]
+crbug.com/73609 virtual/audio-service/http/tests/media/video-play-stall.html [ Pass Timeout ]
 
 # Sheriff failures 2017-03-10
 crbug.com/741210 [ Mac ] inspector-protocol/emulation/device-emulation-restore.js [ Failure ]
@@ -5018,6 +5046,7 @@
 crbug.com/722212 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-event-properties.html [ Failure Timeout Pass ]
 # Crashes on win
 crbug.com/722943 media/audio-repaint.html [ Skip ]
+crbug.com/722943 virtual/audio-service/media/audio-repaint.html [ Skip ]
 
 # Sheriff failures 2018-08-13
 crbug.com/873454 css3/filters/effect-reference-image-hw.html [ Failure Pass ]
@@ -5044,6 +5073,7 @@
 crbug.com/718155 fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
 crbug.com/718155 fullscreen/full-screen-restrictions.html [ Failure Timeout ]
 crbug.com/718155 media/video-controls-fullscreen-iframe-not-allowed.html [ Failure ]
+crbug.com/718155 virtual/audio-service/media/video-controls-fullscreen-iframe-not-allowed.html [ Failure ]
 crbug.com/718155 virtual/android/fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
 crbug.com/718155 virtual/android/fullscreen/full-screen-restrictions.html [ Failure Timeout ]
 
@@ -5107,7 +5137,9 @@
 crbug.com/745887 [ Win ] fast/frames/sandboxed-iframe-plugins.html [ Failure Pass ]
 
 crbug.com/746128 [ Win7 Debug ] media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure ]
+crbug.com/746128 [ Win7 Debug ] virtual/audio-service/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure ]
 crbug.com/746128 [ Mac ] media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure Pass ]
+crbug.com/746128 [ Mac ] virtual/audio-service/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure Pass ]
 
 crbug.com/731018 [ Mac ] sensor/accelerometer.html [ Failure Pass Crash ]
 crbug.com/731018 [ Mac ] sensor/ambient-light-sensor.html [ Failure Pass Crash ]
@@ -5117,12 +5149,17 @@
 
 # Tests failing when enabling new modern media controls
 crbug.com/831942 media/webkit-media-controls-webkit-appearance.html [ Failure Pass ]
+crbug.com/831942 virtual/audio-service/media/webkit-media-controls-webkit-appearance.html [ Failure Pass ]
 crbug.com/831957 compositing/video/video-controls-layer-creation-squashing.html [ Failure Pass ]
 crbug.com/832157 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html [ Skip ]
 crbug.com/832169 media/media-controls-fit-properly-while-zoomed.html [ Failure Pass ]
+crbug.com/832169 virtual/audio-service/media/media-controls-fit-properly-while-zoomed.html [ Failure Pass ]
 crbug.com/832447 media/controls/controls-page-zoom-in.html [ Failure Pass ]
 crbug.com/832447 media/controls/controls-page-zoom-out.html [ Failure Pass ]
+crbug.com/832447 virtual/audio-service/media/controls/controls-page-zoom-in.html [ Failure Pass ]
+crbug.com/832447 virtual/audio-service/media/controls/controls-page-zoom-out.html [ Failure Pass ]
 crbug.com/849694 [ Mac ] http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Failure Pass ]
+crbug.com/849694 [ Mac ] virtual/audio-service/http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Failure Pass ]
 
 # ContentSecurityPolicy modifies the SchemeRegistry before some initialization.
 crbug.com/686118 http/tests/security/contentSecurityPolicy/register-bypassing-scheme.html [ Pass Crash ]
@@ -5235,6 +5272,9 @@
 crbug.com/694855 media/audio-src-suspend-after-have-metadata.html [ Skip ]
 crbug.com/694855 media/video-src-skip-suspend-after-have-metadata.html [ Skip ]
 crbug.com/694855 media/video-src-suspend-after-have-metadata.html [ Skip ]
+crbug.com/694855 virtual/audio-service/media/audio-src-suspend-after-have-metadata.html [ Skip ]
+crbug.com/694855 virtual/audio-service/media/video-src-skip-suspend-after-have-metadata.html [ Skip ]
+crbug.com/694855 virtual/audio-service/media/video-src-suspend-after-have-metadata.html [ Skip ]
 
 ### See crbug.com/891427 comment near the top of this file:
 ###crbug.com/849979 media/video-layer-crash.html [ Pass Timeout ]
@@ -5284,6 +5324,7 @@
 
 # Sheriff failures 2017-10-23
 crbug.com/772411 http/tests/media/autoplay-crossorigin.html [ Timeout Failure Pass ]
+crbug.com/772411 virtual/audio-service/http/tests/media/autoplay-crossorigin.html [ Timeout Failure Pass ]
 crbug.com/777222 http/tests/devtools/inspect-iframe-from-different-domain.js [ Pass Failure Timeout ]
 
 crbug.com/778745 http/tests/inspector-protocol/cachestorage/read-cached-response.js [ Pass Failure ]
@@ -5360,6 +5401,12 @@
 crbug.com/783154 [ Mac ] media/controls/doubletap-on-play-button.html [ Skip ]
 crbug.com/783154 [ Mac ] media/controls/doubletap-to-toggle-fullscreen.html [ Skip ]
 crbug.com/783154 [ Mac ] media/controls/click-anywhere-to-play-pause.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/doubletap-to-jump-backwards.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/doubletap-to-jump-forwards.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/doubletap-to-jump-forwards-too-short.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/doubletap-on-play-button.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/doubletap-to-toggle-fullscreen.html [ Skip ]
+crbug.com/783154 [ Mac ] virtual/audio-service/media/controls/click-anywhere-to-play-pause.html [ Skip ]
 
 # Seen flaky on Linux, suppressing on Windows as well
 crbug.com/831720 [ Win ] media/controls/doubletap-to-jump-forwards-too-short.html [ Pass Failure ]
@@ -5367,6 +5414,11 @@
 crbug.com/831720 [ Mac ] media/controls/tap-to-hide-controls.html [ Pass Failure ]
 crbug.com/831720 [ Win ] media/controls/tap-to-hide-controls.html [ Pass Failure ]
 crbug.com/831720 [ Linux ] media/controls/tap-to-hide-controls.html [ Pass Failure ]
+crbug.com/831720 [ Win ] virtual/audio-service/media/controls/doubletap-to-jump-forwards-too-short.html [ Pass Failure ]
+crbug.com/831720 [ Linux ] virtual/audio-service/media/controls/doubletap-to-jump-forwards-too-short.html [ Pass Failure ]
+crbug.com/831720 [ Mac ] virtual/audio-service/media/controls/tap-to-hide-controls.html [ Pass Failure ]
+crbug.com/831720 [ Win ] virtual/audio-service/media/controls/tap-to-hide-controls.html [ Pass Failure ]
+crbug.com/831720 [ Linux ] virtual/audio-service/media/controls/tap-to-hide-controls.html [ Pass Failure ]
 
 crbug.com/802915 css3/blending/isolation-should-include-non-local-background.html [ Failure ]
 
@@ -5377,6 +5429,7 @@
 
 # Does not work on Mac
 crbug.com/793771 [ Mac ] media/controls/scrubbing.html [ Skip ]
+crbug.com/793771 [ Mac Win ] virtual/audio-service/media/controls/scrubbing.html [ Skip ]
 
 # Different paths may have different anti-aliasing pixels 2018-02-21
 skbug.com/7641 external/wpt/css/css-paint-api/paint2d-paths.https.html [ Failure Pass ]
@@ -5395,6 +5448,7 @@
 
 # Sheriff failures 2018-02-20
 crbug.com/789921 media/controls/repaint-on-resize.html [ Failure Pass ]
+crbug.com/789921 virtual/audio-service/media/controls/repaint-on-resize.html [ Failure Pass ]
 
 # Sheriff failures 2018-02-21
 crbug.com/814585 [ Linux ] fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html [ Pass Failure ]
@@ -5421,7 +5475,9 @@
 crbug.com/807110 external/wpt/media-source/mediasource-sequencemode-append-buffer.html [ Failure Pass ]
 crbug.com/807110 external/wpt/media-source/mediasource-sourcebuffer-mode-timestamps.html [ Failure Pass ]
 crbug.com/794338 media/video-rotation.html [ Failure Pass ]
+crbug.com/794338 virtual/audio-service/media/video-rotation.html [ Failure Pass ]
 crbug.com/811605 media/video-poster-after-loadedmetadata.html [ Failure Pass ]
+crbug.com/811605 virtual/audio-service/media/video-poster-after-loadedmetadata.html [ Failure Pass ]
 
 crbug.com/813704 http/tests/images/png-partial-load-as-document.html [ Failure Pass ]
 
@@ -5456,6 +5512,8 @@
 # Sheriff 2018-03-22
 crbug.com/824775 [ Win ] media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
 crbug.com/824775 [ Mac ] media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
+crbug.com/824775 [ Win ] virtual/audio-service/media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
+crbug.com/824775 [ Mac ] virtual/audio-service/media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
 crbug.com/824848 [ Linux ] external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.html [ Pass Failure ]
 crbug.com/824848 [ Mac ] external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.html [ Pass Failure ]
 crbug.com/824848 [ Win ] external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.html [ Pass Failure ]
@@ -5476,7 +5534,9 @@
 
 # Sheriff 2018-03-26
 crbug.com/825733 [ Win ] media/color-profile-video-seek-filter.html [ Pass Timeout Failure ]
+crbug.com/825733 [ Win ] virtual/audio-service/media/color-profile-video-seek-filter.html [ Pass Timeout Failure ]
 crbug.com/754986 media/video-transformed.html [ Pass Failure ]
+crbug.com/754986 virtual/audio-service/media/video-transformed.html [ Pass Failure ]
 
 # Sheriff 2018-03-29
 crbug.com/827209 [ Win ] fast/events/middleClickAutoscroll-latching.html [ Pass Timeout Failure ]
@@ -5517,6 +5577,10 @@
 crbug.com/833658 [ Linux ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 crbug.com/833658 [ Win ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 crbug.com/833658 [ Mac ] media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
+crbug.com/833655 [ Linux ] virtual/audio-service/media/controls/closed-captions-dynamic-update.html [ Skip ]
+crbug.com/833658 [ Linux ] virtual/audio-service/media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
+crbug.com/833658 [ Win ] virtual/audio-service/media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
+crbug.com/833658 [ Mac ] virtual/audio-service/media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 
 # Sheriff 2018-04-23
 crbug.com/833331 [ Win10 ] inspector-protocol/page/pageNavigateToFragment.js [ Pass Failure ]
@@ -5806,6 +5870,7 @@
 # Sheriff 2018-11-26
 crbug.com/908276 [ Mac ] external/wpt/webstorage/storage_setitem.html [ Pass Timeout ]
 crbug.com/908347 media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
+crbug.com/908347 virtual/audio-service/media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ]
 
 # Sheriff 2018-11-29
 crbug.com/910139 custom-elements/form-submission-file.html [ Crash Pass ]
@@ -5826,6 +5891,7 @@
 
 # Sheriff 2018-12-13
 crbug.com/910452 media/controls/buttons-after-reset.html [ Pass Failure ]
+crbug.com/910452 virtual/audio-service/media/controls/buttons-after-reset.html [ Pass Failure ]
 crbug.com/914782 [ Linux ] fast/scrolling/no-hover-during-scroll.html [ Pass Failure ]
 
 # Sheriff 2018-12-14
@@ -5903,6 +5969,9 @@
 crbug.com/922951 media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html [ Skip ]
 crbug.com/922951 media/controls/overflow-menu-hide-on-click-outside.html [ Skip ]
 crbug.com/922951 media/controls/overflow-menu-toggle-class-for-animation.html [ Skip ]
+crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-hide-on-click-outside-stoppropagation.html [ Skip ]
+crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-hide-on-click-outside.html [ Skip ]
+crbug.com/922951 virtual/audio-service/media/controls/overflow-menu-toggle-class-for-animation.html [ Skip ]
 crbug.com/922951 scrollbars/resize-scales-with-dpi-150.html [ Skip ]
 crbug.com/922951 svg/animations/dynamic-modify-transform-without-baseval.html [ Skip ]
 crbug.com/922951 svg/animations/target-condition-crash.html [ Skip ]
@@ -5986,6 +6055,7 @@
 
 # Sheriff 2019-02-12
 crbug.com/931349 [ Mac ] media/video-played-ranges-1.html [ Failure Timeout Pass ]
+crbug.com/931349 [ Mac ] virtual/audio-service/media/video-played-ranges-1.html [ Failure Timeout Pass ]
 
 # Sheriff 2019-02-13
 crbug.com/931646 [ Win7 ] http/tests/preload/meta-viewport-link-headers-imagesrcset.html [ Failure Pass ]
@@ -6023,6 +6093,7 @@
 # Sheriff 2019-02-26
 crbug.com/936083 external/wpt/import-maps/builtin-import-scheme.tentative.html [ Failure Pass ]
 crbug.com/936165 media/autoplay-muted.html [ Timeout Pass ]
+crbug.com/936165 virtual/audio-service/media/autoplay-muted.html [ Timeout Pass ]
 
 # Sheriff 2019-02-27
 crbug.com/936279 external/wpt/import-maps/fallback-disallowed.sub.tentative.html [ Failure Pass Timeout ]
@@ -6055,6 +6126,7 @@
 
 # Caused a revert of a good change.
 crbug.com/931533 media/video-played-collapse.html [ Pass Failure ]
+crbug.com/931533 virtual/audio-service/media/video-played-collapse.html [ Pass Failure ]
 
 # Test was blocking WPT importer
 crbug.com/941471 external/wpt/css/css-transforms/transform-flattening-001.html [ Pass Failure Crash ]
@@ -6112,6 +6184,7 @@
 crbug.com/919789 images/image-zoom-to-25.html [ Pass Timeout ]
 crbug.com/919789 images/image-zoom-to-500.html [ Pass Timeout ]
 crbug.com/919789 media/controls/overflow-menu-hide-on-resize.html [ Pass Timeout ]
+crbug.com/919789 virtual/audio-service/media/controls/overflow-menu-hide-on-resize.html [ Pass Timeout ]
 crbug.com/919789 [ Linux Mac10.13 ] paint/invalidation/resize-iframe-text.html [ Pass Timeout ]
 crbug.com/919789 paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint.html [ Pass Timeout ]
 crbug.com/919789 paint/invalidation/window-resize/ [ Pass Timeout ]
@@ -6238,9 +6311,14 @@
 crbug.com/963141 media/video-object-fit-change.html [ Pass Failure ]
 crbug.com/963141 [ Mac Win ] media/controls/video-overlay-cast-light-rendering.html [ Pass Failure ]
 crbug.com/963141 [ Mac ] media/video-aspect-ratio.html [ Pass Failure ]
+crbug.com/963141 [ Mac Win ] virtual/audio-service/media/video-object-fit.html [ Pass Failure ]
+crbug.com/963141 virtual/audio-service/media/video-object-fit-change.html [ Pass Failure ]
+crbug.com/963141 [ Mac Win ] virtual/audio-service/media/controls/video-overlay-cast-light-rendering.html [ Pass Failure ]
+crbug.com/963141 [ Mac ] virtual/audio-service/media/video-aspect-ratio.html [ Pass Failure ]
 
 # Sheriff 2019-05-16
 crbug.com/963141 [ Linux ] media/video-object-fit.html [ Pass Failure ]
+crbug.com/963141 [ Linux ] virtual/audio-service/media/video-object-fit.html [ Pass Failure ]
 crbug.com/963740 compositing/video-frame-size-change.html [ Pass Failure ]
 
 # Sheriff 2019-05-17
@@ -6257,6 +6335,7 @@
 crbug.com/963739 [ Fuchsia ] synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Timeout ]
 crbug.com/964239 external/wpt/css/css-scroll-snap/scroll-margin.html [ Pass Failure ]
 crbug.com/965389 [ Mac ] media/track/track-cue-rendering-position-auto.html [ Pass Failure ]
+crbug.com/965389 [ Mac ] virtual/audio-service/media/track/track-cue-rendering-position-auto.html [ Pass Failure ]
 
 # Sheriff 2019-05-27
 crbug.com/942411 [ Win ] http/tests/devtools/network/network-search.js [ Pass Timeout ]
@@ -6279,8 +6358,10 @@
 
 # Sheriff 2019-06-05
 crbug.com/971259 media/controls/volumechange-stopimmediatepropagation.html [ Pass Failure ]
+crbug.com/971259 virtual/audio-service/media/controls/volumechange-stopimmediatepropagation.html [ Pass Failure ]
 crbug.com/971262 http/tests/devtools/profiler/live-line-level-heap-profile.js [ Pass Timeout ]
 crbug.com/971319 [ Mac ] media/audio-garbage-collect.html [ Pass Timeout ]
+crbug.com/971319 [ Mac ] virtual/audio-service/media/audio-garbage-collect.html [ Pass Timeout ]
 
 # Sheriff 2019-06-06
 crbug.com/971590 fast/dom/timer-throttling-out-of-view-cross-origin-page.html [ Pass Failure ]
@@ -6391,11 +6472,15 @@
 crbug.com/986477 [ Win ] external/wpt/cookies/path/match.html [ Pass Timeout ]
 crbug.com/986477 [ Win ] virtual/samesite-by-default-cookies/external/wpt/cookies/path/match.html [ Pass Timeout ]
 
+
+crbug.com/987269 [ Linux ] virtual/audio-service/http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-disabled.html [ Pass Failure ]
+crbug.com/987269 [ Linux ] virtual/audio-service/http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-header.html [ Pass Failure ]
 # Sheriff 2019-07-24
 crbug.com/987108 [ Mac ] fast/forms/select/disabled-select-change-index.html [ Failure ]
 crbug.com/987132 [ Mac ] fast/forms/select/option-strip-whitespace.html [ Failure ]
 crbug.com/986282 external/wpt/client-hints/accept-ch-lifetime.tentative.https.html [ Pass Failure ]
 crbug.com/987138 [ Linux Win ] media/controls/doubletap-to-jump-forwards.html [ Pass Timeout ]
+crbug.com/987138 [ Linux Win ] virtual/audio-service/media/controls/doubletap-to-jump-forwards.html [ Pass Timeout ]
 
 # Sheriff 2019-07-26
 crbug.com/835943 [ Debug ] http/tests/appcache/non-html.xhtml [ Crash Pass ]
@@ -6466,3 +6551,6 @@
 
 # Sheriff 2019-08-05
 crbug.com/981522 [ Linux ] external/wpt/svg/animations/correct-events-for-short-animations-with-syncbases.html [ Pass Failure Timeout ]
+crbug.com/991243 [ Linux ] external/wpt/workers/semantics/multiple-workers/003.html [ Pass Timeout ]
+crbug.com/991243 [ Linux ] virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Pass Timeout ]
+crbug.com/991243 [ Linux ] virtual/not-omt-sw-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 582cdaf..2aef67e 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1139,11 +1139,6 @@
     "args": ["--enable-blink-features=ForcedColors"]
   },
   {
-    "prefix": "forced-colors",
-    "base": "fast/css/forced-colors-mode",
-    "args": ["--force-high-contrast", "--enable-blink-features=ForcedColors"]
-  },
-  {
     "prefix": "force-defer-script",
     "base": "defer-script",
     "args": ["--enable-blink-features=ForceDeferScriptIntervention"]
@@ -1224,5 +1219,20 @@
     "prefix": "conditional-appcache-delay",
     "base": "http/tests/loading/appcache-delay",
     "args": ["--enable-features=VerifyHTMLFetchedFromAppCacheBeforeDelay"]
+  },
+  {
+    "prefix": "audio-service",
+    "base": "http/tests/media",
+    "args": ["--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox"]
+  },
+  {
+    "prefix": "audio-service",
+    "base": "media",
+    "args": ["--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox"]
+  },
+  {
+    "prefix": "audio-service",
+    "base": "external/wpt/mediacapture-streams",
+    "args": ["--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox"]
   }
 ]
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 0ffc1e3..f0cc716 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
@@ -174997,6 +174997,9 @@
    "webaudio/the-audio-api/the-audioparam-interface/retrospective-test.js": [
     []
    ],
+   "webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.headers": [
+    []
+   ],
    "webaudio/the-audio-api/the-audioworklet-interface/processors/active-processing.js": [
     []
    ],
@@ -287448,6 +287451,60 @@
      {}
     ]
    ],
+   "svg/animations/discard-on-discard.html": [
+    [
+     "svg/animations/discard-on-discard.html",
+     {}
+    ]
+   ],
+   "svg/animations/force-use-shadow-tree-recreation-while-animating.html": [
+    [
+     "svg/animations/force-use-shadow-tree-recreation-while-animating.html",
+     {}
+    ]
+   ],
+   "svg/animations/multiple-animations-ending.html": [
+    [
+     "svg/animations/multiple-animations-ending.html",
+     {}
+    ]
+   ],
+   "svg/animations/multiple-animations-fill-freeze.html": [
+    [
+     "svg/animations/multiple-animations-fill-freeze.html",
+     {}
+    ]
+   ],
+   "svg/animations/multiple-begin-additive-animation.html": [
+    [
+     "svg/animations/multiple-begin-additive-animation.html",
+     {}
+    ]
+   ],
+   "svg/animations/non-additive-type-by-animation.html": [
+    [
+     "svg/animations/non-additive-type-by-animation.html",
+     {}
+    ]
+   ],
+   "svg/animations/non-additive-type-from-by-animation.html": [
+    [
+     "svg/animations/non-additive-type-from-by-animation.html",
+     {}
+    ]
+   ],
+   "svg/animations/remove-animation-element-while-animation-is-running.html": [
+    [
+     "svg/animations/remove-animation-element-while-animation-is-running.html",
+     {}
+    ]
+   ],
+   "svg/animations/repeatn-remove-add-animation.html": [
+    [
+     "svg/animations/repeatn-remove-add-animation.html",
+     {}
+    ]
+   ],
    "svg/animations/scripted/end-element-on-inactive-element.svg": [
     [
      "svg/animations/scripted/end-element-on-inactive-element.svg",
@@ -287460,6 +287517,90 @@
      {}
     ]
    ],
+   "svg/animations/single-values-animation.html": [
+    [
+     "svg/animations/single-values-animation.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-deg-to-grad.html": [
+    [
+     "svg/animations/svgangle-animation-deg-to-grad.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-deg-to-rad.html": [
+    [
+     "svg/animations/svgangle-animation-deg-to-rad.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-grad-to-deg.html": [
+    [
+     "svg/animations/svgangle-animation-grad-to-deg.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-grad-to-rad.html": [
+    [
+     "svg/animations/svgangle-animation-grad-to-rad.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-rad-to-deg.html": [
+    [
+     "svg/animations/svgangle-animation-rad-to-deg.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgangle-animation-rad-to-grad.html": [
+    [
+     "svg/animations/svgangle-animation-rad-to-grad.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgboolean-animation-1.html": [
+    [
+     "svg/animations/svgboolean-animation-1.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-1.html": [
+    [
+     "svg/animations/svgenum-animation-1.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-10.html": [
+    [
+     "svg/animations/svgenum-animation-10.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-11.html": [
+    [
+     "svg/animations/svgenum-animation-11.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-12.html": [
+    [
+     "svg/animations/svgenum-animation-12.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-13.html": [
+    [
+     "svg/animations/svgenum-animation-13.html",
+     {}
+    ]
+   ],
+   "svg/animations/svgenum-animation-2.html": [
+    [
+     "svg/animations/svgenum-animation-2.html",
+     {}
+    ]
+   ],
    "svg/animations/svgenum-animation-3.html": [
     [
      "svg/animations/svgenum-animation-3.html",
@@ -320477,7 +320618,7 @@
    "support"
   ],
   "README.md": [
-   "f89061f1674a7008b016031ffae627cfe6795515",
+   "5054889dc167880a75bc1b9bd3a49abed666b78f",
    "support"
   ],
   "WebCryptoAPI/META.yml": [
@@ -326905,7 +327046,7 @@
    "support"
   ],
   "cookies/http-state/resources/test-files/0002-test": [
-   "a3eaff03ba38303a243a964f2e3bfbeb53533a92",
+   "94a71188114290a761eef397f42412e13e7909b7",
    "support"
   ],
   "cookies/http-state/resources/test-files/0003-expected": [
@@ -327561,7 +327702,7 @@
    "support"
   ],
   "cookies/http-state/resources/test-files/comma0006-test": [
-   "a3eaff03ba38303a243a964f2e3bfbeb53533a92",
+   "94a71188114290a761eef397f42412e13e7909b7",
    "support"
   ],
   "cookies/http-state/resources/test-files/comma0007-expected": [
@@ -327569,7 +327710,7 @@
    "support"
   ],
   "cookies/http-state/resources/test-files/comma0007-test": [
-   "29fb0a2695d4fb71115ac1fc6a220216243f8dec",
+   "6ca8efc711ba1e4d2a42679df8b53db580cc28a1",
    "support"
   ],
   "cookies/http-state/resources/test-files/disabled-chromium0020-expected": [
@@ -365645,11 +365786,11 @@
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-columns-invalid.html": [
-   "e7a965f34ad35f32589b6fc895d65946812e0749",
+   "40b6059a7e8b564a4aef5393a7be77cbaa1ff4a2",
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-columns-valid.html": [
-   "ba1f5f60d657ebd2629c94b90c971bb081ea7917",
+   "e26d085a2d95c2ad06a77b25ca2ab0b90c294fc6",
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-flow-computed-expected.txt": [
@@ -365677,11 +365818,11 @@
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-rows-invalid.html": [
-   "7fceaa0f1639494847cc06a7f93876992d620b3c",
+   "4111e2563365579b3810c701a782df54dce3c61e",
    "testharness"
   ],
   "css/css-grid/parsing/grid-auto-rows-valid.html": [
-   "cf63e2b7d52a6fffc5577bc55e37dfd6aa0cd5b8",
+   "d4dcdb12b177cf97c3aa030cbb19c2ce2ae6d25d",
    "testharness"
   ],
   "css/css-grid/parsing/grid-template-areas-computed.html": [
@@ -475632,6 +475773,42 @@
    "96552df4a7c35a264722848a17573e4278bddbbf",
    "testharness"
   ],
+  "svg/animations/discard-on-discard.html": [
+   "4a6b9f9368dcb020120f502e4528860beb5f14c6",
+   "testharness"
+  ],
+  "svg/animations/force-use-shadow-tree-recreation-while-animating.html": [
+   "7a60e0280baa67ef8731b7bdc737788d326c3c24",
+   "testharness"
+  ],
+  "svg/animations/multiple-animations-ending.html": [
+   "a9b7853bb0ed49a11af24d020766248ebd7d4bbe",
+   "testharness"
+  ],
+  "svg/animations/multiple-animations-fill-freeze.html": [
+   "d4a71dcac286f5bcd97b3b3ce6642e58e75f3d54",
+   "testharness"
+  ],
+  "svg/animations/multiple-begin-additive-animation.html": [
+   "9e75bdf17a449df09e72986c95bd3493e56f9221",
+   "testharness"
+  ],
+  "svg/animations/non-additive-type-by-animation.html": [
+   "b596f735446a61592774b89569d80e776f8a39be",
+   "testharness"
+  ],
+  "svg/animations/non-additive-type-from-by-animation.html": [
+   "e974e38177526e2e4bd8344712c37b00dc2e2bda",
+   "testharness"
+  ],
+  "svg/animations/remove-animation-element-while-animation-is-running.html": [
+   "764d25b69f158e028d8ec9fe14e1c43840d00925",
+   "testharness"
+  ],
+  "svg/animations/repeatn-remove-add-animation.html": [
+   "f192d27dfbd99352b6730b45be2a98f097d88f56",
+   "testharness"
+  ],
   "svg/animations/scripted/end-element-on-inactive-element.svg": [
    "34be9b9781f707d488e284c3285b82009557366b",
    "testharness"
@@ -475640,6 +475817,62 @@
    "86a0a40fa2de116c5b2076641180b24688d56f9b",
    "testharness"
   ],
+  "svg/animations/single-values-animation.html": [
+   "40aa3461866cf4c32316d86216dcfe4298be7718",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-deg-to-grad.html": [
+   "7a8146336879a8dccaf8e663d7556e408a8e0048",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-deg-to-rad.html": [
+   "b8ad7300cfa03083409b99ab40299ef6be9ac7dd",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-grad-to-deg.html": [
+   "dd5822db8122bf9cf327967faf4afaefbe86805b",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-grad-to-rad.html": [
+   "28bef66d0ff3372f255b3383cb2bec790d0281cb",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-rad-to-deg.html": [
+   "412f384cc7b1b9c85ebc72eabc3648b9c0a164d7",
+   "testharness"
+  ],
+  "svg/animations/svgangle-animation-rad-to-grad.html": [
+   "d27c052be2e1a45afe9a05a9939b4aea72db89a8",
+   "testharness"
+  ],
+  "svg/animations/svgboolean-animation-1.html": [
+   "3e3de673a3c34432b85dd8f630acaeb1f5de93c6",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-1.html": [
+   "05b75e9ad81d5e979834ef25a42ab9f3a42f1d12",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-10.html": [
+   "e645ea5066fcb24dc90e3f026be57ac5b9f5e175",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-11.html": [
+   "ebf8409f2e08a05748d588bb58c0d3592cb378fb",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-12.html": [
+   "bd60bbc20c42c8000d3d8459d47c03775c7211be",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-13.html": [
+   "c6dbb0c44dece98c0b4b63e2733636631e4648f3",
+   "testharness"
+  ],
+  "svg/animations/svgenum-animation-2.html": [
+   "a1e27a5ef3e60003dedb3440ef4e9b972f696ccd",
+   "testharness"
+  ],
   "svg/animations/svgenum-animation-3.html": [
    "5ed9f5aa8819510f8a7701e5edb7d00fb716aa70",
    "testharness"
@@ -485817,7 +486050,7 @@
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html": [
-   "4f9a998c6ded83d564cbb1f8dc3e1edf0de3efb7",
+   "20780d94b730acf18f4d6ca93fe4abff1a6111db",
    "testharness"
   ],
   "webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-getChannelData.html": [
@@ -486109,9 +486342,13 @@
    "testharness"
   ],
   "webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html": [
-   "8194d1977ad452390efb870197057bcf48fad499",
+   "a5dd004981157c8791c391fbb71e4aa2620559c8",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.headers": [
+   "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
+   "support"
+  ],
   "webaudio/the-audio-api/the-audioworklet-interface/audioworklet-suspend.https.html": [
    "89d361d22f35ffc6e7fbff6abdfc60c57a1d8ebb",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/README.md b/third_party/blink/web_tests/external/wpt/README.md
index f89061f..5054889 100644
--- a/third_party/blink/web_tests/external/wpt/README.md
+++ b/third_party/blink/web_tests/external/wpt/README.md
@@ -89,6 +89,11 @@
 http://web-platform.test:8000/<br>
 https://web-platform.test:8443/ *
 
+To use the web-based runner point your browser to:
+
+http://web-platform.test:8000/tools/runner/index.html <br>
+https://web-platform.test:8443/tools/runner/index.html *
+
 \**See [Trusting Root CA](#trusting-root-ca)*
 
 Running Tests Automatically
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/0002-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/0002-test
index a3eaff0..94a71188 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/0002-test
+++ b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/0002-test
@@ -1 +1 @@
-Set-Cookie: foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT
+Set-Cookie: foo=bar; Expires=Fri, 01 Jan 2038 00:00:00 GMT
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0006-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0006-test
index a3eaff0..94a71188 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0006-test
+++ b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0006-test
@@ -1 +1 @@
-Set-Cookie: foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT
+Set-Cookie: foo=bar; Expires=Fri, 01 Jan 2038 00:00:00 GMT
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0007-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0007-test
index 29fb0a2..6ca8efc 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0007-test
+++ b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/comma0007-test
@@ -1 +1 @@
-Set-Cookie: foo=bar; Expires=Fri 07 Aug 2019 08:04:19 GMT, baz=qux
+Set-Cookie: foo=bar; Expires=Fri 01 Jan 2038 00:00:00 GMT, baz=qux
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-name-computed.html b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-name-computed.html
new file mode 100644
index 0000000..a20aa7d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-name-computed.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Animations: getComputedStyle().animationName</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations/#propdef-animation-name">
+<meta name="assert" content="animation-name computed value is as specified.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("animation-name", 'none');
+
+test_computed_value("animation-name", 'foo');
+test_computed_value("animation-name", 'Both');
+test_computed_value("animation-name", 'ease-in');
+test_computed_value("animation-name", 'infinite');
+test_computed_value("animation-name", 'paused');
+test_computed_value("animation-name", 'first, second, third');
+
+// TODO: Test strings, after https://github.com/w3c/csswg-drafts/issues/2435
+// is resolved.
+// Examples that need testing either here or in animation-name-invalid.html :
+// '"Initial"', '"initial"', '"None"', '"Default"', '" x "', "1", '" "', '""',
+// '"multi word string"', '"---\\22---"'
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/inheritance-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance-expected.txt
index bb0e077..c21b16bc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/inheritance-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance-expected.txt
@@ -1,4 +1,8 @@
 This is a testharness.js-based test.
+PASS Property clear has initial value none
+PASS Property clear does not inherit
+PASS Property float has initial value none
+PASS Property float does not inherit
 PASS Property margin-bottom has initial value 0px
 PASS Property margin-bottom does not inherit
 PASS Property margin-left has initial value 0px
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html
index 5047b8b..22443bf9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/inheritance.html
@@ -4,6 +4,7 @@
 <meta charset="utf-8">
 <title>Inheritance of CSS Box Model properties</title>
 <link rel="help" href="https://drafts.csswg.org/css-box-3/#property-index">
+<link rel="help" href="https://www.w3.org/TR/CSS2/">
 <meta name="assert" content="Properties do not inherit.">
 <meta name="assert" content="length-percentage properties have initial value 0.">
 <script src="/resources/testharness.js"></script>
@@ -15,6 +16,9 @@
   <div id="target"></div>
 </div>
 <script>
+assert_not_inherited('clear', 'none', 'right');
+assert_not_inherited('float', 'none', 'right');
+
 assert_not_inherited('margin-bottom', '0px', '10px');
 assert_not_inherited('margin-left', '0px', '10px');
 assert_not_inherited('margin-right', '0px', '10px');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html
index e7a965f3..40b6059 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html
@@ -32,6 +32,7 @@
 // <track-size>+
 test_invalid_value("grid-auto-columns", "2em / 3em");
 test_invalid_value("grid-auto-columns", "auto, 10%");
+test_invalid_value("grid-auto-rows", "1px [a] 1px");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-valid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-valid.html
index ba1f5f60..e26d085 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-valid.html
@@ -22,6 +22,7 @@
 test_valid_value("grid-auto-columns", "min-content");
 test_valid_value("grid-auto-columns", "max-content");
 test_valid_value("grid-auto-columns", "auto");
+test_valid_value("grid-auto-columns", "auto /**/", "auto");
 
 // minmax( <inflexible-breadth> , <track-breadth> )
 // <inflexible-breadth> = <length-percentage> | min-content | max-content | auto
@@ -47,6 +48,8 @@
 test_valid_value("grid-auto-columns", "fit-content(0px)");
 
 // <track-size>+
+test_valid_value("grid-auto-columns", "auto auto");
+test_valid_value("grid-auto-columns", "auto 10px");
 test_valid_value("grid-auto-columns", "1px 2px 3px 0px");
 test_valid_value("grid-auto-columns", "fit-content(1px) minmax(2px, 3px) 4px");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html
index 7fceaa0..4111e25 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html
@@ -31,6 +31,7 @@
 // <track-size>+
 test_invalid_value("grid-auto-rows", "2em / 3em");
 test_invalid_value("grid-auto-rows", "auto, 10%");
+test_invalid_value("grid-auto-rows", "1px [a] 1px");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-valid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-valid.html
index cf63e2b7..d4dcdb1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-valid.html
@@ -22,6 +22,7 @@
 test_valid_value("grid-auto-rows", "min-content");
 test_valid_value("grid-auto-rows", "max-content");
 test_valid_value("grid-auto-rows", "auto");
+test_valid_value("grid-auto-rows", "auto /**/", "auto");
 
 // minmax( <inflexible-breadth> , <track-breadth> )
 // <inflexible-breadth> = <length-percentage> | min-content | max-content | auto
@@ -47,6 +48,8 @@
 test_valid_value("grid-auto-rows", "fit-content(0px)");
 
 // <track-size>+
+test_valid_value("grid-auto-rows", "auto auto");
+test_valid_value("grid-auto-rows", "auto 10px");
 test_valid_value("grid-auto-rows", "1px 2px 3px 0px");
 test_valid_value("grid-auto-rows", "fit-content(1px) minmax(2px, 3px) 4px");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html
index 4f9a998..20780d94 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html
@@ -149,22 +149,20 @@
           buffer.copyFromChannel(x, 3);
         }, '7: buffer.copyFromChannel(x, 3)').throw(DOMException, 'IndexSizeError');
 
-        if (window.SharedArrayBuffer) {
-          let shared_buffer = new Float32Array(new SharedArrayBuffer(32));
-          should(
-              () => {
-                buffer.copyFromChannel(shared_buffer, 0);
-              },
-              '8: buffer.copyFromChannel(SharedArrayBuffer view, 0)')
-              .throw(TypeError);
+        let shared_buffer = new Float32Array(new SharedArrayBuffer(32));
+        should(
+            () => {
+              buffer.copyFromChannel(shared_buffer, 0);
+            },
+            '8: buffer.copyFromChannel(SharedArrayBuffer view, 0)')
+            .throw(TypeError);
 
-          should(
-              () => {
-                buffer.copyFromChannel(shared_buffer, 0, 0);
-              },
-              '9: buffer.copyFromChannel(SharedArrayBuffer view, 0, 0)')
-              .throw(TypeError);
-        }
+        should(
+            () => {
+              buffer.copyFromChannel(shared_buffer, 0, 0);
+            },
+            '9: buffer.copyFromChannel(SharedArrayBuffer view, 0, 0)')
+            .throw(TypeError);
 
         task.done();
       });
@@ -204,22 +202,20 @@
           buffer.copyToChannel(x, 3);
         }, '6: buffer.copyToChannel(x, 3)').throw(DOMException, 'IndexSizeError');
 
-        if (window.SharedArrayBuffer) {
-          let shared_buffer = new Float32Array(new SharedArrayBuffer(32));
-          should(
-              () => {
-                buffer.copyToChannel(shared_buffer, 0);
-              },
-              '7: buffer.copyToChannel(SharedArrayBuffer view, 0)')
-              .throw(TypeError);
+        let shared_buffer = new Float32Array(new SharedArrayBuffer(32));
+        should(
+            () => {
+              buffer.copyToChannel(shared_buffer, 0);
+            },
+            '7: buffer.copyToChannel(SharedArrayBuffer view, 0)')
+            .throw(TypeError);
 
-          should(
-              () => {
-                buffer.copyToChannel(shared_buffer, 0, 0);
-              },
-              '8: buffer.copyToChannel(SharedArrayBuffer view, 0, 0)')
-              .throw(TypeError);
-        }
+        should(
+            () => {
+              buffer.copyToChannel(shared_buffer, 0, 0);
+            },
+            '8: buffer.copyToChannel(SharedArrayBuffer view, 0, 0)')
+            .throw(TypeError);
 
         task.done();
       });
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html
index 8194d197..a5dd004 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html
@@ -16,65 +16,56 @@
 
       let filePath = 'processors/sharedarraybuffer-processor.js';
 
-      if (window.SharedArrayBuffer) {
-        audit.define(
-            'Test postMessage from AudioWorkletProcessor to AudioWorkletNode',
-            (task, should) => {
-              let workletNode =
-                  new AudioWorkletNode(context, 'sharedarraybuffer-processor');
-
-              // After it is created, the worklet will send a new
-              // SharedArrayBuffer to the main thread.
-              //
-              // The worklet will then wait to receive a message from the main
-              // thread.
-              //
-              // When it receives the message, it will check whether it is a
-              // SharedArrayBuffer, and send this information back to the main
-              // thread.
-
-              workletNode.port.onmessage = (event) => {
-                let data = event.data;
-                switch (data.state) {
-                  case 'created':
-                    should(
-                        data.sab instanceof SharedArrayBuffer,
-                        'event.data.sab from worklet is an instance of SharedArrayBuffer')
-                        .beTrue();
-
-                    // Send a SharedArrayBuffer back to the worklet.
-                    let sab = new SharedArrayBuffer(8);
-                    workletNode.port.postMessage(sab);
-                    break;
-
-                  case 'received message':
-                    should(data.isSab, 'event.data from main thread is an instance of SharedArrayBuffer')
-                        .beTrue();
-                    task.done();
-                    break;
-
-                  default:
-                    should(false,
-                           `Got unexpected message from worklet: ${data.state}`)
-                        .beTrue();
-                    task.done();
-                    break;
-                }
-              };
-
-              workletNode.port.onmessageerror = (event) => {
-                should(false, 'Got messageerror from worklet').beTrue();
-                task.done();
-              };
-            });
-      } else {
-        // NOTE(binji): SharedArrayBuffer is only enabled where we have site
-        // isolation.
-        audit.define('Skipping test because SharedArrayBuffer is not defined',
+      audit.define(
+          'Test postMessage from AudioWorkletProcessor to AudioWorkletNode',
           (task, should) => {
-            task.done();
+            let workletNode =
+                new AudioWorkletNode(context, 'sharedarraybuffer-processor');
+
+            // After it is created, the worklet will send a new
+            // SharedArrayBuffer to the main thread.
+            //
+            // The worklet will then wait to receive a message from the main
+            // thread.
+            //
+            // When it receives the message, it will check whether it is a
+            // SharedArrayBuffer, and send this information back to the main
+            // thread.
+
+            workletNode.port.onmessage = (event) => {
+              let data = event.data;
+              switch (data.state) {
+                case 'created':
+                  should(
+                      data.sab instanceof SharedArrayBuffer,
+                      'event.data.sab from worklet is an instance of SharedArrayBuffer')
+                      .beTrue();
+
+                  // Send a SharedArrayBuffer back to the worklet.
+                  let sab = new SharedArrayBuffer(8);
+                  workletNode.port.postMessage(sab);
+                  break;
+
+                case 'received message':
+                  should(data.isSab, 'event.data from main thread is an instance of SharedArrayBuffer')
+                      .beTrue();
+                  task.done();
+                  break;
+
+                default:
+                  should(false,
+                         `Got unexpected message from worklet: ${data.state}`)
+                      .beTrue();
+                  task.done();
+                  break;
+              }
+            };
+
+            workletNode.port.onmessageerror = (event) => {
+              should(false, 'Got messageerror from worklet').beTrue();
+              task.done();
+            };
           });
-      }
 
       context.audioWorklet.addModule(filePath).then(() => {
         audit.run();
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.headers b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.headers
new file mode 100644
index 0000000..63b60e4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html
deleted file mode 100644
index d04c1bc0..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  table {
-    border-collapse: collapse;
-  }
-
-  td, th {
-    border: 1px solid;
-    border-bottom-color: black;
-    border-left-color: purple;
-    border-right-color: orange;
-    border-top-color: green;
-    padding: 8px;
-    text-align: left;
-  }
-
-  tr:nth-child(even) {
-    background-color: blue;
-    color: red;
-  }
-</style>
-</head>
-<body>
-  <table>
-    <tr>
-      <th>Column1</th>
-      <th>Column2</th>
-      <th>Column3</th>
-    </tr>
-    <tr>
-      <td>Entry1</td>
-      <td>Entry1</td>
-      <td>Entry1</td>
-    </tr>
-    <tr>
-      <td>Entry2</td>
-      <td>Entry2</td>
-      <td>Entry2</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01.html
deleted file mode 100644
index c53078a..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-01.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<html>
-<title>Test forced colors mode on table styles</title>
-<link rel=match href=forced-colors-mode-01-expected.html>
-<style type="text/css">
-  table {
-    border-collapse: collapse;
-  }
-
-  td, th {
-    border: 1px solid;
-    border-bottom-color: black;
-    border-left-color: purple;
-    border-right-color: orange;
-    border-top-color: green;
-    padding: 8px;
-    text-align: left;
-  }
-
-  tr:nth-child(even) {
-    background-color: blue;
-    color: red;
-  }
-</style>
-
-<body>
-  <table>
-    <tr>
-      <th>Column1</th>
-      <th>Column2</th>
-      <th>Column3</th>
-    </tr>
-    <tr>
-      <td>Entry1</td>
-      <td>Entry1</td>
-      <td>Entry1</td>
-    </tr>
-    <tr>
-      <td>Entry2</td>
-      <td>Entry2</td>
-      <td>Entry2</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html
deleted file mode 100644
index 8705bd2..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  body {
-    background-color: lightblue;
-  }
-  #a {
-    background-color: lightgreen;
-    border: 25px solid green;
-    box-shadow: 2px 2px purple;
-    color: orange;
-    forced-color-adjust: auto;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px gray;
-    width: 300px;
-  }
-  #b {
-    background-color: lightgreen;
-    border: 25px solid green;
-    box-shadow: 2px 2px purple;
-    color: orange;
-    forced-color-adjust: none;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px gray;
-    width: 300px;
-  }
-</style>
-</head>
-<body>
-  <div id="a">
-    The colors and shadows of this text and text box should be overridden when in
-    forced colors mode (forced-color-adjust is set to auto.)
-  </div>
-  <div id="b">
-    The colors and shadows of this text and text box should NOT be overridden when in
-    forced colors mode (forced-color-adjust is set to none.)
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02.html
deleted file mode 100644
index e7cfcd5c..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-02.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - style overrides for text.</title>
-<link rel=match href=forced-colors-mode-02-expected.html>
-<style type="text/css">
-  body {
-    background-color: lightblue;
-  }
-  #a {
-    background-color: lightgreen;
-    border: 25px solid green;
-    box-shadow: 2px 2px purple;
-    color: orange;
-    forced-color-adjust: auto;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px gray;
-    width: 300px;
-  }
-  #b {
-    background-color: lightgreen;
-    border: 25px solid green;
-    box-shadow: 2px 2px purple;
-    color: orange;
-    forced-color-adjust: none;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px gray;
-    width: 300px;
-  }
-</style>
-</head>
-<body>
-  <div id="a">
-    The colors and shadows of this text and text box should be overridden when in
-    forced colors mode (forced-color-adjust is set to auto.)
-  </div>
-  <div id="b">
-    The colors and shadows of this text and text box should NOT be overridden when in
-    forced colors mode (forced-color-adjust is set to none.)
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt
deleted file mode 100644
index 5c7aaedd..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks that default highlighted text style does not get overridden in forced colors mode. assert_equals: expected "rgb(0, 0, 0)" but got "rgb(255, 165, 0)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03.html
deleted file mode 100644
index 3eab7297..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-03.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - highlighted text.</title>
-<style type="text/css">
-  #a {
-    color: orange;
-    forced-color-adjust: auto;
-  }
-  #b {
-    color: orange;
-    forced-color-adjust: none;
-  }
-</style>
-</head>
-<body>
-  <mark id="a">
-    This text should be black in forced colors mode because forced-color-adjust
-    is auto. The backgroud color should be yellow because the default
-    highlighted colors should not be overridden in forced colors mode.
-  </mark>
-  <mark id="b">
-    This text should be orange in forced colors mode because
-    forced-color-adjust is none. The backgroud color should be yellow because
-    the default highlighted colors should not be overridden in forced colors
-    mode.
-  </mark>
-</body>
-
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-  test(function(){
-    assert_equals(getComputedStyle(a).color, "rgb(0, 0, 0)");
-
-    assert_equals(getComputedStyle(b).color, "rgb(255, 165, 0)");
-
-    assert_equals(getComputedStyle(a).backgroundColor, "rgb(255, 255, 0)");
-
-    assert_equals(getComputedStyle(b).backgroundColor, "rgb(255, 255, 0)");
-
-  }, "Checks that default highlighted text style does not get overridden in forced colors mode.");
-</script>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt
deleted file mode 100644
index 5f26c685..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks hyperlinks are overridden in forced colors mode. assert_equals: expected "rgba(0, 0, 0, 0.18)" but got "rgb(0, 0, 255)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04.html
deleted file mode 100644
index 368bead..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-04.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - webkit-tap-highlight-color.</title>
-<style type="text/css">
-  a {
-    -webkit-tap-highlight-color: rgb(0, 0, 255);
-  }
-</style>
-</head>
-<body>
-  <p>
-    <a href="https://www.wikipedia.org" id="link">
-      This link color should be overridden when forced colors mode is enabled.
-    </a>
-  </p>
-</body>
-
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-  test(function(){
-    assert_equals(getComputedStyle(link).webkitTapHighlightColor, "rgba(0, 0, 0, 0.18)");
-  }, "Checks hyperlinks are overridden in forced colors mode.");
-</script>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html
deleted file mode 100644
index 18fbc57..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  a {
-    color: rgb(255, 0, 0);
-  }
-</style>
-</head>
-<body>
-  <p>
-    <a href="https://www.wikipedia.org" id="link">
-      This link color should be overridden when forced colors mode is enabled.
-    </a>
-  </p>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05.html
deleted file mode 100644
index 93fff5d..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-05.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - link color.</title>
-<link rel=match href=forced-colors-mode-05-expected.html>
-<style type="text/css">
-  a {
-    color: rgb(255, 0, 0);
-  }
-</style>
-</head>
-<body>
-  <p>
-    <a href="https://www.wikipedia.org" id="link">
-      This link color should be overridden when forced colors mode is enabled.
-    </a>
-  </p>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html
deleted file mode 100644
index ee78fcb..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<body>
-  <iframe src="forced-colors-mode-02-expected.html" width="500" height="500"></iframe>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06.html
deleted file mode 100644
index 7a2dd29e..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-06.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - iframe.
-  Test that styles are overridden inside iframes in forced colors mode.
-</title>
-<link rel=match href=forced-colors-mode-06-expected.html>
-<body>
-    <iframe src="forced-colors-mode-02.html" width="500" height="500"></iframe>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html
deleted file mode 100644
index 15623ae8..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-  p {
-    color: transparent;
-  }
-</style>
-<body>
-  <div style="background-color: rgb(0, 0, 255);">
-    <p>
-      The text color should be overridden, and the background color of the
-      div element should also be overridden in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: transparent;">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: rgba(0, 0, 0, 0);">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07.html
deleted file mode 100644
index b111479..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-07.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - transparent colors.</title>
-<link rel=match href=forced-colors-mode-07-expected.html>
-<style>
-  p {
-    color: transparent;
-  }
-</style>
-<body>
-  <div style="background-color: rgb(0, 0, 255);">
-    <p>
-      The text color should be overridden, and the background color of the
-      div element should also be overridden in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: transparent;">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: rgba(0, 0, 0, 0);">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html
deleted file mode 100644
index c9e55d4..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-  h1 {
-    outline-color: rgb(0, 0, 255);
-    outline-style: solid;
-    -webkit-column-count: 3;
-    -webkit-column-gap: 40px;
-    -webkit-column-rule-color: rgb(0, 0, 255);
-    -webkit-column-rule-style: solid;
-  }
-</style>
-</head>
-<body>
-  <h1>
-    The outline-color and column-rule-color should be blue when forced colors
-    mode is off and WindowText in forced colors mode.
-  </h1>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08.html
deleted file mode 100644
index 133f09ab..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-08.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Forced colors mode - outline and column color.</title>
-<link rel=match href=forced-colors-mode-08-expected.html>
-<style>
-  h1 {
-    outline-color: rgb(0, 0, 255);
-    outline-style: solid;
-    -webkit-column-count: 3;
-    -webkit-column-gap: 40px;
-    -webkit-column-rule-color: rgb(0, 0, 255);
-    -webkit-column-rule-style: solid;
-  }
-</style>
-</head>
-<body>
-  <h1>
-    The outline-color and column-rule-color should be blue when forced colors
-    mode is off and WindowText in forced colors mode.
-  </h1>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt
deleted file mode 100644
index c13cecb..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks that styles defined inside/outside forced-colors are overridden in forced colors mode. assert_not_equals: got disallowed value "rgb(0, 0, 255)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09.html
deleted file mode 100644
index 29b1a88..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-09.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>
-  Forced colors mode - forced-colors media query.
-  Tests that styles defined inside or outside a forced-colors media query are
-  overridden in forced colors mode.
-</title>
-<style type="text/css">
-  @media (forced-colors) {
-    p {
-      color: rgb(0, 0, 255);
-    }
-  }
-  p {
-    color: rgb(0, 0, 255);
-  }
-</style>
-</head>
-<body>
-  <p id="p">
-    This text should NOT be blue forced colors mode.
-  </p>
-</body>
-
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-  test(function() {
-    assert_not_equals(getComputedStyle(p).color, "rgb(0, 0, 255)");
-  }, "Checks that styles defined inside/outside forced-colors are overridden in forced colors mode.");
-  </script>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt
deleted file mode 100644
index dfa26792a..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks that styles defined inside/outside forced-colors are preserved in forced colors mode if forced-color-ajust is none. assert_equals: expected "rgb(0, 0, 255)" but got "rgb(0, 128, 0)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10.html
deleted file mode 100644
index 3d5dca9d..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-10.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>
-  Forced colors mode - forced-colors media query.
-  Tests that styles defined inside/outside forced-color media query
-  are preserved in forced colors mode if forced-color-adjust is none
-  and that the ordering of styles is preserved.
-</title>
-<style type="text/css">
-  p {
-    background-color: rgb(0, 128, 0);
-    color: rgb(0, 0, 255);
-    forced-color-adjust: none;
-  }
-  @media (forced-colors) {
-    p {
-      background-color: rgb(0, 0, 255);
-      color: rgb(0, 128, 0);
-    }
-  }
-</style>
-</head>
-<body>
-  <p id="p">
-    This text should be green in forced colors mode.
-  </p>
-</body>
-
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-  test(function() {
-    assert_equals(getComputedStyle(p).backgroundColor, "rgb(0, 0, 255)");
-    assert_equals(getComputedStyle(p).color, "rgb(0, 128, 0)");
-  }, "Checks that styles defined inside/outside forced-colors are preserved in forced colors mode if forced-color-ajust is none.");
-  </script>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt
deleted file mode 100644
index 06c5ac4..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Checks that styles defined in forced-colors are preserved in forced colors mode. assert_equals: expected "rgb(0, 0, 255)" but got "rgba(0, 0, 0, 0)"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11.html
deleted file mode 100644
index f38baf1..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-11.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>
-  Forced colors mode - forced-colors media query.
-  Tests that styles defined inside forced-color media query
-  are preserved in forced colors mode if forced-color-adjust
-  is none.
-</title>
-<style type="text/css">
-  @media (forced-colors: none) {
-    p {
-      background-color: rgb(255, 0, 0);
-      color: rgb(255, 255, 255);
-    }
-  }
-  @media (forced-colors: active) {
-    p {
-      background-color: rgb(0, 0, 255);
-      color: rgb(0, 128, 0);
-      forced-color-adjust: none;
-    }
-  }
-</style>
-</head>
-<body>
-  <p id="p">
-    This text should be green in forced colors mode.
-  </p>
-</body>
-
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-  test(function() {
-    assert_equals(getComputedStyle(p).backgroundColor, "rgb(0, 0, 255)");
-    assert_equals(getComputedStyle(p).color, "rgb(0, 128, 0)");
-  }, "Checks that styles defined in forced-colors are preserved in forced colors mode.");
-  </script>
-</html>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12-expected.txt
deleted file mode 100644
index 5945bee0..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-FAIL - "color" property for "box" element at 0s expected: rgb(0, 0, 0) but saw: rgb(255, 0, 0)
-FAIL - "color" property for "box" element at 0.5s expected: rgb(0, 0, 0) but saw: rgb(128, 64, 0)
-FAIL - "color" property for "box" element at 1s expected: rgb(0, 0, 0) but saw: rgb(255, 0, 0)
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html
deleted file mode 100644
index 16956ca..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<head>
-  <title>
-    Forced colors mode - animations.
-    Tests that animation colors are overridden in forced colors mode.
-  </title>
-  <style type="text/css">
-    #forcedtextcolor {
-      color: WindowText;
-      forced-color-adjust: none;
-    }
-    #box {
-      animation-duration: 1s;
-      animation-iteration-count: infinite;
-      animation-timing-function: linear;
-      animation-name: anim;
-    }
-    @keyframes anim {
-      from { color: red; }
-      to   { color: green; }
-    }
-  </style>
-</head>
-<body>
-  <div id="box"></div>
-  <p id="forcedtextcolor"></p>
-</body>
-
-<script src="../../../animations/resources/animation-test-helpers.js"></script>
-<script type="text/javascript" charset="utf-8">
-  var textcolor = getComputedStyle(forcedtextcolor).color;
-  const expectedValues = [
-    // [time, element-id, property, expected-value, tolerance]
-    [0.0, "box", "color", textcolor, 1],
-    [0.5, "box", "color", textcolor, 1],
-    [1.0, "box", "color", textcolor, 1],
-  ];
-  runAnimationTest(expectedValues);
-</script>
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13-expected.txt b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13-expected.txt
deleted file mode 100644
index f6555ac..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13-expected.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-PASS - "color" property for "target" element at 0.5s saw something close to: 128,0,0
-
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13.html
deleted file mode 100644
index a18ef2f..0000000
--- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-13.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!doctype html>
-<title>
-  Forced colors mode - transitions.
-  Tests that color transitions work in forced colors mode.
-  The only way to get transitions to work in forced colors mode is if
-  forced-color-adjust is none. Otherwise, the color will always be
-  overridden upon transition, and no transition will actually happen.
-</title>
-<style>
-  #target {
-    color: black;
-    font-size: 50px;
-    forced-color-adjust: none;
-    transition: all 1s linear;
-  }
-
-  #target.final { color: red; }
-</style>
-<script src="../../../animations/resources/animation-test-helpers.js" type="text/javascript"></script>
-<script>
-  const expectedValues = [
-    // [time, element-id, property, expected-value, tolerance]
-    [0.5, 'target', 'color', [128, 0, 0], 64]
-  ];
-
-  function setupTest()
-  {
-    document.getElementById('target').className = 'final';
-  }
-
-  runTransitionTest(expectedValues, setupTest);
-</script>
-<span id="target">filler text</span>
diff --git a/third_party/blink/web_tests/virtual/audio-service/external/wpt/mediacapture-streams/README.txt b/third_party/blink/web_tests/virtual/audio-service/external/wpt/mediacapture-streams/README.txt
new file mode 100644
index 0000000..53221e3
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/audio-service/external/wpt/mediacapture-streams/README.txt
@@ -0,0 +1,2 @@
+Runs external/wpt/mediacapture-streams tests with
+--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox
diff --git a/third_party/blink/web_tests/virtual/audio-service/http/tests/media/README.txt b/third_party/blink/web_tests/virtual/audio-service/http/tests/media/README.txt
new file mode 100644
index 0000000..ff4c6ba
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/audio-service/http/tests/media/README.txt
@@ -0,0 +1,2 @@
+Runs http/tests/media tests with
+--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox
diff --git a/third_party/blink/web_tests/virtual/audio-service/media/README.txt b/third_party/blink/web_tests/virtual/audio-service/media/README.txt
new file mode 100644
index 0000000..bcd289d
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/audio-service/media/README.txt
@@ -0,0 +1,2 @@
+Runs media tests with
+--enable-features=AudioServiceOutOfProcess,AudioServiceSandbox
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/README.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/README.txt
deleted file mode 100644
index de185c88..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-This directory is for testing Forced Colors mode implementation.
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html
deleted file mode 100644
index f8f9ce6..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-01-expected.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  table {
-    border-collapse: collapse;
-  }
-
-  td, th {
-    border: 1px solid;
-    border-bottom-color: WindowText;
-    border-left-color: WindowText;
-    border-right-color: WindowText;
-    border-top-color: WindowText;
-    forced-color-adjust: none;
-    padding: 8px;
-    text-align: left;
-  }
-
-  tr:nth-child(even) {
-    background-color: Window;
-    color: WindowText;
-    forced-color-adjust: none;
-  }
-</style>
-</head>
-<body>
-  <table>
-    <tr>
-      <th>Column1</th>
-      <th>Column2</th>
-      <th>Column3</th>
-    </tr>
-    <tr>
-      <td>Entry1</td>
-      <td>Entry1</td>
-      <td>Entry1</td>
-    </tr>
-    <tr>
-      <td>Entry2</td>
-      <td>Entry2</td>
-      <td>Entry2</td>
-    </tr>
-  </table>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html
deleted file mode 100644
index c7078c36..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-02-expected.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  body {
-    background-color: lightblue;
-  }
-  #a {
-    background-color: Window;
-    border: 25px solid WindowText;
-    box-shadow: 2px 2px Window;
-    color: WindowText;
-    forced-color-adjust: none;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px Window;
-    width: 300px;
-  }
-  #b {
-    background-color: lightgreen;
-    border: 25px solid green;
-    box-shadow: 2px 2px purple;
-    color: orange;
-    forced-color-adjust: none;
-    margin: 25px;
-    padding: 25px;
-    text-shadow: 1px 1px gray;
-    width: 300px;
-  }
-</style>
-</head>
-<body>
-  <div id="a">
-    The colors and shadows of this text and text box should be overridden when in
-    forced colors mode (forced-color-adjust is set to auto.)
-  </div>
-  <div id="b">
-    The colors and shadows of this text and text box should NOT be overridden when in
-    forced colors mode (forced-color-adjust is set to none.)
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt
deleted file mode 100644
index b497ff01..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-03-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks that default highlighted text style does not get overridden in forced colors mode.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt
deleted file mode 100644
index 26a63cd..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-04-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks hyperlinks are overridden in forced colors mode.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html
deleted file mode 100644
index 083a735a..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-05-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style type="text/css">
-  a {
-    color: LinkText;
-    forced-color-adjust: none;
-  }
-</style>
-</head>
-<body>
-  <p>
-    <a href="https://www.wikipedia.org" id="link">
-      This link color should be overridden when forced colors mode is enabled.
-    </a>
-  </p>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html
deleted file mode 100644
index ee78fcb..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-06-expected.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<body>
-  <iframe src="forced-colors-mode-02-expected.html" width="500" height="500"></iframe>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html
deleted file mode 100644
index aad20d16..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-07-expected.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-  p {
-    color: WindowText;
-    forced-color-adjust: none;
-  }
-  div {
-    forced-color-adjust: none;
-  }
-</style>
-<body>
-  <div style="background-color: Window;">
-    <p>
-      The text color should be overridden, and the background color of the
-      div element should also be overridden in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: transparent;">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-  <div style="background-color: rgba(0, 0, 0, 0);">
-    <p>
-      The text color should be overridden, but the background color of the
-      div element should remain transparent in forced colors mode.
-    </p>
-  </div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html
deleted file mode 100644
index b409f80..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-08-expected.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<style>
-  h1 {
-    forced-color-adjust: none;
-    outline-color: WindowText;
-    outline-style: solid;
-    -webkit-column-count: 3;
-    -webkit-column-gap: 40px;
-    -webkit-column-rule-color: WindowText;
-    -webkit-column-rule-style: solid;
-  }
-</style>
-</head>
-<body>
-  <h1>
-    The outline-color and column-rule-color should be blue when forced colors
-    mode is off and WindowText in forced colors mode.
-  </h1>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt
deleted file mode 100644
index 22ecd5d..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-09-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks that styles defined inside/outside forced-colors are overridden in forced colors mode.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt
deleted file mode 100644
index cd96b903..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-10-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks that styles defined inside/outside forced-colors are preserved in forced colors mode if forced-color-ajust is none.
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt b/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt
deleted file mode 100644
index c1a32f8..0000000
--- a/third_party/blink/web_tests/virtual/forced-colors/fast/css/forced-colors-mode/forced-colors-mode-11-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS Checks that styles defined in forced-colors are preserved in forced colors mode.
-Harness: the test ran to completion.
-
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js
index 0dd1d00..3b8a5eb 100644
--- a/third_party/closure_compiler/externs/networking_private.js
+++ b/third_party/closure_compiler/externs/networking_private.js
@@ -76,7 +76,6 @@
   VPN: 'VPN',
   WIRELESS: 'Wireless',
   WI_FI: 'WiFi',
-  WI_MAX: 'WiMAX',
 };
 
 /**
@@ -331,7 +330,7 @@
  *   Gateway: (string|undefined),
  *   IPAddress: (string|undefined),
  *   ExcludedRoutes: (!Array<string>|undefined),
- *   kIncludedRoutes: (!Array<string>|undefined),
+ *   IncludedRoutes: (!Array<string>|undefined),
  *   NameServers: (!Array<string>|undefined),
  *   SearchDomains: (!Array<string>|undefined),
  *   RoutingPrefix: (number|undefined),
@@ -840,31 +839,6 @@
 
 /**
  * @typedef {{
- *   AutoConnect: (boolean|undefined),
- *   EAP: (!chrome.networkingPrivate.EAPProperties|undefined),
- *   SignalStrength: (number|undefined)
- * }}
- */
-chrome.networkingPrivate.WiMAXProperties;
-
-/**
- * @typedef {{
- *   AutoConnect: (!chrome.networkingPrivate.ManagedBoolean|undefined),
- *   EAP: (!chrome.networkingPrivate.ManagedEAPProperties|undefined),
- *   SignalStrength: (number|undefined)
- * }}
- */
-chrome.networkingPrivate.ManagedWiMAXProperties;
-
-/**
- * @typedef {{
- *   SignalStrength: (number|undefined)
- * }}
- */
-chrome.networkingPrivate.WiMAXStateProperties;
-
-/**
- * @typedef {{
  *   Cellular: (!chrome.networkingPrivate.CellularProperties|undefined),
  *   Ethernet: (!chrome.networkingPrivate.EthernetProperties|undefined),
  *   GUID: (string|undefined),
@@ -876,8 +850,7 @@
  *   StaticIPConfig: (!chrome.networkingPrivate.IPConfigProperties|undefined),
  *   Type: (!chrome.networkingPrivate.NetworkType|undefined),
  *   VPN: (!chrome.networkingPrivate.VPNProperties|undefined),
- *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
- *   WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
+ *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined)
  * }}
  */
 chrome.networkingPrivate.NetworkConfigProperties;
@@ -904,8 +877,7 @@
  *   Tether: (!chrome.networkingPrivate.TetherProperties|undefined),
  *   Type: !chrome.networkingPrivate.NetworkType,
  *   VPN: (!chrome.networkingPrivate.VPNProperties|undefined),
- *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined),
- *   WiMAX: (!chrome.networkingPrivate.WiMAXProperties|undefined)
+ *   WiFi: (!chrome.networkingPrivate.WiFiProperties|undefined)
  * }}
  */
 chrome.networkingPrivate.NetworkProperties;
@@ -932,8 +904,7 @@
  *   Tether: (!chrome.networkingPrivate.TetherProperties|undefined),
  *   Type: !chrome.networkingPrivate.NetworkType,
  *   VPN: (!chrome.networkingPrivate.ManagedVPNProperties|undefined),
- *   WiFi: (!chrome.networkingPrivate.ManagedWiFiProperties|undefined),
- *   WiMAX: (!chrome.networkingPrivate.ManagedWiMAXProperties|undefined)
+ *   WiFi: (!chrome.networkingPrivate.ManagedWiFiProperties|undefined)
  * }}
  */
 chrome.networkingPrivate.ManagedProperties;
@@ -952,8 +923,7 @@
  *   Tether: (!chrome.networkingPrivate.TetherProperties|undefined),
  *   Type: !chrome.networkingPrivate.NetworkType,
  *   VPN: (!chrome.networkingPrivate.VPNStateProperties|undefined),
- *   WiFi: (!chrome.networkingPrivate.WiFiStateProperties|undefined),
- *   WiMAX: (!chrome.networkingPrivate.WiMAXStateProperties|undefined)
+ *   WiFi: (!chrome.networkingPrivate.WiFiStateProperties|undefined)
  * }}
  */
 chrome.networkingPrivate.NetworkStateProperties;
diff --git a/third_party/custom_tabs_client/README.chromium b/third_party/custom_tabs_client/README.chromium
index 95d433cc..0bf829b 100644
--- a/third_party/custom_tabs_client/README.chromium
+++ b/third_party/custom_tabs_client/README.chromium
@@ -3,7 +3,7 @@
 URL: https://chromium.googlesource.com/external/github.com/GoogleChrome/custom-tabs-client
 Version: unknown
 License: Apache 2.0
-Security Critical: no
+Security Critical: yes
 License Android Compatible: yes
 
 Description:
@@ -16,4 +16,11 @@
 The example applicaton also presents how to use Browser Actions, including
 creating request intent and adding custom items.
 
+The actual code that Chromium builds from is in
+//third_party/android_sdk/androidx_browser, this subdirectory is kept around
+for the example app (the custom_tabs_client_example_apk target).
+
+TODO(peconn): Get rid of src/customtabs and depend instead on
+androidx_browser.
+
 Local Modifications: None
diff --git a/tools/android/customtabs_benchmark/BUILD.gn b/tools/android/customtabs_benchmark/BUILD.gn
index 27cf5e0..e8dec60 100644
--- a/tools/android/customtabs_benchmark/BUILD.gn
+++ b/tools/android/customtabs_benchmark/BUILD.gn
@@ -21,6 +21,6 @@
   deps = [
     ":customtabs_benchmark_apk_resources",
     "//third_party/android_deps:android_support_v4_java",
-    "//third_party/custom_tabs_client:custom_tabs_support_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
   ]
 }
diff --git a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
index 3e205ec8..b16f4c13 100644
--- a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
+++ b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
@@ -18,11 +18,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.SystemClock;
-import android.support.customtabs.CustomTabsCallback;
-import android.support.customtabs.CustomTabsClient;
-import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsServiceConnection;
-import android.support.customtabs.CustomTabsSession;
 import android.support.v4.app.BundleCompat;
 import android.util.Log;
 import android.view.View;
@@ -39,6 +34,12 @@
 import java.util.Random;
 import java.util.Set;
 
+import androidx.browser.customtabs.CustomTabsCallback;
+import androidx.browser.customtabs.CustomTabsClient;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsServiceConnection;
+import androidx.browser.customtabs.CustomTabsSession;
+
 /** Activity used to benchmark Custom Tabs PLT.
  *
  * This activity contains benchmark code for two modes:
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index e9af384..17f6778 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -114,10 +114,8 @@
     <classpathentry kind="src" path="third_party/android_data_chart/java/src"/>
     <classpathentry kind="src" path="third_party/android_protobuf/src/java/src/main/java" including="com/google/protobuf/nano/*"/>
     <classpathentry kind="src" path="third_party/android_swipe_refresh/java/src"/>
+    <classpathentry kind="src" path="third_party/androidx_browser/src/browser/src"/>
     <classpathentry kind="src" path="third_party/cacheinvalidation/src/java"/>
-    <classpathentry kind="src" path="third_party/custom_tabs_client/src/customtabs/src"/>
-    <classpathentry kind="src" path="third_party/custom_tabs_client/src/Application/src/main/java"/>
-    <classpathentry kind="src" path="third_party/custom_tabs_client/src/shared/src/main/java"/>
     <classpathentry kind="src" path="third_party/gif_player/src"/>
     <classpathentry kind="src" path="third_party/junit/src/src/main/java"/>
     <classpathentry kind="src" path="third_party/mockito/src/src/main/java"/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index de5217a..8dcdfcab 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -29317,6 +29317,16 @@
   <int value="3" label="GPU"/>
 </enum>
 
+<enum name="HeavyAdStatus">
+  <int value="0" label="Not heavy"/>
+  <int value="1" label="Network">
+    The ad exceeded the network threshold for the Heavy Ad Intervention.
+  </int>
+  <int value="2" label="CPU">
+    The ad exceeded the CPU threshold for the Heavy Ad Intervention.
+  </int>
+</enum>
+
 <enum name="HeavyPageCappingInfoBarInteraction">
   <int value="0" label="InfoBar shown">
     The user was shown the capping heavy pages InfoBar.
@@ -35250,6 +35260,7 @@
   <int value="-572012175" label="AssistantEnableStereoAudioInput:disabled"/>
   <int value="-571236436" label="AppManagement:disabled"/>
   <int value="-570889908" label="CCTModuleDexLoading:enabled"/>
+  <int value="-568448085" label="SharedClipboardReceiver:disabled"/>
   <int value="-567920515" label="disable-experimental-hotwording"/>
   <int value="-563980787" label="disable-webrtc"/>
   <int value="-562274241" label="enable-extension-action-redesign"/>
@@ -35999,6 +36010,7 @@
       label="AutofillEnforceMinRequiredFieldsForQuery:enabled"/>
   <int value="510814146" label="OfflineBookmarks:enabled"/>
   <int value="511179195" label="ShoppingAssist:disabled"/>
+  <int value="511392922" label="SharedClipboardReceiver:enabled"/>
   <int value="513258875" label="WinrtSensorsImplementation:disabled"/>
   <int value="513356954" label="InstantTethering:disabled"/>
   <int value="513372959" label="ViewsProfileChooser:enabled"/>
@@ -36030,6 +36042,7 @@
   <int value="564522013" label="Av1Decoder:disabled"/>
   <int value="565406673" label="EnableVirtualKeyboardMdUi:enabled"/>
   <int value="567368307" label="enable-experimental-canvas-features"/>
+  <int value="573385109" label="SharedClipboardUI:enabled"/>
   <int value="575380532" label="ExperimentalAccessibilityLabels:disabled"/>
   <int value="575394365" label="AndroidPaymentApps:disabled"/>
   <int value="575829120" label="shelf-hotseat"/>
@@ -36219,6 +36232,7 @@
   <int value="834033186" label="enable-data-reduction-proxy-dev"/>
   <int value="834326277" label="enable-answers-in-suggest"/>
   <int value="835018878" label="disable-quic"/>
+  <int value="835324823" label="ForceDiceMigration:enabled"/>
   <int value="836406476" label="EnableTouchableAppContextMenu:enabled"/>
   <int value="838887742" label="manual-enhanced-bookmarks"/>
   <int value="839798268" label="SafeBrowsingTelemetryForApkDownloads:disabled"/>
@@ -36275,6 +36289,7 @@
   <int value="926852901" label="DataReductionProxyMainMenu:disabled"/>
   <int value="929462705" label="disable-link-disambiguation-popup"/>
   <int value="934292666" label="DownloadRename:enabled"/>
+  <int value="935364646" label="ForceDiceMigration:disabled"/>
   <int value="935655516" label="password-import-export:disabled"/>
   <int value="936341613" label="OfflinePagesCT:disabled"/>
   <int value="936919953" label="bypass-app-banner-engagement-checks"/>
@@ -37083,6 +37098,7 @@
   <int value="2063091429" label="OfflinePagesSharing:enabled"/>
   <int value="2067634730" label="LsdPermissionPrompt:disabled"/>
   <int value="2067735898" label="WebVrAutopresentFromIntent:enabled"/>
+  <int value="2068193488" label="SharedClipboardUI:disabled"/>
   <int value="2069999572"
       label="AllowSignedHTTPExchangeCertsWithoutExtension:disabled"/>
   <int value="2071229145" label="BloatedRendererDetection:enabled"/>
@@ -51595,6 +51611,13 @@
   <int value="3" label="Load"/>
 </enum>
 
+<enum name="RevokeTokenAction">
+  <int value="0" label="None"/>
+  <int value="1" label="Invalidate token for primary account"/>
+  <int value="2" label="Revoke token for secondary accounts"/>
+  <int value="3" label="Revoke tokens for primary and secondary accounts"/>
+</enum>
+
 <enum name="Rollback_OobeRestoreResult">
   <int value="0" label="Succeeded"/>
   <int value="1" label="Stage 1 Failure"/>
@@ -59436,7 +59459,7 @@
   <int value="0" label="Unknown"/>
   <int value="1" label="Ethernet"/>
   <int value="2" label="Wifi"/>
-  <int value="3" label="WiMAX"/>
+  <int value="3" label="WiMAX (Deprecated)"/>
   <int value="4" label="Bluetooth"/>
   <int value="5" label="Cellular"/>
   <int value="6" label="Tethered (Ethernet)"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4c54ea8..13e7390 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1579,6 +1579,39 @@
   <summary>Records that a specific background task has been canceled.</summary>
 </histogram>
 
+<histogram name="Android.BackgroundTaskScheduler.TaskCreated.WithExpiration"
+    enum="BackgroundTaskId" expires_after="2020-01-31">
+  <owner>ioanastefan@chromium.org</owner>
+  <owner>nator@chromium.org</owner>
+  <owner>knollr@chromium.org</owner>
+  <summary>
+    Records that a specific task has been created with an expiration deadline.
+    Recorded when the task is scheduled.
+  </summary>
+</histogram>
+
+<histogram name="Android.BackgroundTaskScheduler.TaskCreated.WithoutExpiration"
+    enum="BackgroundTaskId" expires_after="2020-01-31">
+  <owner>ioanastefan@chromium.org</owner>
+  <owner>nator@chromium.org</owner>
+  <owner>knollr@chromium.org</owner>
+  <summary>
+    Records that a specific task has been created without the expiration feature
+    activated. Recorded when the task is scheduled.
+  </summary>
+</histogram>
+
+<histogram name="Android.BackgroundTaskScheduler.TaskExpired"
+    enum="BackgroundTaskId" expires_after="2020-01-31">
+  <owner>ioanastefan@chromium.org</owner>
+  <owner>nator@chromium.org</owner>
+  <owner>knollr@chromium.org</owner>
+  <summary>
+    Records that a specific background task has expired. Recorded before the
+    task is to be started.
+  </summary>
+</histogram>
+
 <histogram name="Android.BackgroundTaskScheduler.TaskLoadedNative"
     enum="BackgroundTaskId" expires_after="2020-01-20">
   <owner>fgorski@chromium.org</owner>
@@ -14008,6 +14041,7 @@
 
 <histogram base="true" name="Blink.MainFrame.AnimateRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14019,6 +14053,7 @@
 
 <histogram base="true" name="Blink.MainFrame.CompositingCommitRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14030,6 +14065,7 @@
 
 <histogram base="true" name="Blink.MainFrame.CompositingRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14041,6 +14077,7 @@
 
 <histogram base="true" name="Blink.MainFrame.ForcedStyleAndLayoutRatio"
     units="%" expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14053,6 +14090,7 @@
 
 <histogram base="true" name="Blink.MainFrame.HandleInputEventsRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14064,6 +14102,7 @@
 
 <histogram base="true" name="Blink.MainFrame.IntersectionObservationRatio"
     units="%" expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14075,6 +14114,7 @@
 
 <histogram base="true" name="Blink.MainFrame.PaintRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14086,6 +14126,7 @@
 
 <histogram base="true" name="Blink.MainFrame.PrePaintRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14097,6 +14138,7 @@
 
 <histogram base="true" name="Blink.MainFrame.ProxyCommitRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14106,8 +14148,22 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Blink.MainFrame.ScrollingCoordinatorRatio"
+    units="%" expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
+  <owner>paint-dev@chromium.org</owner>
+<!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
+
+  <summary>
+    The percentage of the total BeginMainFrame execution time used for the
+    ScrollingCoordinator update in Blink, for each frame that we record.
+    Recorded in ScrollingCoordinator::UpdateAfterPaint.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Blink.MainFrame.StyleAndLayoutRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14119,6 +14175,7 @@
 
 <histogram base="true" name="Blink.MainFrame.UpdateLayersRatio" units="%"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
 <!-- Name completed by histogram_suffixes name="BlinkMainFrameUpdateTimeSuffixes" -->
 
@@ -14130,6 +14187,7 @@
 
 <histogram name="Blink.MainFrame.UpdateTime" units="microseconds"
     expires_after="2020-3-1">
+  <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
     Time between a BeginMainFrame and paint results commit in Blink.
@@ -45857,6 +45915,18 @@
   <summary>Time to retrieve the fallback fonts on the system.</summary>
 </histogram>
 
+<histogram name="ForceDiceMigration.RevokeTokenAction" enum="RevokeTokenAction"
+    expires_after="2020-01-25">
+  <owner>msalama@chromium.org</owner>
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Tracks revoke actions taken by the account reconcilior to force Dice
+    migration. To enforce consistency, the reconcilior may invalidate the
+    primary account or revoke one or more secondary account tokens, if no
+    equivalent valid gaia cookie exist for those accounts.
+  </summary>
+</histogram>
+
 <histogram name="Gaia.AuthFetcher.ListAccounts.NetErrorCodes"
     enum="NetErrorCodes" expires_after="2019-08-30">
   <owner>droger@chromium.org</owner>
@@ -93920,6 +93990,32 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="PageLoad.HeavyAds.ComputedType"
+    enum="HeavyAdStatus" expires_after="2020-08-05">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Records heavy ad type for each ad frame, as determine by the ifrst threshold
+    hit (see FrameData::HeavyadStatus). This is recorded regardless of feature
+    flag or other conditions that prevent the heavy ad intervention from
+    occuring. Recored for all ad frames with non-zero bytes. Recorded when the
+    ad frame destroyed or when the page is destroyed.
+  </summary>
+</histogram>
+
+<histogram base="true" name="PageLoad.HeavyAds.InterventionType"
+    enum="HeavyAdStatus" expires_after="2020-08-05">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Records the type of heavy ad unloaded by the heavy ad intervention. Heavy ad
+    type is determined by the first threshold hit. This is not recorded for ad
+    frames that are considered heavy but did not fufill other criteria for the
+    intervention. This includes the feature being enabled and being below the
+    per-origin intervention cap.
+  </summary>
+</histogram>
+
 <histogram name="PageLoad.InputTiming.NavigationToFirstNonScroll.AfterPaint"
     units="ms" expires_after="M77">
   <owner>tdresser@chromium.org</owner>
@@ -127055,7 +127151,7 @@
   <owner>msalama@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <summary>
-    Tracks the reason of why DICE migration is not ready. It is computed by dice
+    Tracks the reason of why DICE migration is not ready. It is computed by Dice
     reconcilor delegate on every reconciliation cycle.
   </summary>
 </histogram>
@@ -127684,8 +127780,8 @@
   <owner>msarda@chromium.org</owner>
   <summary>
     Tracks the state of kTokenServiceDiceCompatible preference. This is recorded
-    at every startup, if the account consistency method is in dice migration and
-    is not ready yet to migrate to dice.
+    at every startup, if the account consistency method is in Dice migration and
+    is not ready yet to migrate to Dice.
   </summary>
 </histogram>
 
@@ -156277,6 +156373,8 @@
   <affected-histogram
       name="PageLoad.FrameCounts.AdFrames.PerFrame.UserActivation"/>
   <affected-histogram name="PageLoad.FrameCounts.AnyParentFrame.AdFrames"/>
+  <affected-histogram name="PageLoad.HeavyAds.ComputedType"/>
+  <affected-histogram name="PageLoad.HeavyAds.InterventionType"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="AffiliationDummyData" separator=".">
@@ -157308,6 +157406,7 @@
   <affected-histogram name="Blink.MainFrame.PaintRatio"/>
   <affected-histogram name="Blink.MainFrame.PrePaintRatio"/>
   <affected-histogram name="Blink.MainFrame.ProxyCommitRatio"/>
+  <affected-histogram name="Blink.MainFrame.ScrollingCoordinatorRatio"/>
   <affected-histogram name="Blink.MainFrame.StyleAndLayoutRatio"/>
   <affected-histogram name="Blink.MainFrame.UpdateLayersRatio"/>
 </histogram_suffixes>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 179dbe5a..c13dce4 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -30,6 +30,7 @@
  <item id="bluetooth_socket" hash_code="94099818" type="0" content_hash_code="30932349" os_list="linux,windows" file_path="device/bluetooth/bluetooth_socket_net.cc"/>
  <item id="brandcode_config" hash_code="109679553" type="0" content_hash_code="128843792" os_list="linux,windows" file_path="chrome/browser/profile_resetter/brandcode_config_fetcher.cc"/>
  <item id="browser_switcher_ieem_sitelist" hash_code="97159948" type="0" content_hash_code="40881413" os_list="linux,windows" file_path="chrome/browser/browser_switcher/browser_switcher_service.cc"/>
+ <item id="bundled_exchanges_start_url_loader" hash_code="105810794" type="0" content_hash_code="20630448" os_list="linux,windows" file_path="content/browser/web_package/bundled_exchanges_handle.cc"/>
  <item id="captive_portal_service" hash_code="88754904" type="0" content_hash_code="70737580" os_list="linux,windows" file_path="chrome/browser/captive_portal/captive_portal_service.cc"/>
  <item id="cast_channel_send" hash_code="103172229" type="0" deprecated="2018-08-23" content_hash_code="33946302" file_path=""/>
  <item id="cast_keep_alive_delegate" hash_code="134755844" type="0" deprecated="2018-08-23" content_hash_code="66118796" file_path=""/>
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index d2b3756..c9967e7 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -180,6 +180,16 @@
   return nullptr;
 }
 
+AtkObject* FindAtkObjectToplevelParentDocument(AtkObject* atk_object) {
+  AtkObject* toplevel_document = nullptr;
+  while (atk_object) {
+    if (atk_object_get_role(atk_object) == ATK_ROLE_DOCUMENT_WEB)
+      toplevel_document = atk_object;
+    atk_object = atk_object_get_parent(atk_object);
+  }
+  return toplevel_document;
+}
+
 bool EmitsAtkTextEvents(AtkObject* atk_object) {
   // If this node is not a static text node, it supports the full AtkText
   // interface.
@@ -214,6 +224,12 @@
   return *active_menus;
 }
 
+std::map<AtkObject*, FindInPageResultInfo>& GetActiveFindInPageResults() {
+  static base::NoDestructor<std::map<AtkObject*, FindInPageResultInfo>>
+      active_results;
+  return *active_results;
+}
+
 // The currently active frame is g_active_top_level_frame, unless there is an
 // active menu. If there is an active menu the parent frame of the
 // most-recently opened active menu should be the currently active frame.
@@ -1039,8 +1055,15 @@
   if (!obj)
     return 0;
 
-  // We only support a single selection.
-  return obj->HasSelection() ? 1 : 0;
+  if (obj->HasSelection())
+    return 1;
+
+  base::Optional<FindInPageResultInfo> result =
+      obj->GetSelectionOffsetsFromFindInPage();
+  if (result.has_value() && result->node == ATK_OBJECT(atk_text))
+    return 1;
+
+  return 0;
 }
 
 gchar* GetSelection(AtkText* atk_text,
@@ -3732,8 +3755,14 @@
 }
 
 int AXPlatformNodeAuraLinux::GetCaretOffset() {
-  if (!HasCaret())
+  if (!HasCaret()) {
+    base::Optional<FindInPageResultInfo> result =
+        GetSelectionOffsetsFromFindInPage();
+    AtkObject* atk_object = GetOrCreateAtkObject();
+    if (result.has_value() && result->node == atk_object)
+      return UTF16ToUnicodeOffsetInText(result->end_offset);
     return -1;
+  }
 
   int selection_start, selection_end;
   GetSelectionOffsets(&selection_start, &selection_end);
@@ -3830,15 +3859,34 @@
                                                      int* end_offset) {
   int selection_start, selection_end;
   GetSelectionExtents(&selection_start, &selection_end);
+
+  AtkObject* atk_object = GetOrCreateAtkObject();
+  if (selection_start < 0 || selection_end < 0 ||
+      selection_start == selection_end) {
+    base::Optional<FindInPageResultInfo> find_in_page_result =
+        GetSelectionOffsetsFromFindInPage();
+    if (!find_in_page_result.has_value() ||
+        find_in_page_result->node != atk_object) {
+      *start_offset = 0;
+      *end_offset = 0;
+      return nullptr;
+    }
+
+    selection_start = find_in_page_result->start_offset;
+    selection_end = find_in_page_result->end_offset;
+  }
+
+  selection_start = UTF16ToUnicodeOffsetInText(selection_start);
+  selection_end = UTF16ToUnicodeOffsetInText(selection_end);
+  if (selection_start < 0 || selection_end < 0 ||
+      selection_start == selection_end) {
+    return nullptr;
+  }
+
   if (start_offset)
     *start_offset = selection_start;
   if (end_offset)
     *end_offset = selection_end;
-
-  if (selection_start < 0 || selection_end < 0 ||
-      selection_start == selection_end)
-    return nullptr;
-
   return atk_text::GetText(ATK_TEXT(GetOrCreateAtkObject()), selection_start,
                            selection_end);
 }
@@ -4217,4 +4265,102 @@
   return default_text_attributes_.get();
 }
 
+void AXPlatformNodeAuraLinux::TerminateFindInPage() {
+  ForgetCurrentFindInPageResult();
+}
+
+void AXPlatformNodeAuraLinux::ActivateFindInPageResult(int start_offset,
+                                                       int end_offset) {
+  AtkObject* atk_object = GetOrCreateAtkObject();
+  DCHECK(ATK_IS_TEXT(atk_object));
+
+  if (!EmitsAtkTextEvents(atk_object)) {
+    ActivateFindInPageInParent(start_offset, end_offset);
+    return;
+  }
+
+  AtkObject* parent_doc = FindAtkObjectToplevelParentDocument(atk_object);
+  if (!parent_doc)
+    return;
+
+  std::map<AtkObject*, FindInPageResultInfo>& active_results =
+      GetActiveFindInPageResults();
+  auto iterator = active_results.find(parent_doc);
+  FindInPageResultInfo new_info = {atk_object, start_offset, end_offset};
+  if (iterator != active_results.end() && iterator->second == new_info)
+    return;
+
+  active_results[parent_doc] = new_info;
+  g_signal_emit_by_name(atk_object, "text-selection-changed");
+  g_signal_emit_by_name(atk_object, "text-caret-moved",
+                        UTF16ToUnicodeOffsetInText(end_offset));
+}
+
+base::Optional<std::pair<int, int>>
+AXPlatformNodeAuraLinux::GetHypertextExtentsOfChild(
+    AXPlatformNodeAuraLinux* child_to_find) {
+  int current_offset = 0;
+  for (auto child_iterator_ptr = GetDelegate()->ChildrenBegin();
+       *child_iterator_ptr != *GetDelegate()->ChildrenEnd();
+       ++(*child_iterator_ptr)) {
+    auto* child = AtkObjectToAXPlatformNodeAuraLinux(
+        child_iterator_ptr->GetNativeViewAccessible());
+    if (!child)
+      continue;
+
+    // If this object is a text only object, it is included directly into this
+    // node's hypertext, otherwise it is represented as an embedded object
+    // character.
+    int size =
+        child->IsTextOnlyObject()
+            ? child->GetString16Attribute(ax::mojom::StringAttribute::kName)
+                  .size()
+            : 1;
+    if (child == child_to_find)
+      return std::make_pair(current_offset, current_offset + size);
+    current_offset += size;
+  }
+
+  return base::nullopt;
+}
+
+void AXPlatformNodeAuraLinux::ActivateFindInPageInParent(int start_offset,
+                                                         int end_offset) {
+  auto* parent = AtkObjectToAXPlatformNodeAuraLinux(GetParent());
+  if (!parent)
+    return;
+
+  base::Optional<std::pair<int, int>> extents_in_parent =
+      parent->GetHypertextExtentsOfChild(this);
+  if (!extents_in_parent.has_value())
+    return;
+
+  DCHECK(IsTextOnlyObject());
+  parent->ActivateFindInPageResult(extents_in_parent->first + start_offset,
+                                   extents_in_parent->first + end_offset);
+}
+
+void AXPlatformNodeAuraLinux::ForgetCurrentFindInPageResult() {
+  AtkObject* atk_object = GetOrCreateAtkObject();
+  AtkObject* parent_doc = FindAtkObjectToplevelParentDocument(atk_object);
+  if (parent_doc)
+    GetActiveFindInPageResults().erase(parent_doc);
+}
+
+base::Optional<FindInPageResultInfo>
+AXPlatformNodeAuraLinux::GetSelectionOffsetsFromFindInPage() {
+  AtkObject* atk_object = GetOrCreateAtkObject();
+  AtkObject* parent_doc = FindAtkObjectToplevelParentDocument(atk_object);
+  if (!parent_doc)
+    return base::nullopt;
+
+  std::map<AtkObject*, FindInPageResultInfo>& active_results =
+      GetActiveFindInPageResults();
+  auto iterator = active_results.find(parent_doc);
+  if (iterator == active_results.end())
+    return base::nullopt;
+
+  return iterator->second;
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h
index d7ccd70..3b08d05 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -44,6 +44,17 @@
 
 namespace ui {
 
+struct FindInPageResultInfo {
+  AtkObject* node;
+  int start_offset;
+  int end_offset;
+
+  bool operator==(const FindInPageResultInfo& other) const {
+    return (node == other.node) && (start_offset == other.start_offset) &&
+           (end_offset == other.end_offset);
+  }
+};
+
 // AtkTableCell was introduced in ATK 2.12. Ubuntu Trusty has ATK 2.10.
 // Compile-time checks are in place for ATK versions that are older than 2.12.
 // However, we also need runtime checks in case the version we are building
@@ -205,6 +216,13 @@
   // atk_attribute_set_free.
   AtkAttributeSet* GetDefaultTextAttributes();
 
+  void ActivateFindInPageResult(int start_offset, int end_offset);
+  void TerminateFindInPage();
+
+  // If there is a find in page result for the toplevel document of this node,
+  // return it, otherwise return base::nullopt;
+  base::Optional<FindInPageResultInfo> GetSelectionOffsetsFromFindInPage();
+
   std::string accessible_name_;
 
  protected:
@@ -258,6 +276,17 @@
   AtkAttributes ComputeTextAttributes() const;
   int FindStartOfStyle(int start_offset, ui::TextBoundaryDirection direction);
 
+  // Reset any find in page operations for the toplevel document of this node.
+  void ForgetCurrentFindInPageResult();
+
+  // Activate a find in page result for the toplevel document of this node.
+  void ActivateFindInPageInParent(int start_offset, int end_offset);
+
+  // If the given argument can be found as a child of this node, return its
+  // hypertext extents, otherwise return base::nullopt;
+  base::Optional<std::pair<int, int>> GetHypertextExtentsOfChild(
+      AXPlatformNodeAuraLinux* child);
+
   // The AtkStateType for a checkable node can vary depending on the role.
   AtkStateType GetAtkStateTypeForCheckableNode();
 
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 b18cc73f..e2ec1acb 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.html
@@ -128,7 +128,7 @@
         </network-config-toggle>
       </template>
 
-      <!-- EAP (WiFi, WiMAX, Ethernet) -->
+      <!-- EAP (WiFi, Ethernet) -->
       <template is="dom-if" if="[[showEap_]]" restamp>
         <network-config-select id="outer" label="[[i18n('OncEAP-Outer')]]"
             value="{{eapProperties_.Outer}}" items="[[eapOuterItems_]]"
@@ -177,7 +177,7 @@
         </network-config-toggle>
       </template>
 
-      <!-- Share (WiFi and WiMAX) -->
+      <!-- Share (WiFi) -->
       <template is="dom-if"
           if="[[shareIsVisible_(guid, type, managedProperties)]]" restamp>
         <div class="property-box">
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 930b447..ade9cad 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -276,7 +276,6 @@
         ETHERNET: CrOnc.Type.ETHERNET,
         VPN: CrOnc.Type.VPN,
         WI_FI: CrOnc.Type.WI_FI,
-        WI_MAX: CrOnc.Type.WI_MAX,
       },
       readOnly: true
     },
@@ -773,23 +772,6 @@
             CrOnc.Security.WPA_EAP :
             CrOnc.Security.NONE;
         break;
-      case CrOnc.Type.WI_MAX:
-        if (managedProperties.WiMAX) {
-          configProperties.WiMAX = {
-            AutoConnect:
-                /** @type {boolean|undefined} */ (
-                    CrOnc.getActiveValue(managedProperties.WiMAX.AutoConnect)),
-            EAP: Object.assign(
-                {}, CrOnc.getActiveProperties(managedProperties.WiMAX.EAP)),
-          };
-          // WiMAX has no EAP.Outer property, only Identity and Password.
-        } else {
-          configProperties.WiMAX = {
-            AutoConnect: false,
-          };
-        }
-        this.security_ = CrOnc.Security.WPA_EAP;
-        break;
       case CrOnc.Type.VPN:
         if (managedProperties.VPN) {
           const vpn = {
@@ -903,12 +885,6 @@
     }
     const outer = this.eapProperties_.Outer;
     switch (this.type) {
-      case CrOnc.Type.WI_MAX:
-        this.showEap_ = {
-          Identity: true,
-          Password: true,
-        };
-        break;
       case CrOnc.Type.WI_FI:
       case CrOnc.Type.ETHERNET:
         this.showEap_ = {
@@ -942,9 +918,6 @@
       case CrOnc.Type.ETHERNET:
         eap = properties.Ethernet && properties.Ethernet.EAP;
         break;
-      case CrOnc.Type.WI_MAX:
-        eap = properties.WiMAX && properties.WiMAX.EAP;
-        break;
     }
     if (opt_create) {
       return eap || {};
@@ -967,9 +940,6 @@
       case CrOnc.Type.ETHERNET:
         this.set('Ethernet.EAP', eapProperties, this.configProperties_);
         break;
-      case CrOnc.Type.WI_MAX:
-        this.set('WiMAX.EAP', eapProperties, this.configProperties_);
-        break;
     }
     this.set('eapProperties_', eapProperties);
   },
@@ -989,9 +959,6 @@
         managedEap =
             managedProperties.Ethernet && managedProperties.Ethernet.EAP;
         break;
-      case CrOnc.Type.WI_MAX:
-        managedEap = managedProperties.WiMAX && managedProperties.WiMAX.EAP;
-        break;
     }
     return managedEap || null;
   },
@@ -1304,7 +1271,7 @@
    */
   shareIsVisible_: function(guid, type, managedProperties) {
     return this.getSource_(guid, managedProperties) == CrOnc.Source.NONE &&
-        (type == CrOnc.Type.WI_FI || type == CrOnc.Type.WI_MAX);
+        type == CrOnc.Type.WI_FI;
   },
 
   /**
@@ -1625,8 +1592,7 @@
    * @private
    */
   configRequiresPassphrase_: function(type, security) {
-    // Note: 'Passphrase' is only used by WiFi; Ethernet and WiMAX use
-    // EAP.Password.
+    // Note: 'Passphrase' is only used by WiFi; Ethernet uses EAP.Password.
     return type == CrOnc.Type.WI_FI &&
         (security == CrOnc.Security.WEP_PSK ||
          security == CrOnc.Security.WPA_PSK);
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
index 2cb7bae..7065ce1d 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_icon.js
@@ -132,12 +132,8 @@
     if (!this.networkState) {
       return '';
     }
-    const mojom = chromeos.networkConfig.mojom;
-    const type = this.networkState.type;
-    if (type == mojom.NetworkType.kWiMAX) {
-      return 'network:4g';
-    }
-    if (type == mojom.NetworkType.kCellular) {
+    if (this.networkState.type ==
+        chromeos.networkConfig.mojom.NetworkType.kCellular) {
       assert(this.networkState.cellular);
       const technology =
           this.getTechnologyId_(this.networkState.cellular.networkTechnology);
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js b/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
index 2452bbc..4cb023c 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
@@ -25,7 +25,6 @@
  *   OncTypeTether: string,
  *   OncTypeVPN: string,
  *   OncTypeWiFi: string,
- *   OncTypeWiMAX: string,
  *   networkListItemConnected: string,
  *   networkListItemConnecting: string,
  *   networkListItemConnectingTo: string,
@@ -421,9 +420,6 @@
   if (type == CrOnc.Type.WI_FI && properties.WiFi) {
     return properties.WiFi.SignalStrength || 0;
   }
-  if (type == CrOnc.Type.WI_MAX && properties.WiMAX) {
-    return properties.WiMAX.SignalStrength || 0;
-  }
   return 0;
 };
 
@@ -446,9 +442,6 @@
   if (type == CrOnc.Type.WI_FI && properties.WiFi) {
     return properties.WiFi.AutoConnect;
   }
-  if (type == CrOnc.Type.WI_MAX && properties.WiMAX) {
-    return properties.WiMAX.AutoConnect;
-  }
   return undefined;
 };
 
diff --git a/ui/webui/resources/js/chromeos/onc_mojo.js b/ui/webui/resources/js/chromeos/onc_mojo.js
index 6008a7e..932aaef5 100644
--- a/ui/webui/resources/js/chromeos/onc_mojo.js
+++ b/ui/webui/resources/js/chromeos/onc_mojo.js
@@ -208,8 +208,6 @@
         return 'Wireless';
       case NetworkType.kWiFi:
         return 'WiFi';
-      case NetworkType.kWiMAX:
-        return 'WiMAX';
     }
     assertNotReached('Unexpected enum value: ' + OncMojo.getEnumString(value));
     return '';
@@ -231,7 +229,6 @@
       case NetworkType.kVPN:
       case NetworkType.kWireless:
       case NetworkType.kWiFi:
-      case NetworkType.kWiMAX:
         return false;
     }
     assertNotReached('Unexpected enum value: ' + OncMojo.getEnumString(value));
@@ -261,8 +258,6 @@
         return NetworkType.kWireless;
       case 'WiFi':
         return NetworkType.kWiFi;
-      case 'WiMAX':
-        return NetworkType.kWiMAX;
     }
     assertNotReached('Unexpected value: ' + value);
     return NetworkType.kAll;
@@ -453,8 +448,6 @@
         return network.tether.signalStrength;
       case NetworkType.kWiFi:
         return network.wifi.signalStrength;
-      case NetworkType.kWiMAX:
-        return network.wimax.signalStrength;
     }
     assertNotReached();
     return 0;
@@ -518,11 +511,6 @@
           ssid: '',
         };
         break;
-      case mojom.NetworkType.kWiMAX:
-        result.wimax = {
-          signalStrength: 0,
-        };
-        break;
     }
     return result;
   }
@@ -616,12 +604,6 @@
               CrOnc.getStateOrActiveString(properties.WiFi.SSID);
         }
         break;
-      case mojom.NetworkType.kWiMAX:
-        if (properties.WiMAX) {
-          networkState.wimax.signalStrength =
-              properties.WiMAX.SignalStrength || 0;
-        }
-        break;
     }
     return networkState;
   }