diff --git a/DEPS b/DEPS
index 991c1e4..4279eee2c 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '78325c1d01fb8b6c3d9e2aadc647140c8abb8976',
+  'skia_revision': '57c9d20102fd53a960293b45e3fed7cb1aac94fd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'b73ce7bcd72a97c780176d9f63681a5415c06422',
+  'pdfium_revision': '4db9046e56c884a350fa2c5087f8d5b8110463c4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '86fadb61788d32393c43d5dd95c3576ea48b6a2f',
+  'catapult_revision': 'c2d7f3a00bd5a59fd099a4959880d3b147dc0d5f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index f231968f..fe1759c 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -351,10 +351,6 @@
     'clipboard': {
       'filepath': 'clipboard|dnd|drag|drop',
     },
-    'closure': {
-      'filepath': 'third_party/closure_(compiler|linter)/|'
-                  'compiled_resources2?.gyp',
-    },
     'codereview_settings': {
       'filepath': 'codereview.settings',
     },
@@ -1952,9 +1948,6 @@
                      'vmpstr+watch@chromium.org',
                      'yunlian@chromium.org'],
     'clipboard': ['dcheng@chromium.org'],
-    'closure': ['dbeam+watch-closure@chromium.org',
-                'jlklein+watch-closure@chromium.org',
-                'vitalyp+closure@chromium.org'],
     'codereview_settings': ['agable+watch@chromium.org'],
     'components_deps': ['blundell+watchlist@chromium.org',
                         'droger+watchlist@chromium.org',
@@ -1980,8 +1973,7 @@
                           'twellington+watch@chromium.org'],
     'courgette': ['huangs+watch@chromium.org',
                   'wfh+watch@chromium.org'],
-    'cr_elements': ['dbeam+watch-elements@chromium.org',
-                    'michaelpg+watch-elements@chromium.org',
+    'cr_elements': ['michaelpg+watch-elements@chromium.org',
                     'stevenjb+watch-md-settings@chromium.org'],
     'custom_tabs': ['lizeb+watch-custom-tabs@chromium.org'],
     'data_reduction_proxy': ['tbansal+watch-data-reduction-proxy@chromium.org'],
@@ -1999,8 +1991,7 @@
              'zhaobin+watch@chromium.org'],
     'disk_cache': ['gavinp+disk@chromium.org'],
     'download': ['dtrainor+watch@chromium.org'],
-    'downloads_ui': ['dtrainor+watch@chromium.org',
-                     'dbeam+watch-downloads@chromium.org'],
+    'downloads_ui': ['dtrainor+watch@chromium.org'],
     'drive': ['tfarina@chromium.org'],
     'drive_resource_metadata': ['hashimoto+watch@chromium.org'],
     'eme': ['eme-reviews@chromium.org'],
@@ -2038,9 +2029,7 @@
              'ukai+cc@chromium.com',
              'yyanagisawa+cc@chromium.com'],
     'gpu': ['piman+watch@chromium.org'],
-    'history_ui': ['dbeam+watch-history@chromium.org',
-                   'dubroy@chromium.org',
-                   'pam+watch@chromium.org'],
+    'history_ui': ['pam+watch@chromium.org'],
     'hotword': ['rlp+watch@chromium.org'],
     'i18n': ['jshin+watch@chromium.org'],
     'importer': ['tfarina@chromium.org'],
@@ -2090,8 +2079,7 @@
     'login': ['vabr+watchlistlogin@chromium.org'],
     'mac' : ['mac-reviews@chromium.org'],
     'manifest': ['mlamouri+watch-manifest@chromium.org'],
-    'md_settings': ['dbeam+watch-settings@chromium.org',
-                    'michaelpg+watch-md-settings@chromium.org',
+    'md_settings': ['michaelpg+watch-md-settings@chromium.org',
                     'stevenjb+watch-md-settings@chromium.org'],
     'media': ['feature-media-reviews@chromium.org'],
     'media_capture_from_element': ['emircan+watch+capturefromdom@chromium.org',
@@ -2140,8 +2128,6 @@
                       'mlamouri+watch-notifications@chromium.org',
                       'peter@chromium.org'],
     'nqe': ['tbansal+watch-nqe@chromium.org'],
-    'ntp': ['dbeam+watch-ntp@chromium.org',
-            'pedrosimonetti+watch@chromium.org'],
     'ntp_snippets': ['ntp-dev+reviews@chromium.org',
                      'noyau+watch@chromium.org'],
     'ntp_tiles': ['ntp-dev+reviews@chromium.org',
@@ -2155,8 +2141,7 @@
                       'petewil+watch@chromium.org',
                       'romax+watch@chromium.org'],
     'omnibox': ['jdonnelly+watch@chromium.org'],
-    'options': ['dbeam+watch-options@chromium.org',
-                'michaelpg+watch-options@chromium.org'],
+    'options': ['michaelpg+watch-options@chromium.org'],
     'origin_trials': ['chasej+watch@chromium.org',
                       'iclelland+watch@chromuim.org'],
     'ozone': ['kalyan.kondapally@intel.com',
@@ -2187,8 +2172,7 @@
     'permissions': ['mlamouri+watch-permissions@chromium.org',
                     'raymes+watch@chromium.org'],
     'plugin': ['jam@chromium.org'],
-    'polymer': ['dbeam+watch-polymer@chromium.org',
-                'michaelpg+watch-polymer@chromium.org'],
+    'polymer': ['michaelpg+watch-polymer@chromium.org'],
     'precache': ['wifiprefetch-reviews@google.com'],
     'prepopulated_engines': ['vasilii+watch@chromium.org'],
     'prerender': ['cbentzel+watch@chromium.org',
@@ -2255,11 +2239,11 @@
                     'einbinder+watch-test-runner@chromium.org'],
     'tests': [],
     'tether': ['jlklein+watch-tether@chromium.org',
-                    'khorimoto+watch-tether@chromium.org',
-                    'hansberry+watch-tether@chromium.org',
-                    'lesliewatkins+watch-tether@chromium.org',
-                    'tengs+watch-tether@chromium.org',
-                    'jhawkins+watch-tether@chromium.org'],
+               'khorimoto+watch-tether@chromium.org',
+               'hansberry+watch-tether@chromium.org',
+               'lesliewatkins+watch-tether@chromium.org',
+               'tengs+watch-tether@chromium.org',
+               'jhawkins+watch-tether@chromium.org'],
     'textinput': ['nona+watch@chromium.org',
                   'shuchen+watch@chromium.org',
                   'suzhe@chromium.org',
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc
index 7048489..22dd034e 100644
--- a/ash/display/display_configuration_controller.cc
+++ b/ash/display/display_configuration_controller.cc
@@ -117,11 +117,11 @@
     int64_t display_id,
     display::Display::Rotation rotation,
     display::Display::RotationSource source) {
-  if (display_manager_->GetDisplayInfo(display_id).GetActiveRotation() ==
-      rotation)
-    return;
-
   if (display_manager_->IsDisplayIdValid(display_id)) {
+    if (display_manager_->GetDisplayInfo(display_id).GetActiveRotation() ==
+        rotation) {
+      return;
+    }
     ScreenRotationAnimator* screen_rotation_animator =
         GetScreenRotationAnimatorForDisplay(display_id);
     screen_rotation_animator->Rotate(rotation, source);
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index 247a50d..b33a4e2 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -164,8 +164,6 @@
 
 ScreenRotationAnimator::ScreenRotationAnimator(aura::Window* root_window)
     : root_window_(root_window),
-      screen_rotation_container_layer_(
-          GetScreenRotationContainer(root_window_)->layer()),
       screen_rotation_state_(IDLE),
       rotation_request_id_(0),
       metrics_reporter_(
@@ -241,9 +239,11 @@
 
 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
     std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
+  ui::Layer* screen_rotation_container_layer =
+      GetScreenRotationContainer(root_window_)->layer();
   copy_output_request->set_area(
-      gfx::Rect(screen_rotation_container_layer_->size()));
-  screen_rotation_container_layer_->RequestCopyOfOutput(
+      gfx::Rect(screen_rotation_container_layer->size()));
+  screen_rotation_container_layer->RequestCopyOfOutput(
       std::move(copy_output_request));
 }
 
@@ -326,9 +326,6 @@
 
 void ScreenRotationAnimator::CreateOldLayerTreeForSlowAnimation() {
   old_layer_tree_owner_ = ::wm::RecreateLayers(root_window_);
-  // |screen_rotation_container_layer_| needs update after |RecreateLayers()|.
-  screen_rotation_container_layer_ =
-      GetScreenRotationContainer(root_window_)->layer();
   AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
 }
 
@@ -338,8 +335,8 @@
   std::unique_ptr<cc::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
-
-  const gfx::Rect rect(screen_rotation_container_layer_->size());
+  const gfx::Rect rect(
+      GetScreenRotationContainer(root_window_)->layer()->size());
   std::unique_ptr<ui::Layer> copy_layer = base::MakeUnique<ui::Layer>();
   copy_layer->SetBounds(rect);
   copy_layer->SetTextureMailbox(texture_mailbox, std::move(release_callback),
@@ -361,15 +358,17 @@
   const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2,
                                       rotated_screen_bounds.height() / 2);
 
+  ui::Layer* screen_rotation_container_layer =
+      GetScreenRotationContainer(root_window_)->layer();
   ui::Layer* new_root_layer;
   if (!new_layer_tree_owner_ ||
       has_switch_ash_disable_smooth_screen_rotation_) {
-    new_root_layer = screen_rotation_container_layer_;
+    new_root_layer = screen_rotation_container_layer;
   } else {
     new_root_layer = new_layer_tree_owner_->root();
-    // Add a black mask layer on top of |screen_rotation_container_layer_|.
+    // Add a black mask layer on top of |screen_rotation_container_layer|.
     mask_layer_tree_owner_ = CreateMaskLayerTreeOwner(
-        gfx::Rect(screen_rotation_container_layer_->size()));
+        gfx::Rect(screen_rotation_container_layer->size()));
     AddLayerBelowWindowLayer(root_window_, new_root_layer,
                              mask_layer_tree_owner_->root());
   }
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h
index 35729810..e7a1aa4 100644
--- a/ash/rotator/screen_rotation_animator.h
+++ b/ash/rotator/screen_rotation_animator.h
@@ -25,7 +25,6 @@
 
 namespace ui {
 class AnimationMetricsReporter;
-class Layer;
 class LayerTreeOwner;
 }  // namespace ui
 
@@ -153,7 +152,6 @@
   void StopAnimating();
 
   aura::Window* root_window_;
-  ui::Layer* screen_rotation_container_layer_;
 
   // For current slow rotation animation, there are two states |ROTATING| and
   // |IDLE|. For the smooth rotation animation, we need to send copy request
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
index 33b945c..b9e68ae 100644
--- a/ash/rotator/screen_rotation_animator_unittest.cc
+++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -27,6 +27,7 @@
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
+#include "ui/wm/core/window_util.h"
 
 namespace ash {
 
@@ -569,4 +570,46 @@
   EXPECT_FALSE(GetTray()->visible());
 }
 
+// Test that smooth screen rotation animation will work when |root_window|
+// recreated.
+TEST_F(ScreenRotationAnimatorSmoothAnimationTest,
+       ShouldRotateAfterRecreateLayers) {
+  // TODO(sky): remove this, temporary until mash_unittests as a separate
+  // executable is nuked. http://crbug.com/729810.
+  if (Shell::GetAshConfig() == Config::MASH)
+    return;
+
+  const int64_t display_id = display_manager()->GetDisplayAt(0).id();
+  aura::Window* root_window = GetRootWindow(display_id);
+  SetScreenRotationAnimator(
+      root_window, run_loop_->QuitWhenIdleClosure(),
+      base::Bind(
+          &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback,
+          base::Unretained(this)));
+  SetDisplayRotation(display_id, display::Display::ROTATE_0);
+  animator()->Rotate(display::Display::ROTATE_90,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+  EXPECT_TRUE(test_api()->HasActiveAnimations());
+
+  test_api()->CompleteAnimations();
+  EXPECT_FALSE(test_api()->HasActiveAnimations());
+  EXPECT_EQ(display::Display::ROTATE_90, GetDisplayRotation(display_id));
+
+  // Colone and delete the old layer tree.
+  std::unique_ptr<ui::LayerTreeOwner> old_layer_tree_owner =
+      ::wm::RecreateLayers(root_window);
+  old_layer_tree_owner.reset();
+
+  // Should work for another rotation.
+  animator()->Rotate(display::Display::ROTATE_180,
+                     display::Display::RotationSource::ROTATION_SOURCE_USER);
+  WaitForCopyCallback();
+  EXPECT_TRUE(test_api()->HasActiveAnimations());
+
+  test_api()->CompleteAnimations();
+  EXPECT_FALSE(test_api()->HasActiveAnimations());
+  EXPECT_EQ(display::Display::ROTATE_180, GetDisplayRotation(display_id));
+}
+
 }  // namespace ash
diff --git a/base/threading/watchdog.cc b/base/threading/watchdog.cc
index 339cc56a..6c384b19 100644
--- a/base/threading/watchdog.cc
+++ b/base/threading/watchdog.cc
@@ -179,7 +179,8 @@
 void Watchdog::ResetStaticData() {
   StaticData* static_data = GetStaticData();
   AutoLock lock(static_data->lock);
-  static_data->last_debugged_alarm_time = TimeTicks();
+  // See https://crbug.com/734232 for why this cannot be zero-initialized.
+  static_data->last_debugged_alarm_time = TimeTicks::Min();
   static_data->last_debugged_alarm_delay = TimeDelta();
 }
 
diff --git a/base/time/time.cc b/base/time/time.cc
index 08c4254e..c52482611 100644
--- a/base/time/time.cc
+++ b/base/time/time.cc
@@ -111,7 +111,7 @@
     return rv.ValueOrDie();
   // Positive RHS overflows. Negative RHS underflows.
   if (value < 0)
-    return -std::numeric_limits<int64_t>::max();
+    return std::numeric_limits<int64_t>::min();
   return std::numeric_limits<int64_t>::max();
 }
 
@@ -123,7 +123,7 @@
   // Negative RHS overflows. Positive RHS underflows.
   if (value < 0)
     return std::numeric_limits<int64_t>::max();
-  return -std::numeric_limits<int64_t>::max();
+  return std::numeric_limits<int64_t>::min();
 }
 
 }  // namespace time_internal
diff --git a/base/time/time.h b/base/time/time.h
index 84e18ac..3ff215cb 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -136,6 +136,11 @@
   // delta to a time or another time delta has an undefined result.
   static constexpr TimeDelta Max();
 
+  // Returns the minimum time delta, which should be less than than any
+  // reasonable time delta we might compare it to. Adding or subtracting the
+  // minimum time delta to a time or another time delta has an undefined result.
+  static constexpr TimeDelta Min();
+
   // Returns the internal numeric value of the TimeDelta object. Please don't
   // use this and do arithmetic on it, as it is more error prone than using the
   // provided operators.
@@ -156,8 +161,9 @@
     return delta_ == 0;
   }
 
-  // Returns true if the time delta is the maximum time delta.
+  // Returns true if the time delta is the maximum/minimum time delta.
   bool is_max() const { return delta_ == std::numeric_limits<int64_t>::max(); }
+  bool is_min() const { return delta_ == std::numeric_limits<int64_t>::min(); }
 
 #if defined(OS_POSIX)
   struct timespec ToTimeSpec() const;
@@ -211,7 +217,7 @@
       return TimeDelta(rv.ValueOrDie());
     // Matched sign overflows. Mismatched sign underflows.
     if ((delta_ < 0) ^ (a < 0))
-      return TimeDelta(-std::numeric_limits<int64_t>::max());
+      return TimeDelta(std::numeric_limits<int64_t>::min());
     return TimeDelta(std::numeric_limits<int64_t>::max());
   }
   template<typename T>
@@ -223,7 +229,7 @@
     // Matched sign overflows. Mismatched sign underflows.
     // Special case to catch divide by zero.
     if ((delta_ < 0) ^ (a <= 0))
-      return TimeDelta(-std::numeric_limits<int64_t>::max());
+      return TimeDelta(std::numeric_limits<int64_t>::min());
     return TimeDelta(std::numeric_limits<int64_t>::max());
   }
   template<typename T>
@@ -332,15 +338,20 @@
     return us_ == 0;
   }
 
-  // Returns true if this object represents the maximum time.
+  // Returns true if this object represents the maximum/minimum time.
   bool is_max() const { return us_ == std::numeric_limits<int64_t>::max(); }
+  bool is_min() const { return us_ == std::numeric_limits<int64_t>::min(); }
 
-  // Returns the maximum time, which should be greater than any reasonable time
-  // with which we might compare it.
+  // Returns the maximum/minimum times, which should be greater/less than than
+  // any reasonable time with which we might compare it.
   static TimeClass Max() {
     return TimeClass(std::numeric_limits<int64_t>::max());
   }
 
+  static TimeClass Min() {
+    return TimeClass(std::numeric_limits<int64_t>::min());
+  }
+
   // For serializing only. Use FromInternalValue() to reconstitute. Please don't
   // use this and do arithmetic on it, as it is more error prone than using the
   // provided operators.
@@ -667,13 +678,18 @@
 }
 
 // static
+constexpr TimeDelta TimeDelta::Min() {
+  return TimeDelta(std::numeric_limits<int64_t>::min());
+}
+
+// static
 constexpr TimeDelta TimeDelta::FromDouble(double value) {
   // TODO(crbug.com/612601): Use saturated_cast<int64_t>(value) once we sort out
   // the Min() behavior.
   return value > std::numeric_limits<int64_t>::max()
              ? Max()
-             : value < -std::numeric_limits<int64_t>::max()
-                   ? -Max()
+             : value < std::numeric_limits<int64_t>::min()
+                   ? Min()
                    : TimeDelta(static_cast<int64_t>(value));
 }
 
@@ -682,16 +698,16 @@
                                            int64_t positive_value) {
   return (
 #if !defined(_PREFAST_) || !defined(OS_WIN)
-          // Avoid internal compiler errors in /analyze builds with VS 2015
-          // update 3.
-          // https://connect.microsoft.com/VisualStudio/feedback/details/2870865
-          DCHECK(positive_value > 0),
+      // Avoid internal compiler errors in /analyze builds with VS 2015
+      // update 3.
+      // https://connect.microsoft.com/VisualStudio/feedback/details/2870865
+      DCHECK(positive_value > 0),
 #endif
-          value > std::numeric_limits<int64_t>::max() / positive_value
-              ? Max()
-              : value < -std::numeric_limits<int64_t>::max() / positive_value
-                    ? -Max()
-                    : TimeDelta(value * positive_value));
+      value > std::numeric_limits<int64_t>::max() / positive_value
+          ? Max()
+          : value < std::numeric_limits<int64_t>::min() / positive_value
+                ? Min()
+                : TimeDelta(value * positive_value));
 }
 
 // For logging use only.
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
index 8906c3b..fe675f19 100644
--- a/base/time/time_unittest.cc
+++ b/base/time/time_unittest.cc
@@ -902,7 +902,7 @@
 }
 
 bool IsMin(TimeDelta delta) {
-  return (-delta).is_max();
+  return delta.is_min();
 }
 
 TEST(TimeDelta, MaxConversions) {
@@ -928,6 +928,7 @@
   EXPECT_TRUE(t.is_max());
 
   int64_t max_int = std::numeric_limits<int64_t>::max();
+  int64_t min_int = std::numeric_limits<int64_t>::min();
 
   t = TimeDelta::FromSeconds(max_int / Time::kMicrosecondsPerSecond + 1);
   EXPECT_TRUE(t.is_max());
@@ -938,22 +939,23 @@
   t = TimeDelta::FromMicroseconds(max_int);
   EXPECT_TRUE(t.is_max());
 
-  t = TimeDelta::FromSeconds(-max_int / Time::kMicrosecondsPerSecond - 1);
+  t = TimeDelta::FromSeconds(min_int / Time::kMicrosecondsPerSecond - 1);
   EXPECT_TRUE(IsMin(t));
 
-  t = TimeDelta::FromMilliseconds(-max_int / Time::kMillisecondsPerSecond - 1);
+  t = TimeDelta::FromMilliseconds(min_int / Time::kMillisecondsPerSecond - 1);
   EXPECT_TRUE(IsMin(t));
 
-  t = TimeDelta::FromMicroseconds(-max_int);
+  t = TimeDelta::FromMicroseconds(min_int);
   EXPECT_TRUE(IsMin(t));
 
-  t = -TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::min());
-  EXPECT_FALSE(IsMin(t));
+  t = TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::min());
+  EXPECT_TRUE(IsMin(t));
 
   t = TimeDelta::FromSecondsD(std::numeric_limits<double>::infinity());
   EXPECT_TRUE(t.is_max());
 
   double max_d = max_int;
+  double min_d = min_int;
 
   t = TimeDelta::FromSecondsD(max_d / Time::kMicrosecondsPerSecond + 1);
   EXPECT_TRUE(t.is_max());
@@ -964,10 +966,10 @@
   t = TimeDelta::FromMillisecondsD(max_d / Time::kMillisecondsPerSecond * 2);
   EXPECT_TRUE(t.is_max());
 
-  t = TimeDelta::FromSecondsD(-max_d / Time::kMicrosecondsPerSecond - 1);
+  t = TimeDelta::FromSecondsD(min_d / Time::kMicrosecondsPerSecond - 1);
   EXPECT_TRUE(IsMin(t));
 
-  t = TimeDelta::FromMillisecondsD(-max_d / Time::kMillisecondsPerSecond * 2);
+  t = TimeDelta::FromMillisecondsD(min_d / Time::kMillisecondsPerSecond * 2);
   EXPECT_TRUE(IsMin(t));
 }
 
@@ -1046,7 +1048,8 @@
 TEST(TimeDelta, Overflows) {
   // Some sanity checks.
   EXPECT_TRUE(TimeDelta::Max().is_max());
-  EXPECT_TRUE(IsMin(-TimeDelta::Max()));
+  EXPECT_LT(-TimeDelta::Max(), TimeDelta());
+  EXPECT_GT(-TimeDelta::Max(), TimeDelta::Min());
   EXPECT_GT(TimeDelta(), -TimeDelta::Max());
 
   TimeDelta large_delta = TimeDelta::Max() - TimeDelta::FromMilliseconds(1);
diff --git a/base/trace_event/memory_dump_scheduler_unittest.cc b/base/trace_event/memory_dump_scheduler_unittest.cc
index 17fb7436..8677978 100644
--- a/base/trace_event/memory_dump_scheduler_unittest.cc
+++ b/base/trace_event/memory_dump_scheduler_unittest.cc
@@ -185,7 +185,6 @@
   bg_thread_->Start();
   evt.Reset();
   expected_task_runner = bg_thread_->task_runner();
-  scheduler_->Start(config, bg_thread_->task_runner());
   EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
   EXPECT_CALL(on_tick_, OnTick(_))
       .WillRepeatedly(
@@ -193,6 +192,7 @@
             EXPECT_TRUE(expected_task_runner->RunsTasksOnCurrentThread());
             evt.Signal();
           }));
+  scheduler_->Start(config, bg_thread_->task_runner());
   evt.Wait();
   scheduler_->Stop();
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 13731ba..c5e0ce0 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=61
 MINOR=0
-BUILD=3136
+BUILD=3137
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index 56e225b..bb3ca8b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -451,7 +451,8 @@
 
         // Create a PendingIntent that shares the file with external apps.
         PendingIntent pendingShareIntent = PendingIntent.getActivity(
-                context, 0, createShareIntent(contentUri, mimeType), 0);
+                context, 0, createShareIntent(contentUri, mimeType),
+                PendingIntent.FLAG_CANCEL_CURRENT);
         builder.setActionButton(
                 shareIcon, context.getString(R.string.share), pendingShareIntent, true);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
index 58047ec..e2ce4b8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
@@ -388,7 +388,11 @@
         setVisibilityOfPermissionsList(false);
 
         // Work out the URL and connection message and status visibility.
-        mFullUrl = mTab.getWebContents().getVisibleUrl();
+        mFullUrl = mTab.getOriginalUrl();
+
+        // This can happen if an invalid chrome-distiller:// url was entered.
+        if (mFullUrl == null) mFullUrl = "";
+
         if (isShowingOfflinePage()) {
             mFullUrl = OfflinePageUtils.stripSchemeFromOnlineUrl(mFullUrl);
         }
diff --git a/chrome/browser/android/vr_shell/vr_controller.cc b/chrome/browser/android/vr_shell/vr_controller.cc
index dbd5ea2..182101b 100644
--- a/chrome/browser/android/vr_shell/vr_controller.cc
+++ b/chrome/browser/android/vr_shell/vr_controller.cc
@@ -106,26 +106,29 @@
 }
 
 device::GvrGamepadData VrController::GetGamepadData() {
-  device::GvrGamepadData pad;
-
+  device::GvrGamepadData pad = {};
+  pad.connected = IsConnected();
   pad.timestamp = controller_state_->GetLastOrientationTimestamp();
-  pad.touch_pos.set_x(TouchPosX());
-  pad.touch_pos.set_y(TouchPosY());
-  pad.orientation = Orientation();
 
-  // Use orientation to rotate acceleration/gyro into seated space.
-  gfx::Transform pose_mat(Orientation());
-  const gvr::Vec3f& accel = controller_state_->GetAccel();
-  const gvr::Vec3f& gyro = controller_state_->GetGyro();
-  pad.accel = gfx::Vector3dF(accel.x, accel.y, accel.z);
-  pose_mat.TransformVector(&pad.accel);
-  pad.gyro = gfx::Vector3dF(gyro.x, gyro.y, gyro.z);
-  pose_mat.TransformVector(&pad.gyro);
+  if (pad.connected) {
+    pad.touch_pos.set_x(TouchPosX());
+    pad.touch_pos.set_y(TouchPosY());
+    pad.orientation = Orientation();
 
-  pad.is_touching = controller_state_->IsTouching();
-  pad.controller_button_pressed =
-      controller_state_->GetButtonState(GVR_CONTROLLER_BUTTON_CLICK);
-  pad.right_handed = handedness_ == GVR_CONTROLLER_RIGHT_HANDED;
+    // Use orientation to rotate acceleration/gyro into seated space.
+    gfx::Transform pose_mat(Orientation());
+    const gvr::Vec3f& accel = controller_state_->GetAccel();
+    const gvr::Vec3f& gyro = controller_state_->GetGyro();
+    pad.accel = gfx::Vector3dF(accel.x, accel.y, accel.z);
+    pose_mat.TransformVector(&pad.accel);
+    pad.gyro = gfx::Vector3dF(gyro.x, gyro.y, gyro.z);
+    pose_mat.TransformVector(&pad.gyro);
+
+    pad.is_touching = controller_state_->IsTouching();
+    pad.controller_button_pressed =
+        controller_state_->GetButtonState(GVR_CONTROLLER_BUTTON_CLICK);
+    pad.right_handed = handedness_ == GVR_CONTROLLER_RIGHT_HANDED;
+  }
 
   return pad;
 }
diff --git a/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg b/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg
new file mode 100644
index 0000000..bce77739
--- /dev/null
+++ b/chrome/browser/resources/settings/images/settings_icon_visibility_off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575" preserveAspectRatio="xMidYMid meet"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></svg>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html b/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
index 2003a32..00db6769d 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
@@ -32,6 +32,11 @@
       paper-input {
         width: var(--paper-input-max-width);
       }
+
+      button[is='paper-icon-button-light'] {
+        -webkit-margin-start: 2px;
+        background-size: 24px;  /* Other buttons are sized by --cr-icon-size. */
+      }
     </style>
     <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}">
       <div class="title">$i18n{passwordDetailsTitle}</div>
@@ -52,7 +57,8 @@
             on-tap="onReadonlyInputTap_">
           </paper-input>
           <button is="paper-icon-button-light" id="showPasswordButton"
-              class="icon-visibility" hidden$="[[item.federationText]]"
+              class$="[[getIconClass_(item, password)]]"
+              hidden$="[[item.federationText]]"
               on-tap="onShowPasswordButtonTap_"
               title="[[showPasswordTitle_(password,
                   '$i18nPolymer{hidePassword}','$i18nPolymer{showPassword}')]]">
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js b/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
index 94f958b..6d76f1b 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.js
@@ -56,6 +56,15 @@
   },
 
   /**
+   * Get the right icon to display when hiding/showing a password.
+   * @return {string}
+   * @private
+   */
+  getIconClass_: function() {
+    return this.password ? 'icon-visibility-off' : 'icon-visibility';
+  },
+
+  /**
    * Gets the text of the password. Will use the value of |password| unless it
    * cannot be shown, in which case it will be spaces. It can also be the
    * federated text.
diff --git a/chrome/browser/resources/settings/settings_icons_css.html b/chrome/browser/resources/settings/settings_icons_css.html
index 2e307bd2..0ea4a644 100644
--- a/chrome/browser/resources/settings/settings_icons_css.html
+++ b/chrome/browser/resources/settings/settings_icons_css.html
@@ -10,6 +10,9 @@
       button[is='paper-icon-button-light'].icon-visibility {
         background-image: url(./images/settings_icon_visibility.svg);
       }
+      button[is='paper-icon-button-light'].icon-visibility-off {
+        background-image: url(./images/settings_icon_visibility_off.svg);
+      }
 <if expr="chromeos">
       button[is='paper-icon-button-light'].icon-add-circle {
         background-image: url(./images/settings_icon_add_circle.svg);
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index fdb621c..866d8fd 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -55,8 +55,15 @@
   if (content_settings()) {
     CleanUpExpiredVerdicts();
     UMA_HISTOGRAM_COUNTS_1000(
-        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown",
-        GetStoredVerdictCount());
+        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown."
+        "PasswordOnFocus",
+        GetStoredVerdictCount(
+            LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+    UMA_HISTOGRAM_COUNTS_1000(
+        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown."
+        "ProtectedPasswordEntry",
+        GetStoredVerdictCount(
+            LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
   }
 }
 
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 a30d126..f496f390 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -75,6 +75,7 @@
   }
 
   void CacheVerdict(const GURL& url,
+                    LoginReputationClientRequest::TriggerType trigger_type,
                     LoginReputationClientResponse* verdict,
                     const base::Time& receive_time) override {}
 
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 4b3cf92d..587b8781 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -244,10 +244,6 @@
   }
 }
 
-base::SequencedWorkerPool* ChromeSyncClient::GetBlockingPool() {
-  return content::BrowserThread::GetBlockingPool();
-}
-
 syncer::SyncService* ChromeSyncClient::GetSyncService() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_);
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h
index 83e10fa..7ad51302 100644
--- a/chrome/browser/sync/chrome_sync_client.h
+++ b/chrome/browser/sync/chrome_sync_client.h
@@ -37,7 +37,6 @@
 
   // SyncClient implementation.
   void Initialize() override;
-  base::SequencedWorkerPool* GetBlockingPool() override;
   syncer::SyncService* GetSyncService() override;
   PrefService* GetPrefService() override;
   base::FilePath GetLocalSyncBackendFolder() override;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a3c7c465..0b402fb6 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -103,6 +103,7 @@
     "chrome_select_file_policy.h",
     "confirm_bubble.h",
     "crypto_module_password_dialog.h",
+    "cryptuiapi_shim.h",
     "find_bar/find_bar.h",
     "find_bar/find_bar_state.h",
     "find_bar/find_bar_state_factory.cc",
diff --git a/chrome/browser/ui/cryptuiapi_shim.h b/chrome/browser/ui/cryptuiapi_shim.h
new file mode 100644
index 0000000..404edcb1
--- /dev/null
+++ b/chrome/browser/ui/cryptuiapi_shim.h
@@ -0,0 +1,18 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_CRYPTUIAPI_SHIM_H_
+#define CHROME_BROWSER_UI_CRYPTUIAPI_SHIM_H_
+
+// cryptuiapi.h includes wincrypt.h which defines macros which conflict with
+// OpenSSL's types. This header includes cryptuiapi.h and then wincrypt_shim.h
+// which undefines the OpenSSL macros which conflict. Any Chromium headers
+// which want to include cryptuiapi should instead include this header.
+
+#include <windows.h>
+#include <cryptuiapi.h>
+
+#include "crypto/wincrypt_shim.h"
+
+#endif  // CHROME_BROWSER_UI_CRYPTUIAPI_SHIM_H_
diff --git a/chrome/browser/ui/views/certificate_viewer_win.cc b/chrome/browser/ui/views/certificate_viewer_win.cc
index 03635b4..827ef99f 100644
--- a/chrome/browser/ui/views/certificate_viewer_win.cc
+++ b/chrome/browser/ui/views/certificate_viewer_win.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/certificate_viewer.h"
 
 #include <windows.h>
-#include <cryptuiapi.h>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -16,7 +15,9 @@
 #include "base/task_runner.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/ui/cryptuiapi_shim.h"
 #include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util_win.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/shell_dialogs/base_shell_dialog_win.h"
@@ -53,23 +54,26 @@
                           const scoped_refptr<net::X509Certificate>& cert) {
     // Create a new cert context and store containing just the certificate
     // and its intermediate certificates.
-    PCCERT_CONTEXT cert_list = cert->CreateOSCertChainForCert();
-    CHECK(cert_list);
+    net::ScopedPCCERT_CONTEXT cert_list(
+        net::x509_util::CreateCertContextWithChain(cert.get()));
+    // Perhaps this should show an error instead of silently failing, but it's
+    // probably not even possible to get here with a cert that can't be
+    // converted to a CERT_CONTEXT.
+    if (!cert_list)
+      return;
 
     CRYPTUI_VIEWCERTIFICATE_STRUCT view_info = {0};
     view_info.dwSize = sizeof(view_info);
     view_info.hwndParent = run_state.owner;
     view_info.dwFlags =
         CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE;
-    view_info.pCertContext = cert_list;
+    view_info.pCertContext = cert_list.get();
     HCERTSTORE cert_store = cert_list->hCertStore;
     view_info.cStores = 1;
     view_info.rghStores = &cert_store;
 
     BOOL properties_changed;
     ::CryptUIDlgViewCertificate(&view_info, &properties_changed);
-
-    CertFreeCertificateContext(cert_list);
   }
 
   void OnDialogClosed(const RunState& run_state,
diff --git a/chrome/browser/ui/webui/settings_utils_win.cc b/chrome/browser/ui/webui/settings_utils_win.cc
index b9ed44f..938389e 100644
--- a/chrome/browser/ui/webui/settings_utils_win.cc
+++ b/chrome/browser/ui/webui/settings_utils_win.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/webui/settings_utils.h"
 
 #include <windows.h>
-#include <cryptuiapi.h>
 #include <shellapi.h>
 
 #include "base/bind.h"
@@ -17,6 +16,7 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/ui/cryptuiapi_shim.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/font.h"
diff --git a/chrome/build/chrome.x64.orderfile.sha1 b/chrome/build/chrome.x64.orderfile.sha1
index 0c57591c..e7f17fa 100644
--- a/chrome/build/chrome.x64.orderfile.sha1
+++ b/chrome/build/chrome.x64.orderfile.sha1
@@ -1 +1 @@
-9ae828ec3366bbc58046f009b5195552e1dc3030
\ No newline at end of file
+825f303082d1665fff6307b064bc68108f156c4c
\ No newline at end of file
diff --git a/chrome/build/chrome.x86.orderfile.sha1 b/chrome/build/chrome.x86.orderfile.sha1
index 579424e..2817d31 100644
--- a/chrome/build/chrome.x86.orderfile.sha1
+++ b/chrome/build/chrome.x86.orderfile.sha1
@@ -1 +1 @@
-c30ec6aff8e403cc42964c6a18ffbdf7de85d4a8
\ No newline at end of file
+010d3c684f265987fdcae16b9c8d5fe91c773bea
\ No newline at end of file
diff --git a/chrome/build/chrome_child.x64.orderfile.sha1 b/chrome/build/chrome_child.x64.orderfile.sha1
index 628dd7f..dcc9d45 100644
--- a/chrome/build/chrome_child.x64.orderfile.sha1
+++ b/chrome/build/chrome_child.x64.orderfile.sha1
@@ -1 +1 @@
-389514001c89d7e6049527396cd7624b15dc2456
\ No newline at end of file
+510b0c2fe281479bb3ad1615623e86bee1e7b27b
\ No newline at end of file
diff --git a/chrome/build/chrome_child.x86.orderfile.sha1 b/chrome/build/chrome_child.x86.orderfile.sha1
index f6019aa..3e04a72 100644
--- a/chrome/build/chrome_child.x86.orderfile.sha1
+++ b/chrome/build/chrome_child.x86.orderfile.sha1
@@ -1 +1 @@
-e9133bf86f174c1eb4096de82d39bd83c3d4a6d4
\ No newline at end of file
+56b07f3d23600d4351a7f3343f59127f28fa6f0a
\ No newline at end of file
diff --git a/chrome/common/extensions/api/desktop_capture.json b/chrome/common/extensions/api/desktop_capture.json
index 179e675..7c20978 100644
--- a/chrome/common/extensions/api/desktop_capture.json
+++ b/chrome/common/extensions/api/desktop_capture.json
@@ -30,7 +30,7 @@
             "$ref": "tabs.Tab",
             "name": "targetTab",
             "optional": true,
-            "description": "Optional tab for which the stream is created. If not specified then the resulting stream can be used only by the calling extension. The stream can only be used by frames in the given tab whose security origin matches <code>tab.url</code>."
+            "description": "Optional tab for which the stream is created. If not specified then the resulting stream can be used only by the calling extension. The stream can only be used by frames in the given tab whose security origin matches <code>tab.url</code>. The tab's origin must be a secure origin, e.g. HTTPS."
           },
           {
             "type": "function",
diff --git a/chrome/common/profiling/memlog_stream.h b/chrome/common/profiling/memlog_stream.h
index 7a9e98d..44557a7 100644
--- a/chrome/common/profiling/memlog_stream.h
+++ b/chrome/common/profiling/memlog_stream.h
@@ -5,10 +5,41 @@
 #ifndef CHROME_COMMON_PROFILING_MEMLOG_STREAM_H_
 #define CHROME_COMMON_PROFILING_MEMLOG_STREAM_H_
 
+#include <stdint.h>
+
 #include "build/build_config.h"
 
 namespace profiling {
 
+static const uint32_t kStreamSignature = 0xF6103B71;
+
+static const uint32_t kAllocPacketType = 0xA1A1A1A1;
+static const uint32_t kFreePacketType = 0xFEFEFEFE;
+
+#pragma pack(push, 1)
+struct StreamHeader {
+  uint32_t signature;  // kStreamSignature
+};
+
+struct AllocPacket {
+  uint32_t op;  // = kAllocPacketType
+
+  uint64_t time;
+  uint64_t address;
+  uint64_t size;
+
+  uint32_t stack_len;
+  // Immediately followed by |stack_len| more addresses.
+};
+
+struct FreePacket {
+  uint32_t op;  // = kFreePacketType
+
+  uint64_t time;
+  uint64_t address;
+};
+#pragma pack(pop)
+
 #if defined(OS_WIN)
 // Prefix for pipe name for communicating between chrome processes and the
 // memlog process. The pipe ID is appended to this to get the pipe name.
diff --git a/chrome/profiling/BUILD.gn b/chrome/profiling/BUILD.gn
index 3a273e2..1adceab 100644
--- a/chrome/profiling/BUILD.gn
+++ b/chrome/profiling/BUILD.gn
@@ -7,10 +7,23 @@
 if (enable_oop_heap_profiling) {
   static_library("profiling") {
     sources = [
+      "address.h",
+      "allocation_tracker.cc",
+      "allocation_tracker.h",
+      "backtrace.cc",
+      "backtrace.h",
+      "backtrace_storage.cc",
+      "backtrace_storage.h",
+      "memlog_connection_manager.cc",
+      "memlog_connection_manager.h",
+      "memlog_receiver.h",
+      "memlog_receiver_pipe_server.h",
       "memlog_receiver_pipe_server_win.cc",
       "memlog_receiver_pipe_server_win.h",
       "memlog_receiver_pipe_win.cc",
       "memlog_receiver_pipe_win.h",
+      "memlog_stream_parser.cc",
+      "memlog_stream_parser.h",
       "memlog_stream_receiver.h",
       "profiling_globals.cc",
       "profiling_globals.h",
diff --git a/chrome/profiling/README.md b/chrome/profiling/README.md
index ea5ffa8..4501ecf3 100644
--- a/chrome/profiling/README.md
+++ b/chrome/profiling/README.md
@@ -1,6 +1,11 @@
 # chrome/profiling
 
-This directory contains the code for the "profiling" process.
+This directory contains the code for the "profiling" process. This is in
+active development and is not ready for use.
+
+Design doc: https://docs.google.com/document/d/1eRAgOFgHwYEPge8G1_5UEvu8TJs5VkYCxd6aFU8AIKY
 
 Currently this is used for out-of-process logging of heap profiling data and
-is enabled by setting the GN flag `enable_oop_heap_profiling`.
+is enabled by setting the GN flag `enable_oop_heap_profiling`. The in-process
+code that communicates with the profiling process is in
+`//chrome/common/profiling`.
diff --git a/chrome/profiling/address.h b/chrome/profiling/address.h
new file mode 100644
index 0000000..40d8642
--- /dev/null
+++ b/chrome/profiling/address.h
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_ADDRESS_H_
+#define CHROME_PROFILING_ADDRESS_H_
+
+#include <stdint.h>
+
+#include <functional>
+#include <iosfwd>
+
+#include "base/hash.h"
+
+namespace profiling {
+
+// Wrapper around an address in the instrumented process. This wrapper should
+// be a zero-overhead abstraction around a 64-bit integer (so pass by value)
+// that prevents getting confused between addresses in the local process and
+// ones in the instrumented process.
+struct Address {
+  Address() : value(0) {}
+  explicit Address(uint64_t v) : value(v) {}
+
+  uint64_t value;
+
+  bool operator<(Address other) const { return value < other.value; }
+  bool operator<=(Address other) const { return value <= other.value; }
+  bool operator>(Address other) const { return value > other.value; }
+  bool operator>=(Address other) const { return value >= other.value; }
+
+  bool operator==(Address other) const { return value == other.value; }
+  bool operator!=(Address other) const { return value != other.value; }
+
+  Address operator+(int64_t delta) const { return Address(value + delta); }
+  Address operator+=(int64_t delta) {
+    value += delta;
+    return *this;
+  }
+
+  Address operator-(int64_t delta) const { return Address(value - delta); }
+  Address operator-=(int64_t delta) {
+    value -= delta;
+    return *this;
+  }
+
+  int64_t operator-(Address a) const { return value - a.value; }
+};
+
+}  // namespace profiling
+
+namespace std {
+
+template <>
+struct hash<profiling::Address> {
+  typedef profiling::Address argument_type;
+  typedef uint32_t result_type;
+  result_type operator()(argument_type a) const {
+    return base::Hash(reinterpret_cast<char*>(&a.value), sizeof(int64_t));
+  }
+};
+
+}  // namespace std
+
+std::ostream& operator<<(std::ostream& out, profiling::Address a);
+
+#endif  // CHROME_PROFILING_ADDRESS_H_
diff --git a/chrome/profiling/allocation_tracker.cc b/chrome/profiling/allocation_tracker.cc
new file mode 100644
index 0000000..89c3b4b0
--- /dev/null
+++ b/chrome/profiling/allocation_tracker.cc
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/profiling/allocation_tracker.h"
+
+#include "base/callback.h"
+#include "chrome/profiling/backtrace_storage.h"
+#include "chrome/profiling/profiling_globals.h"
+
+namespace profiling {
+
+AllocationTracker::Alloc::Alloc(size_t sz, BacktraceStorage::Key key)
+    : size(sz), backtrace_key(key) {}
+
+AllocationTracker::AllocationTracker(CompleteCallback complete_cb)
+    : complete_callback_(std::move(complete_cb)),
+      backtrace_storage_(ProfilingGlobals::Get()->GetBacktraceStorage()) {}
+
+AllocationTracker::~AllocationTracker() {
+  std::vector<BacktraceStorage::Key> to_free;
+  to_free.reserve(live_allocs_.size());
+  for (const auto& cur : live_allocs_)
+    to_free.push_back(cur.second.backtrace_key);
+  backtrace_storage_->Free(to_free);
+}
+
+void AllocationTracker::OnHeader(const StreamHeader& header) {}
+
+void AllocationTracker::OnAlloc(const AllocPacket& alloc_packet,
+                                std::vector<Address>&& bt) {
+  BacktraceStorage::Key backtrace_key =
+      backtrace_storage_->Insert(std::move(bt));
+  live_allocs_.emplace(Address(alloc_packet.address),
+                       Alloc(alloc_packet.size, backtrace_key));
+}
+
+void AllocationTracker::OnFree(const FreePacket& free_packet) {
+  auto found = live_allocs_.find(Address(free_packet.address));
+  if (found != live_allocs_.end()) {
+    backtrace_storage_->Free(found->second.backtrace_key);
+    live_allocs_.erase(found);
+  }
+}
+
+void AllocationTracker::OnComplete() {
+  std::move(complete_callback_).Run();
+  // Danger: object may be deleted now.
+}
+
+}  // namespace profiling
diff --git a/chrome/profiling/allocation_tracker.h b/chrome/profiling/allocation_tracker.h
new file mode 100644
index 0000000..5aa8ea4
--- /dev/null
+++ b/chrome/profiling/allocation_tracker.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_ALLOCATION_TRACKER_H_
+#define CHROME_PROFILING_ALLOCATION_TRACKER_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "chrome/profiling/backtrace_storage.h"
+#include "chrome/profiling/memlog_receiver.h"
+
+namespace profiling {
+
+// Tracks live allocations in one process. This is an analogue to memory-infra
+// allocation register and needs to be merged/deduped.
+class AllocationTracker : public MemlogReceiver {
+ public:
+  using CompleteCallback = base::OnceClosure;
+
+  explicit AllocationTracker(CompleteCallback complete_cb);
+  ~AllocationTracker() override;
+
+  void OnHeader(const StreamHeader& header) override;
+  void OnAlloc(const AllocPacket& alloc_packet,
+               std::vector<Address>&& bt) override;
+  void OnFree(const FreePacket& free_packet) override;
+  void OnComplete() override;
+
+ private:
+  CompleteCallback complete_callback_;
+
+  struct Alloc {
+    Alloc(size_t sz, BacktraceStorage::Key key);
+
+    size_t size;
+    BacktraceStorage::Key backtrace_key;
+  };
+
+  // Cached pointer to the global singleton.
+  BacktraceStorage* backtrace_storage_;
+
+  std::map<Address, Alloc> live_allocs_;
+
+  DISALLOW_COPY_AND_ASSIGN(AllocationTracker);
+};
+
+}  // namespace profiling
+
+#endif  // CHROME_PROFILING_ALLOCATION_TRACKER_H_
diff --git a/chrome/profiling/backtrace.cc b/chrome/profiling/backtrace.cc
new file mode 100644
index 0000000..29094da
--- /dev/null
+++ b/chrome/profiling/backtrace.cc
@@ -0,0 +1,50 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/profiling/backtrace.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include "base/hash.h"
+#include "chrome/profiling/backtrace_storage.h"
+#include "chrome/profiling/profiling_globals.h"
+
+namespace profiling {
+
+namespace {
+
+// TODO(ajwong) replace with a fingerprint capable hash.
+size_t ComputeHash(const std::vector<Address>& addrs) {
+  if (addrs.empty())
+    return 0;
+  // Assume Address is a POD containing only the address with no padding.
+  return base::Hash(reinterpret_cast<const char*>(&addrs[0]),
+                    addrs.size() * sizeof(Address));
+}
+
+}  // namespace
+
+Backtrace::Backtrace(std::vector<Address>&& a)
+    : addrs_(std::move(a)), fingerprint_(ComputeHash(addrs_)) {}
+
+Backtrace::Backtrace(Backtrace&& other) noexcept = default;
+
+Backtrace::~Backtrace() {}
+
+Backtrace& Backtrace::operator=(Backtrace&& other) = default;
+
+bool Backtrace::operator==(const Backtrace& other) const {
+  if (addrs_.size() != other.addrs_.size())
+    return false;
+  return memcmp(addrs_.data(), other.addrs_.data(),
+                addrs_.size() * sizeof(Address)) == 0;
+}
+
+bool Backtrace::operator!=(const Backtrace& other) const {
+  return !operator==(other);
+}
+
+}  // namespace profiling
diff --git a/chrome/profiling/backtrace.h b/chrome/profiling/backtrace.h
new file mode 100644
index 0000000..8e364446
--- /dev/null
+++ b/chrome/profiling/backtrace.h
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_BACKTRACE_H_
+#define CHROME_PROFILING_BACKTRACE_H_
+
+#include <functional>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/profiling/address.h"
+
+namespace profiling {
+
+// Holds a move-only stack backtrace and a precomputed hash. This backtrace
+// uses addresses in the instrumented process. This is in contrast to
+// base::StackTrace which is for getting and working with stack traces in the
+// current process.
+//
+// This is immutable since we assume it can be read from multiple threads
+// without locking.
+//
+// This class has a ref_count member which is used by the allocation tracker
+// to track references to the stack. The reference counting is managed
+// externally. Tracking live objects with a global atom list in a threadsafe
+// manner is much more difficult if this class derives from RefCount.
+class Backtrace {
+ public:
+  // Move-only class. Backtraces should be managed by BacktraceStorage and
+  // we shouldn't be copying vectors around.
+  explicit Backtrace(std::vector<Address>&& a);
+  Backtrace(Backtrace&& other) noexcept;
+  ~Backtrace();
+
+  Backtrace& operator=(Backtrace&& other);
+
+  bool operator==(const Backtrace& other) const;
+  bool operator!=(const Backtrace& other) const;
+
+  const std::vector<Address>& addrs() const;
+
+  size_t fingerprint() const { return fingerprint_; }
+
+ private:
+  friend class BacktraceStorage;  // Only BacktraceStorage can do ref counting.
+
+  // The reference counting is not threadsafe. it's assumed the
+  // BacktraceStorage is the only class accessing this, and it's done inside a
+  // lock.
+  void AddRef() const { ref_count_++; }
+  bool Release() const {  // Returns whether the result is non-zero.
+    return !!(--ref_count_);
+  }
+
+  std::vector<Address> addrs_;
+  size_t fingerprint_;
+  mutable int ref_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(Backtrace);
+};
+
+}  // namespace profiling
+
+namespace std {
+
+template <>
+struct hash<profiling::Backtrace> {
+  using argument_type = profiling::Backtrace;
+  using result_type = size_t;
+  result_type operator()(const argument_type& s) const {
+    return s.fingerprint();
+  }
+};
+
+}  // namespace std
+
+#endif  // CHROME_PROFILING_BACKTRACE_H_
diff --git a/chrome/profiling/backtrace_storage.cc b/chrome/profiling/backtrace_storage.cc
new file mode 100644
index 0000000..5d47fe9
--- /dev/null
+++ b/chrome/profiling/backtrace_storage.cc
@@ -0,0 +1,44 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/profiling/backtrace_storage.h"
+
+#include "chrome/profiling/backtrace.h"
+
+namespace profiling {
+
+BacktraceStorage::BacktraceStorage() {}
+
+BacktraceStorage::~BacktraceStorage() {}
+
+BacktraceStorage::Key BacktraceStorage::Insert(std::vector<Address>&& bt) {
+  base::AutoLock lock(lock_);
+
+  BacktraceStorage::Key key =
+      backtraces_.insert(Backtrace(std::move(bt))).first;
+  key->AddRef();
+  return key;
+}
+
+void BacktraceStorage::Free(const Key& key) {
+  base::AutoLock lock(lock_);
+  if (!key->Release())
+    backtraces_.erase(key);
+}
+
+void BacktraceStorage::Free(const std::vector<Key>& keys) {
+  base::AutoLock lock(lock_);
+  for (size_t i = 0; i < keys.size(); i++) {
+    if (!keys[i]->Release())
+      backtraces_.erase(keys[i]);
+  }
+}
+
+const Backtrace& BacktraceStorage::GetBacktraceForKey(const Key& key) const {
+  // Since the caller should own a reference to the key and the container has
+  // stable iterators, we can access without a lock.
+  return *key;
+}
+
+}  // namespace profiling
diff --git a/chrome/profiling/backtrace_storage.h b/chrome/profiling/backtrace_storage.h
new file mode 100644
index 0000000..a3d7358
--- /dev/null
+++ b/chrome/profiling/backtrace_storage.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_BACKTRACE_STORAGE_H_
+#define CHROME_PROFILING_BACKTRACE_STORAGE_H_
+
+#include <unordered_set>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "chrome/profiling/backtrace.h"
+
+namespace profiling {
+
+// This class is threadsafe.
+class BacktraceStorage {
+ public:
+  using Container = std::unordered_set<Backtrace>;
+  using Key = Container::iterator;
+
+  BacktraceStorage();
+  ~BacktraceStorage();
+
+  // Adds the given backtrace to the storage and returns a key to it. If a
+  // matching backtrace already exists, a key to the existing one will be
+  // returned.
+  //
+  // The returned key will have a reference count associated with it, call
+  // Free when the key is no longer needed.
+  Key Insert(std::vector<Address>&& bt);
+
+  // Frees one reference to a backtrace.
+  void Free(const Key& key);
+  void Free(const std::vector<Key>& keys);
+
+  // Returns the backtrace associated with the given key. Assumes the caller
+  // holds a key to it that will keep the backtrace in scope.
+  const Backtrace& GetBacktraceForKey(const Key& key) const;
+
+ private:
+  mutable base::Lock lock_;
+
+  // List of live backtraces for de-duping. Protected by the lock_.
+  Container backtraces_;
+};
+
+}  // namespace profiling
+
+#endif  // CHROME_PROFILING_BACKTRACE_STORAGE_H_
diff --git a/chrome/profiling/memlog_connection_manager.cc b/chrome/profiling/memlog_connection_manager.cc
new file mode 100644
index 0000000..a9e43bc
--- /dev/null
+++ b/chrome/profiling/memlog_connection_manager.cc
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/profiling/memlog_connection_manager.h"
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread.h"
+#include "chrome/profiling/allocation_tracker.h"
+#include "chrome/profiling/memlog_stream_parser.h"
+#include "chrome/profiling/profiling_globals.h"
+
+namespace profiling {
+
+struct MemlogConnectionManager::Connection {
+  Connection(AllocationTracker::CompleteCallback complete_cb,
+             int process_id,
+             scoped_refptr<MemlogReceiverPipe> p)
+      : thread(base::StringPrintf("Proc %d thread", process_id)),
+        pipe(p),
+        tracker(std::move(complete_cb)) {}
+
+  ~Connection() {}
+
+  base::Thread thread;
+
+  scoped_refptr<MemlogReceiverPipe> pipe;
+  scoped_refptr<MemlogStreamParser> parser;
+  AllocationTracker tracker;
+};
+
+MemlogConnectionManager::MemlogConnectionManager() {}
+
+MemlogConnectionManager::~MemlogConnectionManager() {
+  // Clear the callback since the server is refcounted and may outlive us.
+  server_->set_on_new_connection(
+      base::RepeatingCallback<void(scoped_refptr<MemlogReceiverPipe>)>());
+}
+
+void MemlogConnectionManager::StartConnections(const std::string& pipe_id) {
+  server_ = new MemlogReceiverPipeServer(
+      ProfilingGlobals::Get()->GetIORunner(), pipe_id,
+      base::BindRepeating(&MemlogConnectionManager::OnNewConnection,
+                          base::Unretained(this)));
+  server_->Start();
+}
+
+void MemlogConnectionManager::OnNewConnection(
+    scoped_refptr<MemlogReceiverPipe> new_pipe) {
+  int remote_process = new_pipe->GetRemoteProcessID();
+
+  // Task to post to clean up the connection. Don't need to retain |this| since
+  // it wil be called by objects owned by the MemlogConnectionManager.
+  AllocationTracker::CompleteCallback complete_cb = base::BindOnce(
+      &MemlogConnectionManager::OnConnectionCompleteThunk,
+      base::Unretained(this), base::MessageLoop::current()->task_runner(),
+      remote_process);
+
+  std::unique_ptr<Connection> connection = base::MakeUnique<Connection>(
+      std::move(complete_cb), remote_process, new_pipe);
+  connection->thread.Start();
+
+  connection->parser = new MemlogStreamParser(&connection->tracker);
+  new_pipe->SetReceiver(connection->thread.task_runner(), connection->parser);
+
+  connections_[remote_process] = std::move(connection);
+}
+
+void MemlogConnectionManager::OnConnectionComplete(int process_id) {
+  auto found = connections_.find(process_id);
+  CHECK(found != connections_.end());
+  connections_.erase(found);
+
+  // When all connections are closed, exit.
+  if (connections_.empty())
+    ProfilingGlobals::Get()->QuitWhenIdle();
+}
+
+// Posts back to the given thread the connection complete message.
+void MemlogConnectionManager::OnConnectionCompleteThunk(
+    scoped_refptr<base::SingleThreadTaskRunner> main_loop,
+    int process_id) {
+  // This code is called by the allocation tracker which is owned by the
+  // connection manager. When we tell the connection manager a connection is
+  // done, we know the conncetion manager will still be in scope.
+  main_loop->PostTask(FROM_HERE,
+                      base::Bind(&MemlogConnectionManager::OnConnectionComplete,
+                                 base::Unretained(this), process_id));
+}
+
+}  // namespace profiling
diff --git a/chrome/profiling/memlog_connection_manager.h b/chrome/profiling/memlog_connection_manager.h
new file mode 100644
index 0000000..90879aa1
--- /dev/null
+++ b/chrome/profiling/memlog_connection_manager.h
@@ -0,0 +1,58 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_MEMLOG_CONNECTION_MANAGER_H_
+#define CHROME_PROFILING_MEMLOG_CONNECTION_MANAGER_H_
+
+#include <string>
+
+#include "base/containers/flat_map.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "chrome/profiling/backtrace_storage.h"
+#include "chrome/profiling/memlog_receiver_pipe_server.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace profiling {
+
+// Manages all connections and logging for each process. Pipes are supplied by
+// the pipe server and this class will connect them to a parser and logger.
+class MemlogConnectionManager {
+ public:
+  MemlogConnectionManager();
+  ~MemlogConnectionManager();
+
+  // Starts listening for connections.
+  void StartConnections(const std::string& pipe_id);
+
+ private:
+  struct Connection;
+
+  // Called by the pipe server when a new pipe is created.
+  void OnNewConnection(scoped_refptr<MemlogReceiverPipe> new_pipe);
+
+  // Notification that a connection is complete. Unlike OnNewConnection which
+  // is signaled by the pipe server, this is signaled by the allocation tracker
+  // to ensure that the pipeline for this process has been flushed of all
+  // messages.
+  void OnConnectionComplete(int process_id);
+
+  void OnConnectionCompleteThunk(
+      scoped_refptr<base::SingleThreadTaskRunner> main_loop,
+      int process_id);
+
+  scoped_refptr<MemlogReceiverPipeServer> server_;
+
+  // Maps process ID to the connection information for it.
+  base::flat_map<int, std::unique_ptr<Connection>> connections_;
+
+  DISALLOW_COPY_AND_ASSIGN(MemlogConnectionManager);
+};
+
+}  // namespace profiling
+
+#endif  // CHROME_PROFILING_MEMLOG_CONNECTION_MANAGER_H_
diff --git a/chrome/profiling/memlog_receiver.h b/chrome/profiling/memlog_receiver.h
new file mode 100644
index 0000000..49f94fbb
--- /dev/null
+++ b/chrome/profiling/memlog_receiver.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_MEMLOG_RECEIVER_H_
+#define CHROME_PROFILING_MEMLOG_RECEIVER_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "chrome/common/profiling/memlog_stream.h"
+#include "chrome/profiling/address.h"
+
+namespace profiling {
+
+// A log receiver is a sink for parsed allocation events. See also
+// MemlogStreamReceiver which is for the unparsed data blocks.
+class MemlogReceiver {
+ public:
+  virtual ~MemlogReceiver() {}
+
+  virtual void OnHeader(const StreamHeader& header) = 0;
+  virtual void OnAlloc(const AllocPacket& alloc_packet,
+                       std::vector<Address>&& stack) = 0;
+  virtual void OnFree(const FreePacket& free_packet) = 0;
+  virtual void OnComplete() = 0;
+};
+
+}  // namespace profiling
+
+#endif  // CHROME_PROFILING_MEMLOG_RECEIVER_H_
diff --git a/chrome/profiling/memlog_receiver_pipe_server.h b/chrome/profiling/memlog_receiver_pipe_server.h
new file mode 100644
index 0000000..5ef925ac3
--- /dev/null
+++ b/chrome/profiling/memlog_receiver_pipe_server.h
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_MEMLOG_RECEIVER_PIPE_SERVER_H_
+#define CHROME_PROFILING_MEMLOG_RECEIVER_PIPE_SERVER_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "memlog_receiver_pipe_server_win.h"
+#endif
+
+#endif  // CHROME_PROFILING_MEMLOG_RECEIVER_PIPE_SERVER_H_
diff --git a/chrome/profiling/memlog_stream_parser.cc b/chrome/profiling/memlog_stream_parser.cc
new file mode 100644
index 0000000..b67d0d7
--- /dev/null
+++ b/chrome/profiling/memlog_stream_parser.cc
@@ -0,0 +1,163 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/profiling/memlog_stream_parser.h"
+
+#include <algorithm>
+
+#include "base/containers/stack_container.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/common/profiling/memlog_stream.h"
+#include "chrome/profiling/address.h"
+#include "chrome/profiling/backtrace.h"
+#include "chrome/profiling/profiling_globals.h"
+
+namespace profiling {
+
+namespace {
+
+using AddressVector = base::StackVector<Address, 128>;
+
+}  // namespace
+
+MemlogStreamParser::Block::Block(std::unique_ptr<char[]> d, size_t s)
+    : data(std::move(d)), size(s) {}
+
+MemlogStreamParser::MemlogStreamParser(MemlogReceiver* receiver)
+    : receiver_(receiver) {}
+
+MemlogStreamParser::~MemlogStreamParser() {}
+
+void MemlogStreamParser::OnStreamData(std::unique_ptr<char[]> data, size_t sz) {
+  blocks_.emplace_back(std::move(data), sz);
+
+  if (!received_header_) {
+    received_header_ = true;
+    ReadStatus status = ParseHeader();
+    if (status != READ_OK)
+      return;  // TODO(brettw) signal error.
+  }
+
+  while (true) {
+    uint32_t msg_type;
+    if (!PeekBytes(sizeof(msg_type), &msg_type))
+      return;
+
+    ReadStatus status;
+    switch (msg_type) {
+      case kAllocPacketType:
+        status = ParseAlloc();
+        break;
+      case kFreePacketType:
+        status = ParseFree();
+        break;
+      default:
+        return;  // TODO(brettw) signal error.
+    }
+    if (status != READ_OK)
+      return;  // TODO(brettw) signal error.
+  }
+}
+
+void MemlogStreamParser::OnStreamComplete() {
+  receiver_->OnComplete();
+}
+
+bool MemlogStreamParser::AreBytesAvailable(size_t count) const {
+  size_t used = 0;
+  size_t current_block_offset = block_zero_offset_;
+  for (auto it = blocks_.begin(); it != blocks_.end() && used < count; ++it) {
+    used += it->size - current_block_offset;
+    current_block_offset = 0;
+  }
+  return used >= count;
+}
+
+bool MemlogStreamParser::PeekBytes(size_t count, void* dest) const {
+  char* dest_char = static_cast<char*>(dest);
+  size_t used = 0;
+
+  size_t current_block_offset = block_zero_offset_;
+  for (const auto& block : blocks_) {
+    size_t in_current_block = block.size - current_block_offset;
+    size_t to_copy = std::min(count - used, in_current_block);
+
+    memcpy(&dest_char[used], &block.data[current_block_offset], to_copy);
+    used += to_copy;
+
+    // All subsequent blocks start reading at offset 0.
+    current_block_offset = 0;
+  }
+  return used == count;
+}
+
+bool MemlogStreamParser::ReadBytes(size_t count, void* dest) {
+  if (!PeekBytes(count, dest))
+    return false;
+  ConsumeBytes(count);
+  return true;
+}
+
+void MemlogStreamParser::ConsumeBytes(size_t count) {
+  DCHECK(AreBytesAvailable(count));
+  while (count > 0) {
+    size_t bytes_left_in_block = blocks_.front().size - block_zero_offset_;
+    if (bytes_left_in_block > count) {
+      // Still data left in this block;
+      block_zero_offset_ += count;
+      return;
+    }
+
+    // Current block is consumed.
+    blocks_.pop_front();
+    block_zero_offset_ = 0;
+    count -= bytes_left_in_block;
+  }
+}
+
+MemlogStreamParser::ReadStatus MemlogStreamParser::ParseHeader() {
+  StreamHeader header;
+  if (!ReadBytes(sizeof(StreamHeader), &header))
+    return READ_NO_DATA;
+
+  if (header.signature != kStreamSignature)
+    return READ_ERROR;
+
+  receiver_->OnHeader(header);
+  return READ_OK;
+}
+
+MemlogStreamParser::ReadStatus MemlogStreamParser::ParseAlloc() {
+  // Read the packet. Can't commit the read until the stack is read and
+  // that has to be done below.
+  AllocPacket alloc_packet;
+  if (!PeekBytes(sizeof(AllocPacket), &alloc_packet))
+    return READ_NO_DATA;
+
+  std::vector<Address> stack;
+  stack.resize(alloc_packet.stack_len);
+  size_t stack_byte_size = sizeof(Address) * alloc_packet.stack_len;
+
+  if (!AreBytesAvailable(sizeof(AllocPacket) + stack_byte_size))
+    return READ_NO_DATA;
+
+  // Everything will fit, mark packet consumed, read stack.
+  ConsumeBytes(sizeof(AllocPacket));
+  if (!stack.empty())
+    ReadBytes(stack_byte_size, stack.data());
+
+  receiver_->OnAlloc(alloc_packet, std::move(stack));
+  return READ_OK;
+}
+
+MemlogStreamParser::ReadStatus MemlogStreamParser::ParseFree() {
+  FreePacket free_packet;
+  if (!ReadBytes(sizeof(FreePacket), &free_packet))
+    return READ_NO_DATA;
+
+  receiver_->OnFree(free_packet);
+  return READ_OK;
+}
+
+}  // namespace profiling
diff --git a/chrome/profiling/memlog_stream_parser.h b/chrome/profiling/memlog_stream_parser.h
new file mode 100644
index 0000000..e2d0e48a
--- /dev/null
+++ b/chrome/profiling/memlog_stream_parser.h
@@ -0,0 +1,68 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PROFILING_MEMLOG_STREAM_PARSER_H_
+#define CHROME_PROFILING_MEMLOG_STREAM_PARSER_H_
+
+#include <deque>
+
+#include "base/macros.h"
+#include "chrome/profiling/memlog_receiver.h"
+#include "chrome/profiling/memlog_stream_receiver.h"
+
+namespace profiling {
+
+// Parses a memory stream. Refcounted via StreamReceiver.
+class MemlogStreamParser : public MemlogStreamReceiver {
+ public:
+  // Receiver must outlive this class.
+  explicit MemlogStreamParser(MemlogReceiver* receiver);
+  ~MemlogStreamParser() override;
+
+  // StreamReceiver implementation.
+  void OnStreamData(std::unique_ptr<char[]> data, size_t sz) override;
+  void OnStreamComplete() override;
+
+ private:
+  struct Block {
+    Block(std::unique_ptr<char[]> d, size_t s);
+
+    std::unique_ptr<char[]> data;
+    size_t size;
+  };
+
+  enum ReadStatus {
+    READ_OK,      // Read OK.
+    READ_ERROR,   // Fatal error, don't send more data.
+    READ_NO_DATA  // Not enough data, try again when we get more
+  };
+
+  // Returns true if the given number of bytes are available now.
+  bool AreBytesAvailable(size_t count) const;
+
+  // Returns false if not enough bytes are available. On failure, the dest
+  // buffer will be in an undefined state (it may be written partially).
+  bool PeekBytes(size_t count, void* dest) const;
+  bool ReadBytes(size_t count, void* dest);
+  void ConsumeBytes(size_t count);  // Bytes must be available.
+
+  ReadStatus ParseHeader();
+  ReadStatus ParseAlloc();
+  ReadStatus ParseFree();
+
+  MemlogReceiver* receiver_;  // Not owned by this class.
+
+  std::deque<Block> blocks_;
+
+  bool received_header_ = false;
+
+  // Current offset into blocks_[0] of the next packet to process.
+  size_t block_zero_offset_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(MemlogStreamParser);
+};
+
+}  // namespace profiling
+
+#endif  // CHROME_PROFILING_MEMLOG_STREAM_PARSER_H_
diff --git a/chrome/profiling/profiling_globals.cc b/chrome/profiling/profiling_globals.cc
index 5cd552e..ec31381 100644
--- a/chrome/profiling/profiling_globals.cc
+++ b/chrome/profiling/profiling_globals.cc
@@ -32,6 +32,14 @@
   return io_thread_.task_runner().get();
 }
 
+MemlogConnectionManager* ProfilingGlobals::GetMemlogConnectionManager() {
+  return &memlog_connection_manager_;
+}
+
+BacktraceStorage* ProfilingGlobals::GetBacktraceStorage() {
+  return &backtrace_storage_;
+}
+
 scoped_refptr<base::SingleThreadTaskRunner> ProfilingGlobals::GetMainThread()
     const {
   CHECK(base::MessageLoop::current() == main_message_loop_);
diff --git a/chrome/profiling/profiling_globals.h b/chrome/profiling/profiling_globals.h
index 84060a7..25970a8 100644
--- a/chrome/profiling/profiling_globals.h
+++ b/chrome/profiling/profiling_globals.h
@@ -10,6 +10,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread.h"
+#include "chrome/profiling/backtrace_storage.h"
+#include "chrome/profiling/memlog_connection_manager.h"
 
 namespace base {
 class MessageLoopForUI;
@@ -24,6 +26,8 @@
   static ProfilingGlobals* Get();
 
   base::TaskRunner* GetIORunner();
+  MemlogConnectionManager* GetMemlogConnectionManager();
+  BacktraceStorage* GetBacktraceStorage();
 
   // Returns non-null when inside RunMainMessageLoop. Call only on the
   // main thread (otherwise there's a shutdown race).
@@ -40,6 +44,8 @@
   base::MessageLoopForUI* main_message_loop_ = nullptr;
 
   base::Thread io_thread_;
+  MemlogConnectionManager memlog_connection_manager_;
+  BacktraceStorage backtrace_storage_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfilingGlobals);
 };
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 03a3afa..3c0c461 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -467,9 +467,8 @@
                                       render_process_id, false)) {
     original_runner->PostTask(
         FROM_HERE,
-        base::Bind(continue_callback,
-                   make_scoped_refptr(CastNetworkDelegate::DeviceCert()),
-                   make_scoped_refptr(CastNetworkDelegate::DeviceKey())));
+        base::Bind(continue_callback, CastNetworkDelegate::DeviceCert(),
+                   CastNetworkDelegate::DeviceKey()));
     return;
   } else {
     LOG(ERROR) << "Invalid host for client certificate request: "
diff --git a/chromecast/browser/cast_network_delegate.h b/chromecast/browser/cast_network_delegate.h
index 8b72739..66be4ec 100644
--- a/chromecast/browser/cast_network_delegate.h
+++ b/chromecast/browser/cast_network_delegate.h
@@ -18,14 +18,14 @@
 
 class CastNetworkDelegate : public net::NetworkDelegateImpl {
  public:
-  static CastNetworkDelegate* Create();
-  static net::X509Certificate* DeviceCert();
-  static net::SSLPrivateKey* DeviceKey();
+  static std::unique_ptr<CastNetworkDelegate> Create();
+  static scoped_refptr<net::X509Certificate> DeviceCert();
+  static scoped_refptr<net::SSLPrivateKey> DeviceKey();
 
   CastNetworkDelegate();
   ~CastNetworkDelegate() override;
 
-  virtual void Initialize(bool use_sync_signing) = 0;
+  virtual void Initialize() = 0;
 
   virtual bool IsWhitelisted(const GURL& gurl, int render_process_id,
                              bool for_device_auth) const = 0;
diff --git a/chromecast/browser/cast_network_delegate_simple.cc b/chromecast/browser/cast_network_delegate_simple.cc
index 0657bda7..86f946b 100644
--- a/chromecast/browser/cast_network_delegate_simple.cc
+++ b/chromecast/browser/cast_network_delegate_simple.cc
@@ -5,6 +5,9 @@
 #include "chromecast/browser/cast_network_delegate.h"
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "net/cert/x509_certificate.h"
+#include "net/ssl/ssl_private_key.h"
 #include "url/gurl.h"
 
 namespace chromecast {
@@ -18,7 +21,7 @@
 
  private:
   // CastNetworkDelegate implementation:
-  void Initialize(bool use_sync_signing) override {}
+  void Initialize() override {}
   bool IsWhitelisted(const GURL& gurl, int render_process_id,
                      bool for_device_auth) const override {
     return false;
@@ -30,18 +33,18 @@
 }  // namespace
 
 // static
-CastNetworkDelegate* CastNetworkDelegate::Create() {
-  return new CastNetworkDelegateSimple();
+std::unique_ptr<CastNetworkDelegate> CastNetworkDelegate::Create() {
+  return base::MakeUnique<CastNetworkDelegateSimple>();
 }
 
 // static
-net::X509Certificate* CastNetworkDelegate::DeviceCert() {
-  return NULL;
+scoped_refptr<net::X509Certificate> CastNetworkDelegate::DeviceCert() {
+  return nullptr;
 }
 
 // static
-net::SSLPrivateKey* CastNetworkDelegate::DeviceKey() {
-  return NULL;
+scoped_refptr<net::SSLPrivateKey> CastNetworkDelegate::DeviceKey() {
+  return nullptr;
 }
 
 }  // namespace shell
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index f9a7eb76..84cb7ae 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -435,9 +435,9 @@
 }
 
 void URLRequestContextFactory::InitializeNetworkDelegates() {
-  app_network_delegate_->Initialize(false);
+  app_network_delegate_->Initialize();
   LOG(INFO) << "Initialized app network delegate.";
-  system_network_delegate_->Initialize(false);
+  system_network_delegate_->Initialize();
   LOG(INFO) << "Initialized system network delegate.";
 }
 
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 82d560c..6ccc3a2 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -930,8 +930,7 @@
   }
 
   // Initialize local device info.
-  local_device_->Initialize(cache_guid, signin_scoped_device_id,
-                            sync_client_->GetBlockingPool());
+  local_device_->Initialize(cache_guid, signin_scoped_device_id);
 
   if (protocol_event_observers_.might_have_observers()) {
     engine_->RequestBufferedProtocolEventsAndEnableForwarding();
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
index 2333fe25..4bee639 100644
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -57,6 +57,7 @@
     {CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, 31},
     {CONTENT_SETTINGS_TYPE_ADS, 32},
     {CONTENT_SETTINGS_TYPE_ADS_DATA, 33},
+    {CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 34},
 };
 
 int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting,
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index b22b47bc..d8cb82b1 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -904,7 +904,7 @@
   if (!geometry_.IsEmpty())
     return geometry_.size();
 
-  return surface_ ? surface_->window()->layer()->size() : gfx::Size();
+  return surface_ ? surface_->content_size() : gfx::Size();
 }
 
 gfx::Size ShellSurface::GetMinimumSize() const {
@@ -1413,8 +1413,7 @@
 
 gfx::Rect ShellSurface::GetVisibleBounds() const {
   // Use |geometry_| if set, otherwise use the visual bounds of the surface.
-  return geometry_.IsEmpty() ? gfx::Rect(surface_->window()->layer()->size())
-                             : geometry_;
+  return geometry_.IsEmpty() ? gfx::Rect(surface_->content_size()) : geometry_;
 }
 
 gfx::Point ShellSurface::GetSurfaceOrigin() const {
@@ -1539,7 +1538,7 @@
 
   surface_->window()->SetBounds(
       gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(),
-                surface_->window()->layer()->size()));
+                surface_->content_size()));
 }
 
 void ShellSurface::UpdateShadow() {
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index b6edb5b..2a9bfb59 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -525,8 +525,8 @@
     stacking_target = sub_surface->window();
 
     // Update sub-surface position relative to surface origin.
-    sub_surface->window()->SetBounds(gfx::Rect(
-        sub_surface_entry.second, sub_surface->window()->layer()->size()));
+    sub_surface->window()->SetBounds(
+        gfx::Rect(sub_surface_entry.second, sub_surface->content_size_));
   }
 }
 
@@ -536,8 +536,7 @@
 
 gfx::Rect Surface::GetHitTestBounds() const {
   SkIRect bounds = state_.input_region.getBounds();
-  if (!bounds.intersect(
-          gfx::RectToSkIRect(gfx::Rect(window_->layer()->size()))))
+  if (!bounds.intersect(gfx::RectToSkIRect(gfx::Rect(content_size_))))
     return gfx::Rect();
   return gfx::SkIRectToRect(bounds);
 }
@@ -546,12 +545,12 @@
   if (HasHitTestMask())
     return state_.input_region.intersects(gfx::RectToSkIRect(rect));
 
-  return rect.Intersects(gfx::Rect(window_->layer()->size()));
+  return rect.Intersects(gfx::Rect(content_size_));
 }
 
 bool Surface::HasHitTestMask() const {
   return !state_.input_region.contains(
-      gfx::RectToSkIRect(gfx::Rect(window_->layer()->size())));
+      gfx::RectToSkIRect(gfx::Rect(content_size_)));
 }
 
 void Surface::GetHitTestMask(gfx::Path* mask) const {
diff --git a/components/safe_browsing/password_protection/password_protection_request.cc b/components/safe_browsing/password_protection/password_protection_request.cc
index f58d30b..552def6 100644
--- a/components/safe_browsing/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/password_protection/password_protection_request.cc
@@ -38,12 +38,14 @@
       password_form_action_(password_form_action),
       password_form_frame_url_(password_form_frame_url),
       saved_domain_(saved_domain),
-      request_type_(type),
+      trigger_type_(type),
       password_field_exists_(password_field_exists),
       password_protection_service_(pps),
       request_timeout_in_ms_(request_timeout_in_ms),
       weakptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type_ == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
 }
 
 PasswordProtectionRequest::~PasswordProtectionRequest() {
@@ -98,7 +100,7 @@
   std::unique_ptr<LoginReputationClientResponse> cached_response =
       base::MakeUnique<LoginReputationClientResponse>();
   auto verdict = password_protection_service_->GetCachedVerdict(
-      main_frame_url_, cached_response.get());
+      main_frame_url_, trigger_type_, cached_response.get());
   if (verdict != LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED)
     Finish(PasswordProtectionService::RESPONSE_ALREADY_CACHED,
            std::move(cached_response));
@@ -109,11 +111,11 @@
 void PasswordProtectionRequest::FillRequestProto() {
   request_proto_ = base::MakeUnique<LoginReputationClientRequest>();
   request_proto_->set_page_url(main_frame_url_.spec());
-  request_proto_->set_trigger_type(request_type_);
-  password_protection_service_->FillUserPopulation(request_type_,
+  request_proto_->set_trigger_type(trigger_type_);
+  password_protection_service_->FillUserPopulation(trigger_type_,
                                                    request_proto_.get());
   request_proto_->set_stored_verdict_cnt(
-      password_protection_service_->GetStoredVerdictCount());
+      password_protection_service_->GetStoredVerdictCount(trigger_type_));
   LoginReputationClientRequest::Frame* main_frame =
       request_proto_->add_frames();
   main_frame->set_url(main_frame_url_.spec());
@@ -121,7 +123,7 @@
   password_protection_service_->FillReferrerChain(
       main_frame_url_, -1 /* tab id not available */, main_frame);
 
-  switch (request_type_) {
+  switch (trigger_type_) {
     case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE: {
       LoginReputationClientRequest::Frame::Form* password_form;
       if (password_form_frame_url_ == main_frame_url_) {
@@ -260,7 +262,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   tracker_.TryCancelAll();
 
-  if (request_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
+  if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
     UMA_HISTOGRAM_ENUMERATION(kPasswordOnFocusRequestOutcomeHistogramName,
                               outcome, PasswordProtectionService::MAX_OUTCOME);
   } else {
@@ -269,7 +271,7 @@
   }
 
   if (outcome == PasswordProtectionService::SUCCEEDED && response) {
-    switch (request_type_) {
+    switch (trigger_type_) {
       case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE:
         UMA_HISTOGRAM_ENUMERATION(
             "PasswordProtection.Verdict.PasswordFieldOnFocus",
diff --git a/components/safe_browsing/password_protection/password_protection_request.h b/components/safe_browsing/password_protection/password_protection_request.h
index 4619011..7593ca740 100644
--- a/components/safe_browsing/password_protection/password_protection_request.h
+++ b/components/safe_browsing/password_protection/password_protection_request.h
@@ -74,8 +74,8 @@
 
   content::WebContents* web_contents() const { return web_contents_; }
 
-  LoginReputationClientRequest::TriggerType request_type() const {
-    return request_type_;
+  LoginReputationClientRequest::TriggerType trigger_type() const {
+    return trigger_type_;
   }
 
  private:
@@ -129,7 +129,7 @@
   const std::string saved_domain_;
 
   // If this request is for unfamiliar login page or for a password reuse event.
-  const LoginReputationClientRequest::TriggerType request_type_;
+  const LoginReputationClientRequest::TriggerType trigger_type_;
 
   // If there is a password field on the page.
   const bool password_field_exists_;
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc
index 51d17e93..9fa2c7e 100644
--- a/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -4,6 +4,9 @@
 
 #include "components/safe_browsing/password_protection/password_protection_service.h"
 
+#include <stddef.h>
+#include <string>
+
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -39,6 +42,7 @@
 const int kRequestTimeoutMs = 10000;
 const char kPasswordProtectionRequestUrl[] =
     "https://sb-ssl.google.com/safebrowsing/clientreport/login";
+const char kPasswordOnFocusCacheKey[] = "password_on_focus_cache_key";
 
 // Helper function to determine if the given origin matches content settings
 // map's patterns.
@@ -88,7 +92,8 @@
     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     HistoryService* history_service,
     HostContentSettingsMap* host_content_settings_map)
-    : stored_verdict_count_(-1),
+    : stored_verdict_count_password_on_focus_(-1),
+      stored_verdict_count_password_entry_(-1),
       database_manager_(database_manager),
       request_context_getter_(request_context_getter),
       history_service_observer_(this),
@@ -115,24 +120,48 @@
          hostname.find('.') != std::string::npos;
 }
 
+// We cache both types of pings under the same content settings type (
+// CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION). Since UNFAMILIAR_LOGING_PAGE
+// verdicts are only enabled on extended reporting users, we cache them one
+// layer lower in the content setting DictionaryValue than PASSWORD_REUSE_EVENT
+// verdicts.
+// In other words, to cache a UNFAMILIAR_LOGIN_PAGE verdict we needs two levels
+// of keys: (1) origin, (2) cache expression returned in verdict.
+// To cache a PASSWORD_REUSE_EVENT, three levels of keys are used:
+// (1) origin, (2) 2nd level key is always |kPasswordOnFocusCacheKey|,
+// (3) cache expression.
 LoginReputationClientResponse::VerdictType
 PasswordProtectionService::GetCachedVerdict(
     const GURL& url,
+    TriggerType trigger_type,
     LoginReputationClientResponse* out_response) {
+  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
+
   if (!url.is_valid())
     return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
 
-  DCHECK(content_settings_);
-
   GURL hostname = GetHostNameWithHTTPScheme(url);
-  std::unique_ptr<base::DictionaryValue> verdict_dictionary =
+  std::unique_ptr<base::DictionaryValue> cache_dictionary =
       base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
           hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
           std::string(), nullptr));
-  // Return early if there is no verdict cached for this origin.
-  if (!verdict_dictionary.get() || verdict_dictionary->empty())
+
+  if (!cache_dictionary.get() || cache_dictionary->empty())
     return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
 
+  base::DictionaryValue* verdict_dictionary = nullptr;
+  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
+    // All UNFAMILIAR_LOGIN_PAGE verdicts (a.k.a password on focus ping)
+    // are cached under |kPasswordOnFocusCacheKey|.
+    if (!cache_dictionary->GetDictionaryWithoutPathExpansion(
+            base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary)) {
+      return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
+    }
+  } else {
+    verdict_dictionary = cache_dictionary.get();
+  }
+
   std::vector<std::string> paths;
   GeneratePathVariantsWithoutQuery(url, &paths);
   int max_path_depth = -1;
@@ -141,8 +170,12 @@
   // For all the verdicts of the same origin, we key them by |cache_expression|.
   // Its corresponding value is a DictionaryValue contains its creation time and
   // the serialized verdict proto.
-  for (base::DictionaryValue::Iterator it(*verdict_dictionary.get());
-       !it.IsAtEnd(); it.Advance()) {
+  for (base::DictionaryValue::Iterator it(*verdict_dictionary); !it.IsAtEnd();
+       it.Advance()) {
+    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
+        it.key() == base::StringPiece(kPasswordOnFocusCacheKey)) {
+      continue;
+    }
     base::DictionaryValue* verdict_entry = nullptr;
     CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
         it.key() /* cache_expression */, &verdict_entry));
@@ -173,39 +206,65 @@
 
 void PasswordProtectionService::CacheVerdict(
     const GURL& url,
+    TriggerType trigger_type,
     LoginReputationClientResponse* verdict,
     const base::Time& receive_time) {
   DCHECK(verdict);
   DCHECK(content_settings_);
+  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
 
   GURL hostname = GetHostNameWithHTTPScheme(url);
-  std::unique_ptr<base::DictionaryValue> verdict_dictionary =
+  int* stored_verdict_count =
+      trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
+          ? &stored_verdict_count_password_on_focus_
+          : &stored_verdict_count_password_entry_;
+  std::unique_ptr<base::DictionaryValue> cache_dictionary =
       base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
           hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
           std::string(), nullptr));
 
-  if (!verdict_dictionary.get())
-    verdict_dictionary = base::MakeUnique<base::DictionaryValue>();
+  if (!cache_dictionary || !cache_dictionary.get())
+    cache_dictionary = base::MakeUnique<base::DictionaryValue>();
 
-  std::unique_ptr<base::DictionaryValue> verdict_entry =
-      CreateDictionaryFromVerdict(verdict, receive_time);
+  std::unique_ptr<base::DictionaryValue> verdict_entry(
+      CreateDictionaryFromVerdict(verdict, receive_time));
+
+  base::DictionaryValue* verdict_dictionary = nullptr;
+  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
+    // All UNFAMILIAR_LOGIN_PAGE verdicts (a.k.a password on focus ping)
+    // are cached under |kPasswordOnFocusCacheKey|.
+    if (!cache_dictionary->GetDictionaryWithoutPathExpansion(
+            base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary)) {
+      verdict_dictionary = cache_dictionary->SetDictionaryWithoutPathExpansion(
+          base::StringPiece(kPasswordOnFocusCacheKey),
+          base::MakeUnique<base::DictionaryValue>());
+    }
+  } else {
+    verdict_dictionary = cache_dictionary.get();
+  }
 
   // Increases stored verdict count if we haven't seen this cache expression
   // before.
   if (!verdict_dictionary->HasKey(verdict->cache_expression()))
-    stored_verdict_count_ = GetStoredVerdictCount() + 1;
+    *stored_verdict_count = GetStoredVerdictCount(trigger_type) + 1;
+
   // If same cache_expression is already in this verdict_dictionary, we simply
   // override it.
   verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(),
                                               std::move(verdict_entry));
   content_settings_->SetWebsiteSettingDefaultScope(
       hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
-      std::string(), std::move(verdict_dictionary));
+      std::string(), std::move(cache_dictionary));
 }
 
 void PasswordProtectionService::CleanUpExpiredVerdicts() {
   DCHECK(content_settings_);
-  if (GetStoredVerdictCount() <= 0)
+
+  if (GetStoredVerdictCount(
+          LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) <= 0 &&
+      GetStoredVerdictCount(
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT) <= 0)
     return;
 
   ContentSettingsForOneType password_protection_settings;
@@ -217,44 +276,29 @@
        password_protection_settings) {
     GURL primary_pattern_url = GURL(source.primary_pattern.ToString());
     // Find all verdicts associated with this origin.
-    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
+    std::unique_ptr<base::DictionaryValue> cache_dictionary =
         base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
             primary_pattern_url, GURL(),
             CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), nullptr));
-    std::vector<std::string> expired_keys;
-    for (base::DictionaryValue::Iterator it(*verdict_dictionary.get());
-         !it.IsAtEnd(); it.Advance()) {
-      base::DictionaryValue* verdict_entry = nullptr;
-      CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
-          it.key(), &verdict_entry));
-      int verdict_received_time;
-      LoginReputationClientResponse verdict;
-      CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict));
+    bool has_expired_password_on_focus_entry = RemoveExpiredVerdicts(
+        LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+        cache_dictionary.get());
+    bool has_expired_password_reuse_entry = RemoveExpiredVerdicts(
+        LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+        cache_dictionary.get());
 
-      if (IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) {
-        // Since DictionaryValue::Iterator cannot be used to modify the
-        // dictionary, we record the keys of expired verdicts in |expired_keys|
-        // and remove them in the next for-loop.
-        expired_keys.push_back(it.key());
-      }
-    }
-
-    for (const std::string& key : expired_keys) {
-      verdict_dictionary->RemoveWithoutPathExpansion(key, nullptr);
-      stored_verdict_count_--;
-    }
-
-    if (verdict_dictionary->size() == 0u) {
+    if (cache_dictionary->size() == 0u) {
       content_settings_->ClearSettingsForOneTypeWithPredicate(
           CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, base::Time(),
           base::Bind(&OriginMatchPrimaryPattern, primary_pattern_url));
-    } else if (expired_keys.size() > 0u) {
+    } else if (has_expired_password_on_focus_entry ||
+               has_expired_password_reuse_entry) {
       // Set the website setting of this origin with the updated
       // |verdict_diectionary|.
       content_settings_->SetWebsiteSettingDefaultScope(
           primary_pattern_url, GURL(),
           CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
-          std::move(verdict_dictionary));
+          std::move(cache_dictionary));
     }
   }
 }
@@ -265,14 +309,15 @@
     const GURL& password_form_action,
     const GURL& password_form_frame_url,
     const std::string& saved_domain,
-    LoginReputationClientRequest::TriggerType type,
+    TriggerType trigger_type,
     bool password_field_exists) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<PasswordProtectionRequest> request(
       new PasswordProtectionRequest(
           web_contents, main_frame_url, password_form_action,
-          password_form_frame_url, saved_domain, type, password_field_exists,
-          this, GetRequestTimeoutInMS()));
+          password_form_frame_url, saved_domain, trigger_type,
+          password_field_exists, this, GetRequestTimeoutInMS()));
+
   DCHECK(request);
   request->Start();
   requests_.insert(std::move(request));
@@ -325,11 +370,11 @@
 
   if (response) {
     if (!already_cached) {
-      CacheVerdict(request->main_frame_url(), response.get(),
-                   base::Time::Now());
+      CacheVerdict(request->main_frame_url(), request->trigger_type(),
+                   response.get(), base::Time::Now());
     }
 
-    if (request->request_type() ==
+    if (request->trigger_type() ==
             LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
         response->verdict_type() == LoginReputationClientResponse::PHISHING &&
         base::FeatureList::IsEnabled(kPasswordProtectionInterstitial)) {
@@ -372,30 +417,49 @@
   return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
 }
 
-int PasswordProtectionService::GetStoredVerdictCount() {
+int PasswordProtectionService::GetStoredVerdictCount(TriggerType trigger_type) {
   DCHECK(content_settings_);
+  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
+  int* stored_verdict_count =
+      trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
+          ? &stored_verdict_count_password_on_focus_
+          : &stored_verdict_count_password_entry_;
   // If we have already computed this, return its value.
-  if (stored_verdict_count_ >= 0)
-    return stored_verdict_count_;
+  if (*stored_verdict_count >= 0)
+    return *stored_verdict_count;
 
   ContentSettingsForOneType password_protection_settings;
   content_settings_->GetSettingsForOneType(
       CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
       &password_protection_settings);
-  stored_verdict_count_ = 0;
+  stored_verdict_count_password_on_focus_ = 0;
+  stored_verdict_count_password_entry_ = 0;
   if (password_protection_settings.empty())
     return 0;
 
   for (const ContentSettingPatternSource& source :
        password_protection_settings) {
-    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
+    std::unique_ptr<base::DictionaryValue> cache_dictionary =
         base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
             GURL(source.primary_pattern.ToString()), GURL(),
             CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), nullptr));
-    if (verdict_dictionary.get() && !verdict_dictionary->empty())
-      stored_verdict_count_ += static_cast<int>(verdict_dictionary->size());
+    if (cache_dictionary.get() && !cache_dictionary->empty()) {
+      stored_verdict_count_password_entry_ +=
+          static_cast<int>(cache_dictionary->size());
+      base::DictionaryValue* password_on_focus_dict = nullptr;
+      if (cache_dictionary->GetDictionaryWithoutPathExpansion(
+              base::StringPiece(kPasswordOnFocusCacheKey),
+              &password_on_focus_dict)) {
+        // Substracts 1 from password_entry count if |kPasswordOnFocusCacheKey|
+        // presents.
+        stored_verdict_count_password_entry_ -= 1;
+        stored_verdict_count_password_on_focus_ +=
+            static_cast<int>(password_on_focus_dict->size());
+      }
+    }
   }
-  return stored_verdict_count_;
+  return *stored_verdict_count;
 }
 
 int PasswordProtectionService::GetRequestTimeoutInMS() {
@@ -403,7 +467,7 @@
 }
 
 void PasswordProtectionService::FillUserPopulation(
-    const LoginReputationClientRequest::TriggerType& request_type,
+    TriggerType trigger_type,
     LoginReputationClientRequest* request_proto) {
   ChromeUserPopulation* user_population = request_proto->mutable_population();
   user_population->set_user_population(
@@ -433,8 +497,10 @@
     bool expired,
     const history::URLRows& deleted_rows,
     const std::set<GURL>& favicon_urls) {
-  if (stored_verdict_count_ <= 0)
+  if (stored_verdict_count_password_on_focus_ <= 0 &&
+      stored_verdict_count_password_entry_ <= 0) {
     return;
+  }
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
@@ -456,7 +522,8 @@
   if (all_history) {
     content_settings_->ClearSettingsForOneType(
         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION);
-    stored_verdict_count_ = 0;
+    stored_verdict_count_password_on_focus_ = 0;
+    stored_verdict_count_password_entry_ = 0;
     return;
   }
 
@@ -467,24 +534,106 @@
   for (const history::URLRow& row : deleted_rows) {
     if (!row.url().SchemeIsHTTPOrHTTPS())
       continue;
+
     GURL url_key = GetHostNameWithHTTPScheme(row.url());
-    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
-        base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
-            url_key, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
-            std::string(), nullptr));
-
-    // Move on if we have no cached verdict for this deleted history row.
-    if (!verdict_dictionary.get() || verdict_dictionary->empty())
-      continue;
-
-    int verdict_count = static_cast<int>(verdict_dictionary->size());
-    stored_verdict_count_ = GetStoredVerdictCount() - verdict_count;
+    stored_verdict_count_password_on_focus_ =
+        GetStoredVerdictCount(
+            LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) -
+        GetVerdictCountForURL(
+            url_key, LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE);
+    stored_verdict_count_password_entry_ =
+        GetStoredVerdictCount(
+            LoginReputationClientRequest::PASSWORD_REUSE_EVENT) -
+        GetVerdictCountForURL(
+            url_key, LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
     content_settings_->ClearSettingsForOneTypeWithPredicate(
         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, base::Time(),
         base::Bind(&OriginMatchPrimaryPattern, url_key));
   }
 }
 
+int PasswordProtectionService::GetVerdictCountForURL(const GURL& url,
+                                                     TriggerType trigger_type) {
+  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
+  std::unique_ptr<base::DictionaryValue> cache_dictionary =
+      base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
+          url, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
+          nullptr));
+  if (!cache_dictionary.get() || cache_dictionary->empty())
+    return 0;
+
+  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
+    base::DictionaryValue* password_on_focus_dict = nullptr;
+    return cache_dictionary->GetDictionaryWithoutPathExpansion(
+               base::StringPiece(kPasswordOnFocusCacheKey),
+               &password_on_focus_dict)
+               ? password_on_focus_dict->size()
+               : 0;
+  } else {
+    return cache_dictionary->HasKey(base::StringPiece(kPasswordOnFocusCacheKey))
+               ? cache_dictionary->size() - 1
+               : cache_dictionary->size();
+  }
+}
+
+bool PasswordProtectionService::RemoveExpiredVerdicts(
+    TriggerType trigger_type,
+    base::DictionaryValue* cache_dictionary) {
+  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
+         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
+  base::DictionaryValue* verdict_dictionary = nullptr;
+  if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT) {
+    verdict_dictionary = cache_dictionary;
+  } else {
+    if (!cache_dictionary->GetDictionaryWithoutPathExpansion(
+            base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary)) {
+      return false;
+    }
+  }
+
+  if (!verdict_dictionary || verdict_dictionary->empty())
+    return false;
+
+  std::vector<std::string> expired_keys;
+  for (base::DictionaryValue::Iterator it(*verdict_dictionary); !it.IsAtEnd();
+       it.Advance()) {
+    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
+        it.key() == std::string(kPasswordOnFocusCacheKey))
+      continue;
+
+    base::DictionaryValue* verdict_entry = nullptr;
+    CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
+        it.key(), &verdict_entry));
+    int verdict_received_time;
+    LoginReputationClientResponse verdict;
+    CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict));
+
+    if (IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) {
+      // Since DictionaryValue::Iterator cannot be used to modify the
+      // dictionary, we record the keys of expired verdicts in |expired_keys|
+      // and remove them in the next for-loop.
+      expired_keys.push_back(it.key());
+    }
+  }
+
+  for (const std::string& key : expired_keys) {
+    verdict_dictionary->RemoveWithoutPathExpansion(key, nullptr);
+    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT)
+      stored_verdict_count_password_entry_--;
+    else
+      stored_verdict_count_password_on_focus_--;
+  }
+
+  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
+      verdict_dictionary->size() == 0U) {
+    cache_dictionary->RemoveWithoutPathExpansion(
+        base::StringPiece(kPasswordOnFocusCacheKey), nullptr);
+  }
+
+  return expired_keys.size() > 0U;
+}
+
 // static
 bool PasswordProtectionService::ParseVerdictEntry(
     base::DictionaryValue* verdict_entry,
diff --git a/components/safe_browsing/password_protection/password_protection_service.h b/components/safe_browsing/password_protection/password_protection_service.h
index 89870aa..10036f4 100644
--- a/components/safe_browsing/password_protection/password_protection_service.h
+++ b/components/safe_browsing/password_protection/password_protection_service.h
@@ -49,6 +49,7 @@
 // HostContentSettingsMap instance.
 class PasswordProtectionService : public history::HistoryServiceObserver {
  public:
+  using TriggerType = LoginReputationClientRequest::TriggerType;
   // The outcome of the request. These values are used for UMA.
   // DO NOT CHANGE THE ORDERING OF THESE VALUES.
   enum RequestOutcome {
@@ -87,11 +88,13 @@
   // any thread.
   LoginReputationClientResponse::VerdictType GetCachedVerdict(
       const GURL& url,
+      TriggerType trigger_type,
       LoginReputationClientResponse* out_response);
 
-  // Stores |verdict| in |settings| based on |url|, |verdict| and
-  // |receive_time|.
+  // Stores |verdict| in |settings| based on its |trigger_type|, |url|,
+  // |verdict| and |receive_time|.
   virtual void CacheVerdict(const GURL& url,
+                            TriggerType trigger_type,
                             LoginReputationClientResponse* verdict,
                             const base::Time& receive_time);
 
@@ -106,7 +109,7 @@
                     const GURL& password_form_action,
                     const GURL& password_form_frame_url,
                     const std::string& saved_domain,
-                    LoginReputationClientRequest::TriggerType type,
+                    TriggerType trigger_type,
                     bool password_field_exists);
 
   virtual void MaybeStartPasswordFieldOnFocusRequest(
@@ -152,9 +155,9 @@
   // the requests.
   void CancelPendingRequests();
 
-  // Gets the total number of verdict (no matter expired or not) we cached for
-  // current active profile.
-  virtual int GetStoredVerdictCount();
+  // Gets the total number of verdicts of the specified |trigger_type| we cached
+  // for this profile. This counts both expired and active verdicts.
+  virtual int GetStoredVerdictCount(TriggerType trigger_type);
 
   scoped_refptr<net::URLRequestContextGetter> request_context_getter() {
     return request_context_getter_;
@@ -173,9 +176,8 @@
       int event_tab_id,  // -1 if tab id is not available.
       LoginReputationClientRequest::Frame* frame) = 0;
 
-  void FillUserPopulation(
-      const LoginReputationClientRequest::TriggerType& request_type,
-      LoginReputationClientRequest* request_proto);
+  void FillUserPopulation(TriggerType trigger_type,
+                          LoginReputationClientRequest* request_proto);
 
   virtual bool IsExtendedReporting() = 0;
 
@@ -223,6 +225,15 @@
   void RemoveContentSettingsOnURLsDeleted(bool all_history,
                                           const history::URLRows& deleted_rows);
 
+  // Helper function called by RemoveContentSettingsOnURLsDeleted(..). It
+  // calculate the number of verdicts of |type| that associate with |url|.
+  int GetVerdictCountForURL(const GURL& url, TriggerType type);
+
+  // Remove verdict of |type| from |cache_dictionary|. Return false if no
+  // verdict removed, true otherwise.
+  bool RemoveExpiredVerdicts(TriggerType type,
+                             base::DictionaryValue* cache_dictionary);
+
   static bool ParseVerdictEntry(base::DictionaryValue* verdict_entry,
                                 int* out_verdict_received_time,
                                 LoginReputationClientResponse* out_verdict);
@@ -245,8 +256,12 @@
 
   static void RecordNoPingingReason(const base::Feature& feature,
                                     RequestOutcome reason);
-  // Number of verdict stored for this profile.
-  int stored_verdict_count_;
+  // Number of verdict stored for this profile for password on focus pings.
+  int stored_verdict_count_password_on_focus_;
+
+  // Number of verdict stored for this profile for protected password entry
+  // pings.
+  int stored_verdict_count_password_entry_;
 
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
 
diff --git a/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
index fb61afd5..ddba3ee7 100644
--- a/components/safe_browsing/password_protection/password_protection_service_unittest.cc
+++ b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -208,18 +208,19 @@
   }
 
   void CacheVerdict(const GURL& url,
+                    LoginReputationClientRequest::TriggerType trigger,
                     LoginReputationClientResponse::VerdictType verdict,
                     int cache_duration_sec,
                     const std::string& cache_expression,
                     const base::Time& verdict_received_time) {
     LoginReputationClientResponse response(
         CreateVerdictProto(verdict, cache_duration_sec, cache_expression));
-    password_protection_service_->CacheVerdict(url, &response,
+    password_protection_service_->CacheVerdict(url, trigger, &response,
                                                verdict_received_time);
   }
 
-  size_t GetStoredVerdictCount() {
-    return password_protection_service_->GetStoredVerdictCount();
+  size_t GetStoredVerdictCount(LoginReputationClientRequest::TriggerType type) {
+    return password_protection_service_->GetStoredVerdictCount(type);
   }
 
  protected:
@@ -311,80 +312,173 @@
       GURL("http://evil.com/worse/index.html"), cache_expression_with_slash));
 }
 
-TEST_F(PasswordProtectionServiceTest, TestCachedVerdicts) {
-  ASSERT_EQ(0U, GetStoredVerdictCount());
+TEST_F(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+
   // Assume each verdict has a TTL of 10 minutes.
   // Cache a verdict for http://www.test.com/foo/index.html
   CacheVerdict(GURL("http://www.test.com/foo/index.html"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foo",
                base::Time::Now());
 
-  EXPECT_EQ(1U, GetStoredVerdictCount());
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
 
   // Cache another verdict with the some origin and cache_expression should
   // override the cache.
   CacheVerdict(GURL("http://www.test.com/foo/index2.html"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/foo",
                base::Time::Now());
-  EXPECT_EQ(1U, GetStoredVerdictCount());
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
   LoginReputationClientResponse out_verdict;
-  EXPECT_EQ(LoginReputationClientResponse::PHISHING,
-            password_protection_service_->GetCachedVerdict(
-                GURL("http://www.test.com/foo/index2.html"), &out_verdict));
+  EXPECT_EQ(
+      LoginReputationClientResponse::PHISHING,
+      password_protection_service_->GetCachedVerdict(
+          GURL("http://www.test.com/foo/index2.html"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &out_verdict));
 
   // Cache another verdict with the same origin but different cache_expression
   // will not increase setting count, but will increase the number of verdicts
   // in the given origin.
   CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com/bar",
                base::Time::Now());
-  EXPECT_EQ(2U, GetStoredVerdictCount());
+  EXPECT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+
+  // Now cache a UNFAMILIAR_LOGIN_PAGE verdict, stored verdict count for
+  // PASSWORD_REUSE_EVENT should be the same.
+  CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foobar",
+               base::Time::Now());
+  EXPECT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+}
+
+TEST_F(PasswordProtectionServiceTest, TestCacheUnfamiliarLoginVerdicts) {
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+
+  // Assume each verdict has a TTL of 10 minutes.
+  // Cache a verdict for http://www.test.com/foo/index.html
+  CacheVerdict(GURL("http://www.test.com/foo/index.html"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foo",
+               base::Time::Now());
+
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+
+  // Cache another verdict with the same origin but different cache_expression
+  // will not increase setting count, but will increase the number of verdicts
+  // in the given origin.
+  CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/bar",
+               base::Time::Now());
+  EXPECT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+
+  // Now cache a PASSWORD_REUSE_EVENT verdict, stored verdict count for
+  // UNFAMILIAR_LOGIN_PAGE should be the same.
+  CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foobar",
+               base::Time::Now());
+  EXPECT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
 }
 
 TEST_F(PasswordProtectionServiceTest, TestGetCachedVerdicts) {
-  ASSERT_EQ(0U, GetStoredVerdictCount());
-  // Prepare 2 verdicts of the same origin with different cache expressions,
-  // one is expired, the other is not.
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  // Prepare 3 verdicts of the same origin with different cache expressions,
+  // one is expired, one is not, the other is of a different type.
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("http://test.com/login.html"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com", now);
   CacheVerdict(
       GURL("http://test.com/def/index.jsp"),
+      LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
       LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/def",
       base::Time::FromDoubleT(now.ToDoubleT() -
                               24.0 * 60.0 * 60.0));  // Yesterday, expired.
-  ASSERT_EQ(2U, GetStoredVerdictCount());
+  CacheVerdict(GURL("http://test.com/bar/login.html"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/bar",
+               now);
+
+  ASSERT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  ASSERT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
 
   // Return VERDICT_TYPE_UNSPECIFIED if look up for a URL with unknown origin.
   LoginReputationClientResponse actual_verdict;
-  EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-            password_protection_service_->GetCachedVerdict(
-                GURL("http://www.unknown.com/"), &actual_verdict));
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("http://www.unknown.com/"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
 
   // Return SAFE if look up for a URL that matches "test.com" cache expression.
-  EXPECT_EQ(LoginReputationClientResponse::SAFE,
-            password_protection_service_->GetCachedVerdict(
-                GURL("http://test.com/xyz/foo.jsp"), &actual_verdict));
+  EXPECT_EQ(
+      LoginReputationClientResponse::SAFE,
+      password_protection_service_->GetCachedVerdict(
+          GURL("http://test.com/xyz/foo.jsp"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
 
   // Return VERDICT_TYPE_UNSPECIFIED if look up for a URL whose variants match
   // test.com/def, but the corresponding verdict is expired.
-  EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-            password_protection_service_->GetCachedVerdict(
-                GURL("http://test.com/def/ghi/index.html"), &actual_verdict));
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("http://test.com/def/ghi/index.html"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
 }
 
 TEST_F(PasswordProtectionServiceTest, TestRemoveCachedVerdictOnURLsDeleted) {
-  ASSERT_EQ(0U, GetStoredVerdictCount());
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  ASSERT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
   // Prepare 2 verdicts. One is for origin "http://foo.com", and the other is
   // for "http://bar.com".
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("http://foo.com/abc/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
                "foo.com/abc", now);
   CacheVerdict(GURL("http://bar.com/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 10 * 60, "bar.com",
                now);
-  ASSERT_EQ(2U, GetStoredVerdictCount());
+  ASSERT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+
+  CacheVerdict(GURL("http://foo.com/abc/index.jsp"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
+               "foo.com/abc", now);
+  CacheVerdict(GURL("http://bar.com/index.jsp"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::PHISHING, 10 * 60, "bar.com",
+               now);
+  ASSERT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
 
   // Delete a bar.com URL. Corresponding content setting keyed on
   // origin "http://bar.com" should be removed,
@@ -397,17 +491,31 @@
 
   password_protection_service_->RemoveContentSettingsOnURLsDeleted(
       false /* all_history */, deleted_urls);
-  EXPECT_EQ(1U, GetStoredVerdictCount());
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+
   LoginReputationClientResponse actual_verdict;
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("http://bar.com"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
   EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
             password_protection_service_->GetCachedVerdict(
-                GURL("http://bar.com"), &actual_verdict));
+                GURL("http://bar.com"),
+                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+                &actual_verdict));
 
   // If delete all history. All password protection content settings should be
   // gone.
   password_protection_service_->RemoveContentSettingsOnURLsDeleted(
       true /* all_history */, history::URLRows());
-  EXPECT_EQ(0U, GetStoredVerdictCount());
+  EXPECT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(0U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
 }
 
 TEST_F(PasswordProtectionServiceTest, VerifyCanGetReputationOfURL) {
@@ -461,8 +569,10 @@
 
 TEST_F(PasswordProtectionServiceTest, TestNoRequestSentIfVerdictAlreadyCached) {
   histograms_.ExpectTotalCount(kPasswordOnFocusRequestOutcomeHistogramName, 0);
-  CacheVerdict(GURL(kTargetUrl), LoginReputationClientResponse::LOW_REPUTATION,
-               600, GURL(kTargetUrl).host(), base::Time::Now());
+  CacheVerdict(GURL(kTargetUrl),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::LOW_REPUTATION, 600,
+               GURL(kTargetUrl).host(), base::Time::Now());
   InitializeAndStartPasswordOnFocusRequest(false /* match whitelist */,
                                            10000 /* timeout in ms*/);
   base::RunLoop().RunUntilIdle();
@@ -569,42 +679,87 @@
 }
 
 TEST_F(PasswordProtectionServiceTest, TestCleanUpExpiredVerdict) {
-  ASSERT_EQ(0U, GetStoredVerdictCount());
-  // Prepare 4 verdicts:
+  // Prepare 4 verdicts for PASSWORD_REUSE_EVENT:
   // (1) "foo.com/abc" valid
   // (2) "foo.com/def" expired
   // (3) "bar.com/abc" expired
   // (4) "bar.com/def" expired
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("https://foo.com/abc/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
                "foo.com/abc", now);
   CacheVerdict(GURL("https://foo.com/def/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 0, "foo.com/def",
                now);
   CacheVerdict(GURL("https://bar.com/abc/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 0, "bar.com/abc", now);
   CacheVerdict(GURL("https://bar.com/def/index.jsp"),
+               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 0, "bar.com/def", now);
-  ASSERT_EQ(4U, GetStoredVerdictCount());
+  ASSERT_EQ(4U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+
+  // Prepare 2 verdicts for UNFAMILIAR_LOGIN_PAGE:
+  // (1) "bar.com/def" valid
+  // (2) "bar.com/xyz" expired
+  CacheVerdict(GURL("https://bar.com/def/index.jsp"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::SAFE, 10 * 60, "bar.com/def",
+               now);
+  CacheVerdict(GURL("https://bar.com/xyz/index.jsp"),
+               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+               LoginReputationClientResponse::PHISHING, 0, "bar.com/xyz", now);
+  ASSERT_EQ(2U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
 
   password_protection_service_->CleanUpExpiredVerdicts();
 
-  ASSERT_EQ(1U, GetStoredVerdictCount());
+  ASSERT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  ASSERT_EQ(1U, GetStoredVerdictCount(
+                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
   LoginReputationClientResponse actual_verdict;
-  // Has cached verdict for foo.com/abc.
-  EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION,
+  // Has cached PASSWORD_REUSE_EVENT verdict for foo.com/abc.
+  EXPECT_EQ(
+      LoginReputationClientResponse::LOW_REPUTATION,
+      password_protection_service_->GetCachedVerdict(
+          GURL("https://foo.com/abc/test.jsp"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  // No cached PASSWORD_REUSE_EVENT verdict for foo.com/def.
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("https://foo.com/def/index.jsp"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  // No cached PASSWORD_REUSE_EVENT verdict for bar.com/abc.
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("https://bar.com/abc/index.jsp"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  // No cached PASSWORD_REUSE_EVENT verdict for bar.com/def.
+  EXPECT_EQ(
+      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      password_protection_service_->GetCachedVerdict(
+          GURL("https://bar.com/def/index.jsp"),
+          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+
+  // Has cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/def.
+  EXPECT_EQ(LoginReputationClientResponse::SAFE,
             password_protection_service_->GetCachedVerdict(
-                GURL("https://foo.com/abc/test.jsp"), &actual_verdict));
-  // No cached verdict for foo.com/def.
+                GURL("https://bar.com/def/index.jsp"),
+                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+                &actual_verdict));
+
+  // No cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/xyz.
   EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
             password_protection_service_->GetCachedVerdict(
-                GURL("https://foo.com/def/index.jsp"), &actual_verdict));
-  // Nothing in content setting for bar.com.
-  EXPECT_EQ(nullptr, content_setting_map_->GetWebsiteSetting(
-                         GURL("https://bar.com"), GURL(),
-                         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
-                         std::string(), nullptr));
+                GURL("https://bar.com/xyz/index.jsp"),
+                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
+                &actual_verdict));
 }
 
 TEST_F(PasswordProtectionServiceTest, VerifyPasswordOnFocusRequestProto) {
diff --git a/components/sync/base/get_session_name.cc b/components/sync/base/get_session_name.cc
index 1d3aebd..2df94e5 100644
--- a/components/sync/base/get_session_name.cc
+++ b/components/sync/base/get_session_name.cc
@@ -11,6 +11,8 @@
 #include "base/strings/string_util.h"
 #include "base/sys_info.h"
 #include "base/task_runner.h"
+#include "base/task_runner_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 
 #if defined(OS_CHROMEOS)
@@ -32,6 +34,7 @@
 namespace {
 
 std::string GetSessionNameSynchronously() {
+  base::ThreadRestrictions::AssertIOAllowed();
   std::string session_name;
 #if defined(OS_CHROMEOS)
   switch (chromeos::GetDeviceType()) {
@@ -72,26 +75,14 @@
   return session_name;
 }
 
-void FillSessionName(std::string* session_name) {
-  *session_name = GetSessionNameSynchronously();
-}
-
-void OnSessionNameFilled(
-    const base::Callback<void(const std::string&)>& done_callback,
-    std::string* session_name) {
-  done_callback.Run(*session_name);
-}
-
 }  // namespace
 
 void GetSessionName(
     const scoped_refptr<base::TaskRunner>& task_runner,
     const base::Callback<void(const std::string&)>& done_callback) {
-  std::string* session_name = new std::string();
-  task_runner->PostTaskAndReply(
-      FROM_HERE, base::Bind(&FillSessionName, base::Unretained(session_name)),
-      base::Bind(&OnSessionNameFilled, done_callback,
-                 base::Owned(session_name)));
+  base::PostTaskAndReplyWithResult(task_runner.get(), FROM_HERE,
+                                   base::Bind(&GetSessionNameSynchronously),
+                                   done_callback);
 }
 
 std::string GetSessionNameSynchronouslyForTesting() {
diff --git a/components/sync/device_info/local_device_info_provider.h b/components/sync/device_info/local_device_info_provider.h
index 3efe28b2..a0973f4e 100644
--- a/components/sync/device_info/local_device_info_provider.h
+++ b/components/sync/device_info/local_device_info_provider.h
@@ -10,10 +10,6 @@
 
 #include "base/callback_list.h"
 
-namespace base {
-class TaskRunner;
-}
-
 namespace syncer {
 
 class DeviceInfo;
@@ -43,10 +39,8 @@
   virtual std::string GetLocalSyncCacheGUID() const = 0;
 
   // Starts initializing local device info.
-  virtual void Initialize(
-      const std::string& cache_guid,
-      const std::string& signin_scoped_device_id,
-      const scoped_refptr<base::TaskRunner>& blocking_task_runner) = 0;
+  virtual void Initialize(const std::string& cache_guid,
+                          const std::string& signin_scoped_device_id) = 0;
 
   // Registers a callback to be called when local device info becomes available.
   // The callback will remain registered until the
diff --git a/components/sync/device_info/local_device_info_provider_impl.cc b/components/sync/device_info/local_device_info_provider_impl.cc
index 4b50c63..d09ffe0 100644
--- a/components/sync/device_info/local_device_info_provider_impl.cc
+++ b/components/sync/device_info/local_device_info_provider_impl.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/task_runner.h"
+#include "base/task_scheduler/post_task.h"
 #include "build/build_config.h"
 #include "components/sync/base/get_session_name.h"
 #include "components/sync/driver/sync_util.h"
@@ -74,14 +74,15 @@
 
 void LocalDeviceInfoProviderImpl::Initialize(
     const std::string& cache_guid,
-    const std::string& signin_scoped_device_id,
-    const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
+    const std::string& signin_scoped_device_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!cache_guid.empty());
   cache_guid_ = cache_guid;
 
   GetSessionName(
-      blocking_task_runner,
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}),
       base::Bind(&LocalDeviceInfoProviderImpl::InitializeContinuation,
                  weak_factory_.GetWeakPtr(), cache_guid,
                  signin_scoped_device_id));
diff --git a/components/sync/device_info/local_device_info_provider_impl.h b/components/sync/device_info/local_device_info_provider_impl.h
index f15743f..d7a5c76 100644
--- a/components/sync/device_info/local_device_info_provider_impl.h
+++ b/components/sync/device_info/local_device_info_provider_impl.h
@@ -28,10 +28,8 @@
   const DeviceInfo* GetLocalDeviceInfo() const override;
   std::string GetSyncUserAgent() const override;
   std::string GetLocalSyncCacheGUID() const override;
-  void Initialize(
-      const std::string& cache_guid,
-      const std::string& signin_scoped_device_id,
-      const scoped_refptr<base::TaskRunner>& blocking_task_runner) override;
+  void Initialize(const std::string& cache_guid,
+                  const std::string& signin_scoped_device_id) override;
   std::unique_ptr<Subscription> RegisterOnInitializedCallback(
       const base::Closure& callback) override;
   void Clear() override;
diff --git a/components/sync/device_info/local_device_info_provider_impl_unittest.cc b/components/sync/device_info/local_device_info_provider_impl_unittest.cc
index 9319c0a..56d7090 100644
--- a/components/sync/device_info/local_device_info_provider_impl_unittest.cc
+++ b/components/sync/device_info/local_device_info_provider_impl_unittest.cc
@@ -6,8 +6,8 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/sync/base/get_session_name.h"
 #include "components/version_info/version_string.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -37,8 +37,7 @@
   void StartInitializeProvider() { StartInitializeProvider(kLocalDeviceGuid); }
 
   void StartInitializeProvider(const std::string& guid) {
-    provider_->Initialize(guid, kSigninScopedDeviceId,
-                          message_loop_.task_runner());
+    provider_->Initialize(guid, kSigninScopedDeviceId);
   }
 
   void FinishInitializeProvider() {
@@ -67,7 +66,7 @@
   bool called_back_;
 
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 TEST_F(LocalDeviceInfoProviderImplTest, OnInitializedCallback) {
diff --git a/components/sync/device_info/local_device_info_provider_mock.cc b/components/sync/device_info/local_device_info_provider_mock.cc
index b147335..8507a53 100644
--- a/components/sync/device_info/local_device_info_provider_mock.cc
+++ b/components/sync/device_info/local_device_info_provider_mock.cc
@@ -40,8 +40,7 @@
 
 void LocalDeviceInfoProviderMock::Initialize(
     const std::string& cache_guid,
-    const std::string& signin_scoped_device_id,
-    const scoped_refptr<base::TaskRunner>& blocking_task_runner) {
+    const std::string& signin_scoped_device_id) {
   local_device_info_ = base::MakeUnique<DeviceInfo>(
       cache_guid, "client_name", "chrome_version", GetSyncUserAgent(),
       sync_pb::SyncEnums_DeviceType_TYPE_LINUX, signin_scoped_device_id);
diff --git a/components/sync/device_info/local_device_info_provider_mock.h b/components/sync/device_info/local_device_info_provider_mock.h
index 379514f..7f7528f 100644
--- a/components/sync/device_info/local_device_info_provider_mock.h
+++ b/components/sync/device_info/local_device_info_provider_mock.h
@@ -29,10 +29,8 @@
   const DeviceInfo* GetLocalDeviceInfo() const override;
   std::string GetSyncUserAgent() const override;
   std::string GetLocalSyncCacheGUID() const override;
-  void Initialize(
-      const std::string& cache_guid,
-      const std::string& signin_scoped_device_id,
-      const scoped_refptr<base::TaskRunner>& blocking_task_runner) override;
+  void Initialize(const std::string& cache_guid,
+                  const std::string& signin_scoped_device_id) override;
   std::unique_ptr<Subscription> RegisterOnInitializedCallback(
       const base::Closure& callback) override;
   void Clear() override;
diff --git a/components/sync/driver/fake_sync_client.cc b/components/sync/driver/fake_sync_client.cc
index 8346be6..698c01f 100644
--- a/components/sync/driver/fake_sync_client.cc
+++ b/components/sync/driver/fake_sync_client.cc
@@ -40,10 +40,6 @@
 
 void FakeSyncClient::Initialize() {}
 
-base::SequencedWorkerPool* FakeSyncClient::GetBlockingPool() {
-  return nullptr;
-}
-
 SyncService* FakeSyncClient::GetSyncService() {
   return sync_service_.get();
 }
diff --git a/components/sync/driver/fake_sync_client.h b/components/sync/driver/fake_sync_client.h
index aeb099e7..a5e8b48 100644
--- a/components/sync/driver/fake_sync_client.h
+++ b/components/sync/driver/fake_sync_client.h
@@ -25,7 +25,6 @@
 
   void Initialize() override;
 
-  base::SequencedWorkerPool* GetBlockingPool() override;
   SyncService* GetSyncService() override;
   PrefService* GetPrefService() override;
   base::FilePath GetLocalSyncBackendFolder() override;
diff --git a/components/sync/driver/sync_client.h b/components/sync/driver/sync_client.h
index ddf64d8..77d8f33e 100644
--- a/components/sync/driver/sync_client.h
+++ b/components/sync/driver/sync_client.h
@@ -22,10 +22,6 @@
 class PersonalDataManager;
 }  // namespace autofill
 
-namespace base {
-class SequencedWorkerPool;
-}  // namespace base
-
 namespace bookmarks {
 class BookmarkModel;
 }  // namespace bookmarks
@@ -65,10 +61,6 @@
   // Initializes the sync client with the specified sync service.
   virtual void Initialize() = 0;
 
-  // Returns SequencedWorkerPool to be used by ProfileSyncService for blocking
-  // operations.
-  virtual base::SequencedWorkerPool* GetBlockingPool() = 0;
-
   // Returns the current SyncService instance.
   virtual SyncService* GetSyncService() = 0;
 
diff --git a/components/sync_sessions/favicon_cache.cc b/components/sync_sessions/favicon_cache.cc
index dff0ae06..e6eddc55 100644
--- a/components/sync_sessions/favicon_cache.cc
+++ b/components/sync_sessions/favicon_cache.cc
@@ -9,6 +9,7 @@
 #include "base/location.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/history/core/browser/history_service.h"
@@ -961,7 +962,11 @@
 
 void FaviconCache::DropSyncedFavicon(FaviconMap::iterator favicon_iter) {
   DVLOG(1) << "Dropping favicon " << favicon_iter->second.get()->favicon_url;
+  const GURL& url = favicon_iter->first;
   recent_favicons_.erase(favicon_iter->second);
+  base::EraseIf(page_favicon_map_, [url](const PageFaviconMap::value_type& kv) {
+    return kv.second == url;
+  });
   synced_favicons_.erase(favicon_iter);
 }
 
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn
index f7ad715..6f6721e7 100644
--- a/components/translate/core/browser/BUILD.gn
+++ b/components/translate/core/browser/BUILD.gn
@@ -109,6 +109,7 @@
     "translate_ranker_impl_unittest.cc",
     "translate_script_unittest.cc",
     "translate_ui_delegate_unittest.cc",
+    "translate_url_util_unittest.cc",
   ]
   deps = [
     ":browser",
diff --git a/components/translate/core/browser/translate_url_util_unittest.cc b/components/translate/core/browser/translate_url_util_unittest.cc
new file mode 100644
index 0000000..bf901fb
--- /dev/null
+++ b/components/translate/core/browser/translate_url_util_unittest.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/translate/core/browser/translate_url_util.h"
+
+#include <string>
+
+#include "components/translate/core/browser/translate_download_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace translate {
+namespace {
+
+TEST(TranslateUrlUtilTest, AddHostLocaleToUrl) {
+  const std::string kExampleUrl = "http://www.example.com";
+
+  // Cache existing locale so it can be restored.
+  const std::string kExistingLocale =
+      TranslateDownloadManager::GetInstance()->application_locale();
+  TranslateDownloadManager::GetInstance()->set_application_locale("es");
+  const GURL url = AddHostLocaleToUrl(GURL(kExampleUrl));
+  EXPECT_EQ(url.spec(), kExampleUrl + "/?hl=es");
+  EXPECT_TRUE(url.is_valid());
+
+  // Restore locale.
+  TranslateDownloadManager::GetInstance()->set_application_locale(
+      kExistingLocale);
+}
+
+}  // namespace
+}  // namespace translate
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 73cd9aa8..a1df1c1 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -8,6 +8,7 @@
   sources = [
     "action_runner.cc",
     "action_runner.h",
+    "action_runner_win.cc",
     "background_downloader_win.cc",
     "background_downloader_win.h",
     "component.cc",
diff --git a/components/update_client/action_runner.cc b/components/update_client/action_runner.cc
index cc0bf5ec..5183fa3 100644
--- a/components/update_client/action_runner.cc
+++ b/components/update_client/action_runner.cc
@@ -5,15 +5,16 @@
 #include "components/update_client/action_runner.h"
 
 #include <iterator>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-
 #include "components/update_client/component.h"
 #include "components/update_client/update_client.h"
 
@@ -73,10 +74,36 @@
 void ActionRunner::UnpackComplete(const ComponentUnpacker::Result& result) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
-  // TODO(sorin): invoke the command runner here. For now, just return
-  // canned values for the unit test.
-  base::DeleteFile(result.unpack_path, true);
-  main_task_runner_->PostTask(FROM_HERE, base::Bind(run_complete_, true, 1, 2));
+  if (result.error != UnpackerError::kNone) {
+    DCHECK(!base::DirectoryExists(result.unpack_path));
+
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(run_complete_, false, static_cast<int>(result.error),
+                   result.extended_error));
+    return;
+  }
+
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ActionRunner::RunCommand, base::Unretained(this),
+                     MakeCommandLine(result.unpack_path)));
 }
 
+#if !defined(OS_WIN)
+
+void ActionRunner::RunCommand(const base::CommandLine& cmdline) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  main_task_runner_->PostTask(FROM_HERE,
+                              base::Bind(run_complete_, false, -1, 0));
+}
+
+base::CommandLine ActionRunner::MakeCommandLine(
+    const base::FilePath& unpack_path) const {
+  return base::CommandLine(base::CommandLine::NO_PROGRAM);
+}
+
+#endif  // OS_WIN
+
 }  // namespace update_client
diff --git a/components/update_client/action_runner.h b/components/update_client/action_runner.h
index 1517f757..3ae70209 100644
--- a/components/update_client/action_runner.h
+++ b/components/update_client/action_runner.h
@@ -16,6 +16,8 @@
 #include "components/update_client/component_unpacker.h"
 
 namespace base {
+class CommandLine;
+class Process;
 class SequencedTaskRunner;
 }
 
@@ -36,9 +38,14 @@
 
  private:
   void Unpack();
-
   void UnpackComplete(const ComponentUnpacker::Result& result);
 
+  void RunCommand(const base::CommandLine& cmdline);
+
+  base::CommandLine MakeCommandLine(const base::FilePath& unpack_path) const;
+
+  void WaitForCommand(base::Process process);
+
   const Component& component_;
   const scoped_refptr<base::SequencedTaskRunner>& task_runner_;
 
diff --git a/components/update_client/action_runner_win.cc b/components/update_client/action_runner_win.cc
new file mode 100644
index 0000000..cc02f7ca
--- /dev/null
+++ b/components/update_client/action_runner_win.cc
@@ -0,0 +1,58 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/update_client/action_runner.h"
+
+#include <utility>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/process/launch.h"
+#include "base/process/process.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+
+namespace {
+
+// TODO(sorin): rename to "ChromeRecovery.exe".
+const base::FilePath::CharType kRecoveryFileName[] =
+    FILE_PATH_LITERAL("recovery.exe");
+
+}  // namespace
+
+namespace update_client {
+
+void ActionRunner::RunCommand(const base::CommandLine& cmdline) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  base::LaunchOptions options;
+  options.start_hidden = true;
+  base::Process process = base::LaunchProcess(cmdline, options);
+
+  // This task joins a process, hence .WithBaseSyncPrimitives().
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      {base::WithBaseSyncPrimitives(), base::TaskPriority::BACKGROUND,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(&ActionRunner::WaitForCommand, base::Unretained(this),
+                     std::move(process)));
+}
+
+void ActionRunner::WaitForCommand(base::Process process) {
+  int exit_code = 0;
+  const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(600);
+  const bool succeeded =
+      process.WaitForExitWithTimeout(kMaxWaitTime, &exit_code);
+
+  main_task_runner_->PostTask(
+      FROM_HERE, base::Bind(run_complete_, succeeded, exit_code, 0));
+}
+
+base::CommandLine ActionRunner::MakeCommandLine(
+    const base::FilePath& unpack_path) const {
+  return base::CommandLine(unpack_path.Append(kRecoveryFileName));
+}
+
+}  // namespace update_client
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 1c9e24d..03da14c 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -3022,6 +3022,8 @@
   update_client->RemoveObserver(&observer);
 }
 
+#if defined(OS_WIN)  // ActionRun is only implemented on Windows.
+
 // Tests that a run action in invoked in the CRX install scenario.
 TEST_F(UpdateClientTest, ActionRun_Install) {
   class FakeUpdateChecker : public UpdateChecker {
@@ -3149,8 +3151,8 @@
           "total=\"1843\" download_time_ms=\"1000\"/>",
           events[0].c_str());
       EXPECT_STREQ(
-          "<event eventtype=\"42\" eventresult=\"1\" errorcode=\"1\" "
-          "extracode1=\"2\"/>",
+          "<event eventtype=\"42\" eventresult=\"1\" "
+          "errorcode=\"1877345072\"/>",
           events[1].c_str());
       EXPECT_STREQ("<event eventtype=\"3\" eventresult=\"1\"/>",
                    events[2].c_str());
@@ -3162,6 +3164,7 @@
           config(), base::MakeUnique<FakePingManager>(config()),
           &FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
 
+  // The action is a program which returns 1877345072 as a hardcoded value.
   update_client->Install(
       std::string("nieaegbcncggjkpbaogejidgjnnfegoe"),
       base::Bind([](const std::vector<std::string>& ids,
@@ -3259,8 +3262,8 @@
       const auto& events = FakePingManagerImpl::events();
       EXPECT_EQ(1u, events.size());
       EXPECT_STREQ(
-          "<event eventtype=\"42\" eventresult=\"1\" errorcode=\"1\" "
-          "extracode1=\"2\"/>",
+          "<event eventtype=\"42\" eventresult=\"1\" "
+          "errorcode=\"1877345072\"/>",
           events[0].c_str());
     }
   };
@@ -3305,6 +3308,7 @@
           config(), base::MakeUnique<FakePingManager>(config()),
           &FakeUpdateChecker::Create, &FakeCrxDownloader::Create);
 
+  // The action is a program which returns 1877345072 as a hardcoded value.
   const std::vector<std::string> ids = {"nieaegbcncggjkpbaogejidgjnnfegoe"};
   update_client->Update(
       ids,
@@ -3331,4 +3335,6 @@
   RunThreads();
 }
 
+#endif  // OS_WIN
+
 }  // namespace update_client
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index 572f3c5..1f07ec6 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -915,6 +915,7 @@
       // the caller that nothing has happened.
       if (pending_entry_) {
         DiscardNonCommittedEntries();
+        delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
       }
       return false;
     default:
@@ -1776,26 +1777,13 @@
 }
 
 void NavigationControllerImpl::DiscardNonCommittedEntries() {
-  bool discarding_visible_entry = GetVisibleEntry() != GetLastCommittedEntry();
-  bool had_transient_entry = GetTransientEntry() != nullptr;
-
-  // Clearing the transient entry should always result in a change to the
-  // visible entry.
-  DCHECK(!had_transient_entry || discarding_visible_entry);
-
-  // Actually discard pending entries.
+  bool transient = transient_entry_index_ != -1;
   DiscardNonCommittedEntriesInternal();
 
-  DCHECK_EQ(GetVisibleEntry(), GetLastCommittedEntry());
-  DCHECK(!GetTransientEntry());
-  DCHECK(!GetPendingEntry());
-
-  if (discarding_visible_entry) {
-    // If we discarded a visible transient entry, invalidate all.
-    // Otherwise we've discarded a pending entry, and we only
-    // need to invalidate the URL.
-    delegate_->NotifyNavigationStateChanged(
-        had_transient_entry ? INVALIDATE_TYPE_ALL : INVALIDATE_TYPE_URL);
+  // If there was a transient entry, invalidate everything so the new active
+  // entry state is shown.
+  if (transient) {
+    delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_ALL);
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 9fd9d6d5..3754bebc 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1722,6 +1722,10 @@
     frame_tree_node_->render_manager()->OnBeforeUnloadACK(
         unload_ack_is_for_navigation_, proceed, before_unload_end_time);
   }
+
+  // If canceled, notify the delegate to cancel its pending navigation entry.
+  if (!proceed)
+    render_view_host_->GetDelegate()->DidCancelLoading();
 }
 
 bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
diff --git a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index 998ef8e..36c26f8 100644
--- a/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -148,24 +148,37 @@
 void BrowserPpapiHostImpl::AddInstance(
     PP_Instance instance,
     const PepperRendererInstanceData& renderer_instance_data) {
-  DCHECK(instance_map_.find(instance) == instance_map_.end());
-  instance_map_[instance] =
-      base::MakeUnique<InstanceData>(renderer_instance_data);
+  // NOTE: 'instance' may be coming from a compromised renderer process. We
+  // take care here to make sure an attacker can't overwrite data for an
+  // existing plugin instance.
+  // See http://crbug.com/733548.
+  if (instance_map_.find(instance) == instance_map_.end()) {
+    instance_map_[instance] =
+        base::MakeUnique<InstanceData>(renderer_instance_data);
+  } else {
+    NOTREACHED();
+  }
 }
 
 void BrowserPpapiHostImpl::DeleteInstance(PP_Instance instance) {
+  // NOTE: 'instance' may be coming from a compromised renderer process. We
+  // take care here to make sure an attacker can't cause a UAF by deleting a
+  // non-existent plugin instance.
+  // See http://crbug.com/733548.
   auto it = instance_map_.find(instance);
-  DCHECK(it != instance_map_.end());
+  if (it != instance_map_.end()) {
+    // We need to tell the observers for that instance that we are destroyed
+    // because we won't have the opportunity to once we remove them from the
+    // |instance_map_|. If the instance was deleted, observers for those
+    // instances should never call back into the host anyway, so it is safe to
+    // tell them that the host is destroyed.
+    for (auto& observer : it->second->observer_list)
+      observer.OnHostDestroyed();
 
-  // We need to tell the observers for that instance that we are destroyed
-  // because we won't have the opportunity to once we remove them from the
-  // |instance_map_|. If the instance was deleted, observers for those instances
-  // should never call back into the host anyway, so it is safe to tell them
-  // that the host is destroyed.
-  for (auto& observer : it->second->observer_list)
-    observer.OnHostDestroyed();
-
-  instance_map_.erase(it);
+    instance_map_.erase(it);
+  } else {
+    NOTREACHED();
+  }
 }
 
 void BrowserPpapiHostImpl::AddInstanceObserver(PP_Instance instance,
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index d62fe9c..be3dccd 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -232,12 +232,16 @@
     PP_Instance instance,
     const PepperRendererInstanceData& instance_data) {
   PepperRendererInstanceData data = instance_data;
+  // It's important that we supply the render process ID ourselves since the
+  // message may be coming from a compromised renderer.
   data.render_process_id = render_process_id_;
+  // 'instance' is possibly invalid. The host must be careful not to trust it.
   in_process_host_->AddInstance(instance, data);
 }
 
 void PepperRendererConnection::OnMsgDidDeleteInProcessInstance(
     PP_Instance instance) {
+  // 'instance' is possibly invalid. The host must be careful not to trust it.
   in_process_host_->DeleteInstance(instance);
 }
 
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 2c8e25ff..1490ac4 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -94,6 +94,9 @@
   // The page is trying to move the RenderView's representation in the client.
   virtual void RequestMove(const gfx::Rect& new_bounds) {}
 
+  // The pending page load was canceled.
+  virtual void DidCancelLoading() {}
+
   // The RenderView's main frame document element is ready. This happens when
   // the document has finished parsing.
   virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) {}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index f64e30a..d1bd434 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4813,6 +4813,13 @@
   return GetContentClient()->browser()->GetNavigationUIData(navigation_handle);
 }
 
+void WebContentsImpl::DidCancelLoading() {
+  controller_.DiscardNonCommittedEntries();
+
+  // Update the URL display.
+  NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
+}
+
 void WebContentsImpl::DidAccessInitialDocument() {
   has_accessed_initial_document_ = true;
 
@@ -5363,9 +5370,6 @@
     // meantime.  Do not reset the navigation state in that case.
     if (rfh && rfh == rfh->frame_tree_node()->current_frame_host()) {
       rfh->frame_tree_node()->BeforeUnloadCanceled();
-
-      // Remove the entry for the navigation that's being cancelled, and notify
-      // the WebContentsDelegate that the visible URL has changed.
       controller_.DiscardNonCommittedEntries();
     }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 30cb08d..4ef2a60d 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -581,6 +581,7 @@
                        const GURL& url) override;
   void Close(RenderViewHost* render_view_host) override;
   void RequestMove(const gfx::Rect& new_bounds) override;
+  void DidCancelLoading() override;
   void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) override;
   void RouteCloseEvent(RenderViewHost* rvh) override;
   bool DidAddMessageToConsole(int32_t level,
@@ -918,8 +919,6 @@
                            JavaScriptDialogsInMainAndSubframes);
   FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
                            DialogsFromJavaScriptEndFullscreen);
-  FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
-                           DismissingBeforeUnloadDialogInvalidatesUrl);
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
                            IframeBeforeUnloadParentHang);
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest,
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 7361143..2f161b01 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -939,145 +939,6 @@
 
 namespace {
 
-// Test implementation of WebContentsDelegate that handles and automatically
-// cancels beforeunload dialogs. This class also listens for
-// NavigationStateChanged(INVALIDATE_TYPE_URL) and records the state of
-// GetVisibleURL().
-class DialogDismissingWebContentsDelegate : public JavaScriptDialogManager,
-                                            public WebContentsDelegate {
- public:
-  DialogDismissingWebContentsDelegate()
-      : message_loop_runner_(new MessageLoopRunner) {}
-  ~DialogDismissingWebContentsDelegate() override {}
-
-  void WaitForDialogDismissed() {
-    message_loop_runner_->Run();
-    message_loop_runner_ = new MessageLoopRunner;
-  }
-
-  // The recent of values of web_contents()->GetVisibleURL(), recorded each time
-  // this WebContentsDelegate gets an INVALIDATE_TYPE_URL event.
-  std::vector<GURL> GetAndClearVisibleUrlInvalidations() {
-    return std::move(visible_url_invalidations_);
-  }
-
-  // WebContentsDelegate
-
-  JavaScriptDialogManager* GetJavaScriptDialogManager(
-      WebContents* source) override {
-    return this;
-  }
-  void NavigationStateChanged(WebContents* web_contents,
-                              InvalidateTypes invalidate_types) override {
-    if (invalidate_types & INVALIDATE_TYPE_URL) {
-      visible_url_invalidations_.push_back(web_contents->GetVisibleURL());
-    }
-  }
-
-  // JavaScriptDialogManager
-
-  void RunJavaScriptDialog(WebContents* web_contents,
-                           const GURL& origin_url,
-                           JavaScriptDialogType dialog_type,
-                           const base::string16& message_text,
-                           const base::string16& default_prompt_text,
-                           const DialogClosedCallback& callback,
-                           bool* did_suppress_message) override {}
-
-  void RunBeforeUnloadDialog(WebContents* web_contents,
-                             bool is_reload,
-                             const DialogClosedCallback& callback) override {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(callback, false, base::string16()));
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            message_loop_runner_->QuitClosure());
-  }
-
-  bool HandleJavaScriptDialog(WebContents* web_contents,
-                              bool accept,
-                              const base::string16* prompt_override) override {
-    return true;
-  }
-
-  void CancelDialogs(WebContents* web_contents, bool reset_state) override {}
-
- private:
-  std::vector<GURL> visible_url_invalidations_;
-
-  // The MessageLoopRunner used to spin the message loop.
-  scoped_refptr<MessageLoopRunner> message_loop_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(DialogDismissingWebContentsDelegate);
-};
-
-}  // namespace
-
-// Test that if a BeforeUnload dialog is destroyed due to the commit of a
-// same-site or cross-site navigation, it will not reset the loading state.
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
-                       DismissingBeforeUnloadDialogInvalidatesUrl) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  const GURL kStartURL(embedded_test_server()->GetURL(
-      "foo.com", "/render_frame_host/beforeunload.html"));
-  const GURL kSameSiteURL(
-      embedded_test_server()->GetURL("foo.com", "/title1.html"));
-  const GURL kCrossSiteURL(
-      embedded_test_server()->GetURL("bar.com", "/title1.html"));
-
-  // Navigate to a first web page with a BeforeUnload event listener.
-  EXPECT_TRUE(NavigateToURL(shell(), kStartURL));
-
-  DialogDismissingWebContentsDelegate web_contents_delegate;
-  shell()->web_contents()->SetDelegate(&web_contents_delegate);
-  PrepContentsForBeforeUnloadTest(shell()->web_contents());
-
-  // Start a same-site navigation that is cancelled because of the beforeunload
-  // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the
-  // cancellation, so that the location bar resets to the original URL.
-  shell()->LoadURL(kSameSiteURL);
-  EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
-  web_contents_delegate.WaitForDialogDismissed();
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  EXPECT_EQ(std::vector<GURL>{kStartURL},
-            web_contents_delegate.GetAndClearVisibleUrlInvalidations());
-
-  // Start a cross-site navigation that is cancelled because of the beforeunload
-  // dialog. INVALIDATE_TYPE_URL should be sent to the delegate after the
-  // cancellation, so that the location bar resets to the original URL.
-  shell()->LoadURL(kCrossSiteURL);
-  EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
-  web_contents_delegate.WaitForDialogDismissed();
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  EXPECT_EQ(std::vector<GURL>{kStartURL},
-            web_contents_delegate.GetAndClearVisibleUrlInvalidations());
-
-  // Now clear the unload handler and re-try the navigations, which should now
-  // succeed. INVALIDATE_TYPE_URL should happen on commit, with the value of the
-  // new URL.
-  EXPECT_TRUE(ExecuteScript(shell(),
-                            "window.onbeforeunload=function(e){return null;}"));
-  shell()->LoadURL(kSameSiteURL);
-  EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  EXPECT_EQ(kSameSiteURL, shell()->web_contents()->GetVisibleURL());
-  EXPECT_EQ(std::vector<GURL>{kSameSiteURL},
-            web_contents_delegate.GetAndClearVisibleUrlInvalidations());
-
-  shell()->LoadURL(kCrossSiteURL);
-  EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  EXPECT_EQ(kCrossSiteURL, shell()->web_contents()->GetVisibleURL());
-  EXPECT_EQ(std::vector<GURL>{kCrossSiteURL},
-            web_contents_delegate.GetAndClearVisibleUrlInvalidations());
-
-  // Clear the test delegates.
-  static_cast<WebContentsImpl*>(shell()->web_contents())
-      ->SetJavaScriptDialogManagerForTesting(nullptr);
-  shell()->web_contents()->SetDelegate(shell());
-}
-
-namespace {
-
 class TestJavaScriptDialogManager : public JavaScriptDialogManager,
                                     public WebContentsDelegate {
  public:
diff --git a/content/common/service_manager/embedded_service_runner.cc b/content/common/service_manager/embedded_service_runner.cc
index 665a6e3..7e217a1c 100644
--- a/content/common/service_manager/embedded_service_runner.cc
+++ b/content/common/service_manager/embedded_service_runner.cc
@@ -50,8 +50,8 @@
     DCHECK(service_task_runner_);
     service_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&InstanceManager::BindServiceRequestOnServiceThread,
-                   this, base::Passed(&request)));
+        base::Bind(&InstanceManager::BindServiceRequestOnServiceSequence, this,
+                   base::Passed(&request)));
   }
 
   void ShutDown() {
@@ -59,11 +59,11 @@
     if (!service_task_runner_)
       return;
     // Any extant ServiceContexts must be destroyed on the application thread.
-    if (service_task_runner_->BelongsToCurrentThread()) {
-      QuitOnServiceThread();
+    if (service_task_runner_->RunsTasksOnCurrentThread()) {
+      QuitOnServiceSequence();
     } else {
       service_task_runner_->PostTask(
-          FROM_HERE, base::Bind(&InstanceManager::QuitOnServiceThread, this));
+          FROM_HERE, base::Bind(&InstanceManager::QuitOnServiceSequence, this));
     }
   }
 
@@ -76,9 +76,9 @@
     DCHECK(!thread_);
   }
 
-  void BindServiceRequestOnServiceThread(
+  void BindServiceRequestOnServiceSequence(
       service_manager::mojom::ServiceRequest request) {
-    DCHECK(service_task_runner_->BelongsToCurrentThread());
+    DCHECK(service_task_runner_->RunsTasksOnCurrentThread());
 
     int instance_id = next_instance_id_++;
 
@@ -94,7 +94,7 @@
   }
 
   void OnInstanceLost(int instance_id) {
-    DCHECK(service_task_runner_->BelongsToCurrentThread());
+    DCHECK(service_task_runner_->RunsTasksOnCurrentThread());
 
     auto id_iter = id_to_context_map_.find(instance_id);
     CHECK(id_iter != id_to_context_map_.end());
@@ -106,14 +106,14 @@
 
     // If we've lost the last instance, run the quit closure.
     if (contexts_.empty())
-      QuitOnServiceThread();
+      QuitOnServiceSequence();
   }
 
-  void QuitOnServiceThread() {
-    DCHECK(service_task_runner_->BelongsToCurrentThread());
+  void QuitOnServiceSequence() {
+    DCHECK(service_task_runner_->RunsTasksOnCurrentThread());
 
     contexts_.clear();
-    if (quit_task_runner_->BelongsToCurrentThread()) {
+    if (quit_task_runner_->RunsTasksOnCurrentThread()) {
       QuitOnRunnerThread();
     } else {
       quit_task_runner_->PostTask(
@@ -142,7 +142,7 @@
 
   // These fields must only be accessed from the runner's thread.
   std::unique_ptr<base::Thread> thread_;
-  scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
 
   // These fields must only be accessed from the service thread, except in
   // the destructor which may run on either the runner thread or the service
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h
index c757da4d..ffe2eaed 100644
--- a/content/public/browser/navigation_controller.h
+++ b/content/public/browser/navigation_controller.h
@@ -291,8 +291,7 @@
 
   // Pending entry -------------------------------------------------------------
 
-  // Discards the pending and transient entries if any, and send an appropriate
-  // notification (INVALIDATE_TYPE_URL or INVALIDATE_TYPE_ALL) if they were.
+  // Discards the pending and transient entries if any.
   virtual void DiscardNonCommittedEntries() = 0;
 
   // Returns the pending entry corresponding to the navigation that is
diff --git a/content/public/common/service_info.h b/content/public/common/service_info.h
index dcfd270..a0df30c 100644
--- a/content/public/common/service_info.h
+++ b/content/public/common/service_info.h
@@ -35,7 +35,7 @@
   // The task runner on which to construct and bind new Service instances
   // for this service. If null, behavior depends on the value of
   // |use_own_thread| below.
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner;
+  scoped_refptr<base::SequencedTaskRunner> task_runner;
 
   // If |task_runner| is null, setting this to |true| will give each instance of
   // this service its own thread to run on. Setting this to |false| (the
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index 99ebfe0..ea4b7b2 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -98,6 +98,13 @@
   base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
       kTraceEventRendererProcessSortIndex);
 
+#if defined(OS_WIN) && defined(__clang__)
+  // TODO(thakis): Remove this again soon, it's here to check what effect
+  // renderer startup delays have on a particular metric in the next dev
+  // channel release.
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
+#endif
+
   const base::CommandLine& parsed_command_line = parameters.command_line;
 
 #if defined(OS_MACOSX)
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index adea703..0c6a517d 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -681,8 +681,6 @@
   test_phase_ = CLEAN_UP;
   if (!printer_->output_finished())
     printer_->PrintImageFooter();
-  RenderViewHost* render_view_host =
-      main_window_->web_contents()->GetRenderViewHost();
   main_window_->web_contents()->ExitFullscreen(/*will_cause_resize=*/false);
 
   ShellBrowserContext* browser_context =
@@ -690,12 +688,16 @@
   StoragePartition* storage_partition =
       BrowserContext::GetStoragePartition(browser_context, nullptr);
   storage_partition->GetServiceWorkerContext()->ClearAllServiceWorkersForTest(
-      base::Bind(base::IgnoreResult(&BlinkTestController::Send),
-                 base::Unretained(this),
-                 new ShellViewMsg_Reset(render_view_host->GetRoutingID())));
+      base::Bind(&BlinkTestController::OnAllServiceWorkersCleared,
+                 base::Unretained(this)));
   storage_partition->ClearBluetoothAllowedDevicesMapForTesting();
 }
 
+void BlinkTestController::OnAllServiceWorkersCleared() {
+  Send(new ShellViewMsg_Reset(
+      main_window_->web_contents()->GetRenderViewHost()->GetRoutingID()));
+}
+
 void BlinkTestController::OnImageDump(const std::string& actual_pixel_hash,
                                       const SkBitmap& image) {
   printer_->PrintImageHeader(actual_pixel_hash, expected_pixel_hash_);
diff --git a/content/shell/browser/layout_test/blink_test_controller.h b/content/shell/browser/layout_test/blink_test_controller.h
index a96d888..270ce4d 100644
--- a/content/shell/browser/layout_test/blink_test_controller.h
+++ b/content/shell/browser/layout_test/blink_test_controller.h
@@ -226,6 +226,8 @@
   mojom::LayoutTestControl* GetLayoutTestControlPtr(RenderFrameHost* frame);
   void HandleLayoutTestControlError(RenderFrameHost* frame);
 
+  void OnAllServiceWorkersCleared();
+
   std::unique_ptr<BlinkTestResultPrinter> printer_;
 
   base::FilePath current_working_directory_;
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index 20585331..09c91b67 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -1022,12 +1022,16 @@
 }
 
 void BlinkTestRunner::OnReset() {
+  // ShellViewMsg_Reset should always be sent to the *current* view.
+  DCHECK(render_view()->GetWebView()->MainFrame()->IsWebLocalFrame());
+  WebLocalFrame* main_frame =
+      render_view()->GetWebView()->MainFrame()->ToWebLocalFrame();
+
   LayoutTestRenderThreadObserver::GetInstance()->test_interfaces()->ResetAll();
   Reset(true /* for_new_test */);
   // Navigating to about:blank will make sure that no new loads are initiated
   // by the renderer.
-  WebURLRequest request = WebURLRequest(GURL(url::kAboutBlankURL));
-  render_view()->GetWebView()->MainFrame()->LoadRequest(request);
+  main_frame->LoadRequest(WebURLRequest(GURL(url::kAboutBlankURL)));
   Send(new ShellViewHostMsg_ResetDone(routing_id()));
 }
 
diff --git a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
index eaa5ce67..a24b4a24 100644
--- a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
+++ b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
@@ -47,7 +47,7 @@
 GvrGamepadDataFetcher::GvrGamepadDataFetcher(
     GvrGamepadDataProvider* data_provider,
     unsigned int display_id)
-    : display_id_(display_id) {
+    : display_id_(display_id), gamepad_data_({}) {
   // Called on UI thread.
   DVLOG(1) << __FUNCTION__ << "=" << this;
   data_provider->RegisterGvrGamepadDataFetcher(this);
@@ -85,7 +85,6 @@
   if (state->active_state == GAMEPAD_NEWLY_ACTIVE) {
     // This is the first time we've seen this device, so do some one-time
     // initialization
-    pad.connected = true;
     CopyToUString(pad.id, Gamepad::kIdLengthCap,
                   base::UTF8ToUTF16("Daydream Controller"));
     CopyToUString(pad.mapping, Gamepad::kMappingLengthCap,
@@ -99,6 +98,7 @@
         provided_data.right_handed ? GamepadHand::kRight : GamepadHand::kLeft;
   }
 
+  pad.connected = provided_data.connected;
   pad.timestamp = provided_data.timestamp;
 
   if (provided_data.is_touching) {
diff --git a/device/vr/android/gvr/gvr_gamepad_data_provider.h b/device/vr/android/gvr/gvr_gamepad_data_provider.h
index e67e7c9..53a84e11 100644
--- a/device/vr/android/gvr/gvr_gamepad_data_provider.h
+++ b/device/vr/android/gvr/gvr_gamepad_data_provider.h
@@ -24,6 +24,7 @@
   bool is_touching;
   bool controller_button_pressed;
   bool right_handed;
+  bool connected;
 };
 
 // This class exposes GVR controller data to the gamepad API. Data is
diff --git a/docs/process/images/release_cycle.png b/docs/process/images/release_cycle.png
new file mode 100644
index 0000000..a8aef75
--- /dev/null
+++ b/docs/process/images/release_cycle.png
Binary files differ
diff --git a/docs/process/release_cycle.md b/docs/process/release_cycle.md
new file mode 100644
index 0000000..af2a07f
--- /dev/null
+++ b/docs/process/release_cycle.md
@@ -0,0 +1,77 @@
+# Chrome Release Cycle
+
+[TOC]
+
+## Overview
+
+Chrome pushes a new stable version to the public every 6 weeks while
+taking 7 weeks to stabilize the beta branch.
+
+## Schedule
+
+![Schedule](images/release_cycle.png)
+* Feature freeze and branch point dates are fixed, but release dates may change
+depending on the build quality.
+* There would be some adjustment in the release schedule due to Chrome no
+meeting weeks or holidays.
+
+## Key Dates
+
+### Feature Freeze
+
+**2 weeks** before the branch point, the feature freeze is declared! Any feature
+planned to launch with this milestone should be code-complete (its
+implementation should be done) and enabled on Trunk/Canary so that the test team
+can give initial feedback. By the feature freeze, all strings must be landed!
+
+### Branch Point
+
+**Every 6 weeks**, the latest canary is declared as the new milestone
+stabilization branch with a number (used as the branch name) associated with it.
+The feature enhancement should be completed by the branch point and all
+ReleaseBlock-Beta bugs should be fixed. Avoid committing big and risky changes
+close to the branch point!
+
+### First Beta
+
+**2 weeks** after the branch point, the first beta release is pushed. All
+disabled tests associated with the release milestone should be completely
+addressed. New beta builds are pushed weekly until the stable release.
+
+### Stable Cut
+
+The Thursday before the stable release date, the last build from the beta branch
+is cut as the release build. All ReleaseBlock-Stable bugs should be fixed by the
+stable cut, which consequently corresponds to the absolute last date a merge to
+the release branch should be taken for inclusion in the initial stable release.
+The stable cut will, unless there are exceptions, use the final beta as its
+basis.
+
+### Stable Release
+
+**7 weeks** after the branch point a new major version is released. The
+stable rollout is staged over time so that any issues can be detected early and
+addressed before they reach all users. Each Chrome platform has a different
+stable rollout plan and the schedule below can vary based on circumstances:
+
+*  **Desktop**: Desktop consists of three main platforms, Windows, Mac, and
+Linux. Linux is ramped up to 100% immediately. Mac and Windows follow a
+staged rollout as follows:
+    * 5% deployment ->15% deployment ->50% deployment ->100% deployment.
+*  **Android**: Android releases both Chrome and WebView with each release, and
+follows a pattern similar to:
+    * 1% deployment -> 5% deployment -> 10% deployment -> 50% deployment
+    -> 100% deployment.
+*  **iOS**: iOS follows a phased release with no control over the following
+rollout percentage schedule:
+    * Day 1: 1% -> Day 2: 2% -> Day 3: 5% -> Day 4: 10% -> Day 5: 20%
+    -> Day 6: 50% -> Day 7: 100%.
+
+### Stable Refresh
+
+A stable refresh is defined as a release of a new Chrome build outside of the
+normal release schedule to fix critical bugs detected during the stable rollout.
+Except for extremely critical issues (e.g. security or privacy escalations),
+a Chrome stable refresh should not be pushed more than **2 weeks** after the
+initial build has been released to the public. In this case, we should consider
+punting any detected production issues to the next release.
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.h b/ios/chrome/browser/sync/ios_chrome_sync_client.h
index 3d93a7c..6f6a8ba5 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.h
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.h
@@ -38,7 +38,6 @@
 
   // SyncClient implementation.
   void Initialize() override;
-  base::SequencedWorkerPool* GetBlockingPool() override;
   syncer::SyncService* GetSyncService() override;
   PrefService* GetPrefService() override;
   base::FilePath GetLocalSyncBackendFolder() override;
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index d066897..fd9fe29 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -180,10 +180,6 @@
   }
 }
 
-base::SequencedWorkerPool* IOSChromeSyncClient::GetBlockingPool() {
-  return web::WebThread::GetBlockingPool();
-}
-
 syncer::SyncService* IOSChromeSyncClient::GetSyncService() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   return IOSChromeProfileSyncServiceFactory::GetForBrowserState(browser_state_);
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm
index 8ca6be4..31ee7e8 100644
--- a/ios/chrome/browser/web/visible_url_egtest.mm
+++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -496,7 +496,8 @@
 
 // Tests that visible URL is always the same as last committed URL if user
 // issues 2 go forward commands to WebUI page (crbug.com/711465).
-- (void)testDoubleForwardNavigationToWebUIPage {
+// TODO(crbug.com/734856): Reenable test when fixed.
+- (void)DISABLED_testDoubleForwardNavigationToWebUIPage {
   // Create 3rd entry in the history, to be able to go back twice.
   GURL URL(kChromeUIVersionURL);
   [ChromeEarlGrey loadURL:GURL(kChromeUIVersionURL)];
diff --git a/ios/web/public/crw_session_certificate_policy_cache_storage.h b/ios/web/public/crw_session_certificate_policy_cache_storage.h
index 36c0c353..3ea26c0 100644
--- a/ios/web/public/crw_session_certificate_policy_cache_storage.h
+++ b/ios/web/public/crw_session_certificate_policy_cache_storage.h
@@ -16,6 +16,14 @@
 
 #pragma mark - CRWSessionCertificateStorage
 
+namespace web {
+// Serialization keys used in CRWSessionCertificateStorage's NSCoding
+// implementation.
+extern NSString* const kCertificateSerializationKey;
+extern NSString* const kHostSerializationKey;
+extern NSString* const kStatusSerializationKey;
+}  // namespace web
+
 // A serializable representation of a certificate.
 @interface CRWSessionCertificateStorage : NSObject<NSCoding>
 
@@ -37,6 +45,12 @@
 
 #pragma mark - CRWSessionCertificatePolicyCacheStorage
 
+namespace web {
+// Serialization key used in CRWSessionCertificatePolicyCacheStorage's NSCoding
+// implementation.
+extern NSString* const kCertificateStoragesKey;
+}  // namespace web
+
 // A serializable representation of a list of allowed certificates.
 @interface CRWSessionCertificatePolicyCacheStorage : NSObject<NSCoding>
 
diff --git a/ios/web/public/crw_session_certificate_policy_cache_storage.mm b/ios/web/public/crw_session_certificate_policy_cache_storage.mm
index 527e40d..970334d 100644
--- a/ios/web/public/crw_session_certificate_policy_cache_storage.mm
+++ b/ios/web/public/crw_session_certificate_policy_cache_storage.mm
@@ -12,8 +12,7 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
+namespace web {
 // CRWSessionCertificateStorage serialization keys.
 NSString* const kCertificateSerializationKey = @"CertificateSerializationKey";
 NSString* const kHostSerializationKey = @"HostSerializationKey";
@@ -22,6 +21,9 @@
 // CRWSessionCertificatePolicyCacheStorage serialization keys.
 NSString* const kCertificateStoragesKey = @"kCertificateStoragesKey";
 NSString* const kCertificateStoragesDeprecatedKey = @"allowedCertificates";
+}  // namespace web
+
+namespace {
 
 // The deprecated serialization technique serialized each certificate policy as
 // an NSArray, where the necessary information is stored at the following
@@ -58,6 +60,12 @@
   std::string _host;
 }
 
+// Initializes the CRWSessionCertificateStorage using decoded values.  Can
+// return nil if the parameters cannot be converted correctly to a cert storage.
+- (instancetype)initWithCertData:(NSData*)certData
+                        hostName:(NSString*)hostName
+                      certStatus:(NSNumber*)certStatus;
+
 // Initializes the CRWSessionCertificateStorage using the deprecated
 // serialization technique.  See DeprecatedSerializationIndices above for more
 // details.
@@ -73,6 +81,8 @@
 - (instancetype)initWithCertificate:(scoped_refptr<net::X509Certificate>)cert
                                host:(const std::string&)host
                              status:(net::CertStatus)status {
+  DCHECK(cert);
+  DCHECK(host.length());
   if ((self = [super init])) {
     _certificate = cert;
     _host = host;
@@ -90,38 +100,42 @@
 #pragma mark NSCoding
 
 - (instancetype)initWithCoder:(NSCoder*)aDecoder {
-  NSData* certData = [aDecoder decodeObjectForKey:kCertificateSerializationKey];
-  NSString* hostString = [aDecoder decodeObjectForKey:kHostSerializationKey];
-  NSNumber* statusNumber =
-      [aDecoder decodeObjectForKey:kStatusSerializationKey];
-  if (!certData.length || !hostString.length || !statusNumber)
-    return nil;
-  return [self initWithCertificate:NSDataToCertificate(certData)
-                              host:base::SysNSStringToUTF8(hostString)
-                            status:statusNumber.unsignedIntegerValue];
+  NSData* certData =
+      [aDecoder decodeObjectForKey:web::kCertificateSerializationKey];
+  NSString* hostName = [aDecoder decodeObjectForKey:web::kHostSerializationKey];
+  NSNumber* certStatus =
+      [aDecoder decodeObjectForKey:web::kStatusSerializationKey];
+  return
+      [self initWithCertData:certData hostName:hostName certStatus:certStatus];
 }
 
 - (void)encodeWithCoder:(NSCoder*)aCoder {
   [aCoder encodeObject:CertificateToNSData(_certificate.get())
-                forKey:kCertificateSerializationKey];
+                forKey:web::kCertificateSerializationKey];
   [aCoder encodeObject:base::SysUTF8ToNSString(_host)
-                forKey:kHostSerializationKey];
-  [aCoder encodeObject:@(_status) forKey:kStatusSerializationKey];
+                forKey:web::kHostSerializationKey];
+  [aCoder encodeObject:@(_status) forKey:web::kStatusSerializationKey];
 }
 
 #pragma mark Private
 
+- (instancetype)initWithCertData:(NSData*)certData
+                        hostName:(NSString*)hostName
+                      certStatus:(NSNumber*)certStatus {
+  scoped_refptr<net::X509Certificate> cert = NSDataToCertificate(certData);
+  std::string host = base::SysNSStringToUTF8(hostName);
+  if (!cert || !host.length() || !certStatus)
+    return nil;
+  net::CertStatus status = certStatus.unsignedIntegerValue;
+  return [self initWithCertificate:cert host:host status:status];
+}
+
 - (instancetype)initWithDeprecatedSerialization:(NSArray*)serialization {
   if (serialization.count != DeprecatedSerializationIndexCount)
     return nil;
-  NSData* certData = serialization[CertificateDataIndex];
-  NSString* hostString = serialization[HostStringIndex];
-  NSNumber* statusNumber = serialization[StatusIndex];
-  if (!certData.length || !hostString.length || !statusNumber)
-    return nil;
-  return [self initWithCertificate:NSDataToCertificate(certData)
-                              host:base::SysNSStringToUTF8(hostString)
-                            status:[statusNumber unsignedIntegerValue]];
+  return [self initWithCertData:serialization[CertificateDataIndex]
+                       hostName:serialization[HostStringIndex]
+                     certStatus:serialization[StatusIndex]];
 }
 
 @end
@@ -137,11 +151,11 @@
 - (instancetype)initWithCoder:(NSCoder*)aDecoder {
   if ((self = [super init])) {
     _certificateStorages =
-        [aDecoder decodeObjectForKey:kCertificateStoragesKey];
+        [aDecoder decodeObjectForKey:web::kCertificateStoragesKey];
     if (!_certificateStorages.count) {
       // Attempt to use the deprecated serialization if none were decoded.
       NSMutableSet* deprecatedSerializations =
-          [aDecoder decodeObjectForKey:kCertificateStoragesDeprecatedKey];
+          [aDecoder decodeObjectForKey:web::kCertificateStoragesDeprecatedKey];
       NSMutableSet* certificateStorages = [[NSMutableSet alloc]
           initWithCapacity:deprecatedSerializations.count];
       for (NSArray* serialiazation in deprecatedSerializations) {
@@ -158,7 +172,8 @@
 }
 
 - (void)encodeWithCoder:(NSCoder*)aCoder {
-  [aCoder encodeObject:self.certificateStorages forKey:kCertificateStoragesKey];
+  [aCoder encodeObject:self.certificateStorages
+                forKey:web::kCertificateStoragesKey];
 }
 
 @end
diff --git a/ios/web/public/crw_session_certificate_policy_cache_storage_unittest.mm b/ios/web/public/crw_session_certificate_policy_cache_storage_unittest.mm
index 526fa64..696ba5f6 100644
--- a/ios/web/public/crw_session_certificate_policy_cache_storage_unittest.mm
+++ b/ios/web/public/crw_session_certificate_policy_cache_storage_unittest.mm
@@ -72,3 +72,19 @@
   id decoded = [NSKeyedUnarchiver unarchiveObjectWithData:data];
   EXPECT_TRUE(CacheStoragesAreEqual(cache_storage_.get(), decoded));
 }
+
+// Tests that unarchiving a CRWSessionCertificateStorage returns nil if the
+// certificate data does not correctly decode to a certificate.
+TEST(CRWSessionCertificateStorageTest, InvalidCertData) {
+  NSMutableData* data = [[NSMutableData alloc] init];
+  NSKeyedArchiver* archiver =
+      [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
+  [archiver encodeObject:[@"not a  cert" dataUsingEncoding:NSUTF8StringEncoding]
+                  forKey:web::kCertificateSerializationKey];
+  [archiver encodeObject:@"host" forKey:web::kHostSerializationKey];
+  [archiver encodeObject:@(net::CERT_STATUS_INVALID)
+                  forKey:web::kStatusSerializationKey];
+  [archiver finishEncoding];
+  id decoded = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+  EXPECT_FALSE(decoded);
+}
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index 5361d8e..b9f9a8ec 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -18,6 +18,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
@@ -208,7 +209,7 @@
   mojo::InterfaceEndpointController* AttachEndpointClient(
       const mojo::ScopedInterfaceEndpointHandle& handle,
       mojo::InterfaceEndpointClient* client,
-      scoped_refptr<base::SingleThreadTaskRunner> runner) override {
+      scoped_refptr<base::SequencedTaskRunner> runner) override {
     const mojo::InterfaceId id = handle.id();
 
     DCHECK(mojo::IsValidInterfaceId(id));
@@ -343,7 +344,7 @@
       disconnect_reason_ = disconnect_reason;
     }
 
-    base::SingleThreadTaskRunner* task_runner() const {
+    base::SequencedTaskRunner* task_runner() const {
       return task_runner_.get();
     }
 
@@ -353,11 +354,11 @@
     }
 
     void AttachClient(mojo::InterfaceEndpointClient* client,
-                      scoped_refptr<base::SingleThreadTaskRunner> runner) {
+                      scoped_refptr<base::SequencedTaskRunner> runner) {
       controller_->lock_.AssertAcquired();
       DCHECK(!client_);
       DCHECK(!closed_);
-      DCHECK(runner->BelongsToCurrentThread());
+      DCHECK(runner->RunsTasksOnCurrentThread());
 
       task_runner_ = std::move(runner);
       client_ = client;
@@ -366,7 +367,7 @@
     void DetachClient() {
       controller_->lock_.AssertAcquired();
       DCHECK(client_);
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
       DCHECK(!closed_);
 
       task_runner_ = nullptr;
@@ -400,20 +401,20 @@
 
     // mojo::InterfaceEndpointController:
     bool SendMessage(mojo::Message* message) override {
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
       message->set_interface_id(id_);
       return controller_->SendMessage(message);
     }
 
     void AllowWokenUpBySyncWatchOnSameThread() override {
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
       EnsureSyncWatcherExists();
       sync_watcher_->AllowWokenUpBySyncWatchOnSameThread();
     }
 
     bool SyncWatch(const bool* should_stop) override {
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
       // It's not legal to make sync calls from the master endpoint's thread,
       // and in fact they must only happen from the proxy task runner.
@@ -436,7 +437,7 @@
     }
 
     void OnSyncMessageEventReady() {
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
       scoped_refptr<Endpoint> keepalive(this);
       scoped_refptr<AssociatedGroupController> controller_keepalive(
@@ -483,7 +484,7 @@
     }
 
     void EnsureSyncWatcherExists() {
-      DCHECK(task_runner_->BelongsToCurrentThread());
+      DCHECK(task_runner_->RunsTasksOnCurrentThread());
       if (sync_watcher_)
         return;
 
@@ -519,7 +520,7 @@
     bool handle_created_ = false;
     base::Optional<mojo::DisconnectReason> disconnect_reason_;
     mojo::InterfaceEndpointClient* client_ = nullptr;
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+    scoped_refptr<base::SequencedTaskRunner> task_runner_;
     std::unique_ptr<mojo::SyncEventWatcher> sync_watcher_;
     std::unique_ptr<base::WaitableEvent> sync_message_event_;
     std::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
@@ -626,7 +627,7 @@
   void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) {
     lock_.AssertAcquired();
     DCHECK(endpoint->task_runner() && endpoint->client());
-    if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) {
+    if (endpoint->task_runner()->RunsTasksOnCurrentThread() && !force_async) {
       mojo::InterfaceEndpointClient* client = endpoint->client();
       base::Optional<mojo::DisconnectReason> reason(
           endpoint->disconnect_reason());
@@ -651,7 +652,7 @@
     if (!endpoint->client())
       return;
 
-    DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
+    DCHECK(endpoint->task_runner()->RunsTasksOnCurrentThread());
     NotifyEndpointOfError(endpoint, false /* force_async */);
   }
 
@@ -709,7 +710,7 @@
       return true;
 
     mojo::InterfaceEndpointClient* client = endpoint->client();
-    if (!client || !endpoint->task_runner()->BelongsToCurrentThread()) {
+    if (!client || !endpoint->task_runner()->RunsTasksOnCurrentThread()) {
       // No client has been bound yet or the client runs tasks on another
       // thread. We assume the other thread must always be the one on which
       // |proxy_task_runner_| runs tasks, since that's the only valid scenario.
@@ -765,7 +766,7 @@
     if (!client)
       return;
 
-    DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
+    DCHECK(endpoint->task_runner()->RunsTasksOnCurrentThread());
 
     // Sync messages should never make their way to this method.
     DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
@@ -794,7 +795,7 @@
     if (!client)
       return;
 
-    DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
+    DCHECK(endpoint->task_runner()->RunsTasksOnCurrentThread());
     MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
 
     // The message must have already been dequeued by the endpoint waking up
diff --git a/mojo/public/cpp/bindings/associated_binding.h b/mojo/public/cpp/bindings/associated_binding.h
index 6cae6e07..de0d85a 100644
--- a/mojo/public/cpp/bindings/associated_binding.h
+++ b/mojo/public/cpp/bindings/associated_binding.h
@@ -15,8 +15,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/associated_interface_request.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
@@ -72,7 +72,7 @@
                 MessageReceiverWithResponderStatus* receiver,
                 std::unique_ptr<MessageReceiver> payload_validator,
                 bool expect_sync_requests,
-                scoped_refptr<base::SingleThreadTaskRunner> runner,
+                scoped_refptr<base::SequencedTaskRunner> runner,
                 uint32_t interface_version);
 
   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
@@ -82,7 +82,7 @@
 // to Binding, except that it doesn't own a message pipe handle.
 //
 // When you bind this class to a request, optionally you can specify a
-// base::SingleThreadTaskRunner. This task runner must belong to the same
+// base::SequencedTaskRunner. This task runner must belong to the same
 // thread. It will be used to dispatch incoming method calls and connection
 // error notification. It is useful when you attach multiple task runners to a
 // single thread for the purposes of task scheduling. Please note that incoming
@@ -105,8 +105,8 @@
   // the binding.
   AssociatedBinding(ImplPointerType impl,
                     AssociatedInterfaceRequest<Interface> request,
-                    scoped_refptr<base::SingleThreadTaskRunner> runner =
-                        base::ThreadTaskRunnerHandle::Get())
+                    scoped_refptr<base::SequencedTaskRunner> runner =
+                        base::SequencedTaskRunnerHandle::Get())
       : AssociatedBinding(std::move(impl)) {
     Bind(std::move(request), std::move(runner));
   }
@@ -115,8 +115,8 @@
 
   // Sets up this object as the implementation side of an associated interface.
   void Bind(AssociatedInterfaceRequest<Interface> request,
-            scoped_refptr<base::SingleThreadTaskRunner> runner =
-                base::ThreadTaskRunnerHandle::Get()) {
+            scoped_refptr<base::SequencedTaskRunner> runner =
+                base::SequencedTaskRunnerHandle::Get()) {
     BindImpl(request.PassHandle(), &stub_,
              base::WrapUnique(new typename Interface::RequestValidator_()),
              Interface::HasSyncMethods_, std::move(runner),
diff --git a/mojo/public/cpp/bindings/associated_group_controller.h b/mojo/public/cpp/bindings/associated_group_controller.h
index d33c277..116c926 100644
--- a/mojo/public/cpp/bindings/associated_group_controller.h
+++ b/mojo/public/cpp/bindings/associated_group_controller.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
@@ -58,7 +58,7 @@
   virtual InterfaceEndpointController* AttachEndpointClient(
       const ScopedInterfaceEndpointHandle& handle,
       InterfaceEndpointClient* endpoint_client,
-      scoped_refptr<base::SingleThreadTaskRunner> runner) = 0;
+      scoped_refptr<base::SequencedTaskRunner> runner) = 0;
 
   // Detaches the client attached to the specified endpoint. It must be called
   // on the same thread as the corresponding AttachEndpointClient() call.
diff --git a/mojo/public/cpp/bindings/associated_interface_ptr.h b/mojo/public/cpp/bindings/associated_interface_ptr.h
index 64b6a6b..35c264e6 100644
--- a/mojo/public/cpp/bindings/associated_interface_ptr.h
+++ b/mojo/public/cpp/bindings/associated_interface_ptr.h
@@ -14,8 +14,8 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/associated_interface_request.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
@@ -71,8 +71,8 @@
   // comments of MakeRequest(AssociatedInterfacePtr<Interface>*) for more
   // details.
   void Bind(AssociatedInterfacePtrInfo<Interface> info,
-            scoped_refptr<base::SingleThreadTaskRunner> runner =
-                base::ThreadTaskRunnerHandle::Get()) {
+            scoped_refptr<base::SequencedTaskRunner> runner =
+                base::SequencedTaskRunnerHandle::Get()) {
     reset();
 
     if (info.is_valid())
@@ -186,8 +186,8 @@
 template <typename Interface>
 AssociatedInterfaceRequest<Interface> MakeRequest(
     AssociatedInterfacePtr<Interface>* ptr,
-    scoped_refptr<base::SingleThreadTaskRunner> runner =
-        base::ThreadTaskRunnerHandle::Get()) {
+    scoped_refptr<base::SequencedTaskRunner> runner =
+        base::SequencedTaskRunnerHandle::Get()) {
   AssociatedInterfacePtrInfo<Interface> ptr_info;
   auto request = MakeRequest(&ptr_info);
   ptr->Bind(std::move(ptr_info), std::move(runner));
@@ -231,13 +231,13 @@
     AssociatedInterfacePtr<Interface>* ptr) {
   MessagePipe pipe;
   scoped_refptr<internal::MultiplexRouter> router0 =
-      new internal::MultiplexRouter(std::move(pipe.handle0),
-                                    internal::MultiplexRouter::MULTI_INTERFACE,
-                                    false, base::ThreadTaskRunnerHandle::Get());
+      new internal::MultiplexRouter(
+          std::move(pipe.handle0), internal::MultiplexRouter::MULTI_INTERFACE,
+          false, base::SequencedTaskRunnerHandle::Get());
   scoped_refptr<internal::MultiplexRouter> router1 =
-      new internal::MultiplexRouter(std::move(pipe.handle1),
-                                    internal::MultiplexRouter::MULTI_INTERFACE,
-                                    true, base::ThreadTaskRunnerHandle::Get());
+      new internal::MultiplexRouter(
+          std::move(pipe.handle1), internal::MultiplexRouter::MULTI_INTERFACE,
+          true, base::SequencedTaskRunnerHandle::Get());
 
   ScopedInterfaceEndpointHandle endpoint0, endpoint1;
   ScopedInterfaceEndpointHandle::CreatePairPendingAssociation(&endpoint0,
diff --git a/mojo/public/cpp/bindings/binding.h b/mojo/public/cpp/bindings/binding.h
index ca4d74d..1e07a840 100644
--- a/mojo/public/cpp/bindings/binding.h
+++ b/mojo/public/cpp/bindings/binding.h
@@ -11,8 +11,8 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
@@ -60,7 +60,7 @@
 // bound to a message pipe, it may be bound or destroyed on any thread.
 //
 // When you bind this class to a message pipe, optionally you can specify a
-// base::SingleThreadTaskRunner. This task runner must belong to the same
+// base::SequencedTaskRunner. This task runner must belong to the same
 // thread. It will be used to dispatch incoming method calls and connection
 // error notification. It is useful when you attach multiple task runners to a
 // single thread for the purposes of task scheduling. Please note that incoming
@@ -82,8 +82,8 @@
   // |impl|, which must outlive the binding.
   Binding(ImplPointerType impl,
           InterfaceRequest<Interface> request,
-          scoped_refptr<base::SingleThreadTaskRunner> runner =
-              base::ThreadTaskRunnerHandle::Get())
+          scoped_refptr<base::SequencedTaskRunner> runner =
+              base::SequencedTaskRunnerHandle::Get())
       : Binding(std::move(impl)) {
     Bind(std::move(request), std::move(runner));
   }
@@ -96,8 +96,8 @@
   // implementation by removing the message pipe endpoint from |request| and
   // binding it to the previously specified implementation.
   void Bind(InterfaceRequest<Interface> request,
-            scoped_refptr<base::SingleThreadTaskRunner> runner =
-                base::ThreadTaskRunnerHandle::Get()) {
+            scoped_refptr<base::SequencedTaskRunner> runner =
+                base::SequencedTaskRunnerHandle::Get()) {
     internal_state_.Bind(request.PassMessagePipe(), std::move(runner));
   }
 
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
index 75db16a..340af92 100644
--- a/mojo/public/cpp/bindings/connector.h
+++ b/mojo/public/cpp/bindings/connector.h
@@ -13,8 +13,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/bindings/sync_handle_watcher.h"
@@ -50,14 +50,14 @@
   // The Connector takes ownership of |message_pipe|.
   Connector(ScopedMessagePipeHandle message_pipe,
             ConnectorConfig config,
-            scoped_refptr<base::SingleThreadTaskRunner> runner);
+            scoped_refptr<base::SequencedTaskRunner> runner);
   ~Connector() override;
 
   // Sets the receiver to handle messages read from the message pipe.  The
   // Connector will read messages from the pipe regardless of whether or not an
   // incoming receiver has been set.
   void set_incoming_receiver(MessageReceiver* receiver) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     incoming_receiver_ = receiver;
   }
 
@@ -65,21 +65,21 @@
   // state, where no more messages will be processed. This method is used
   // during testing to prevent that from happening.
   void set_enforce_errors_from_incoming_receiver(bool enforce) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     enforce_errors_from_incoming_receiver_ = enforce;
   }
 
   // Sets the error handler to receive notifications when an error is
   // encountered while reading from the pipe or waiting to read from the pipe.
   void set_connection_error_handler(base::OnceClosure error_handler) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     connection_error_handler_ = std::move(error_handler);
   }
 
   // Returns true if an error was encountered while reading from the pipe or
   // waiting to read from the pipe.
   bool encountered_error() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return error_;
   }
 
@@ -107,7 +107,7 @@
 
   // Is the connector bound to a MessagePipe handle?
   bool is_valid() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return message_pipe_.is_valid();
   }
 
@@ -124,7 +124,7 @@
   bool Accept(Message* message) override;
 
   MessagePipeHandle handle() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return message_pipe_.get();
   }
 
@@ -148,9 +148,7 @@
     return sync_handle_watcher_callback_count_ > 0;
   }
 
-  base::SingleThreadTaskRunner* task_runner() const {
-    return task_runner_.get();
-  }
+  base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
 
   // Sets the tag used by the heap profiler.
   // |tag| must be a const string literal.
@@ -191,7 +189,7 @@
   ScopedMessagePipeHandle message_pipe_;
   MessageReceiver* incoming_receiver_ = nullptr;
 
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::unique_ptr<SimpleWatcher> handle_watcher_;
 
   bool error_ = false;
@@ -210,7 +208,7 @@
   // callback.
   size_t sync_handle_watcher_callback_count_ = 0;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::Lock connected_lock_;
   bool connected_ = true;
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
index 2e303843..93c4ec8e 100644
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -18,8 +18,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
@@ -46,34 +46,34 @@
                           MessageReceiverWithResponderStatus* receiver,
                           std::unique_ptr<MessageReceiver> payload_validator,
                           bool expect_sync_requests,
-                          scoped_refptr<base::SingleThreadTaskRunner> runner,
+                          scoped_refptr<base::SequencedTaskRunner> runner,
                           uint32_t interface_version);
   ~InterfaceEndpointClient() override;
 
   // Sets the error handler to receive notifications when an error is
   // encountered.
   void set_connection_error_handler(base::OnceClosure error_handler) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     error_handler_ = std::move(error_handler);
     error_with_reason_handler_.Reset();
   }
 
   void set_connection_error_with_reason_handler(
       ConnectionErrorWithReasonCallback error_handler) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     error_with_reason_handler_ = std::move(error_handler);
     error_handler_.Reset();
   }
 
   // Returns true if an error was encountered.
   bool encountered_error() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return encountered_error_;
   }
 
   // Returns true if this endpoint has any pending callbacks.
   bool has_pending_responders() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return !async_responders_.empty() || !sync_responses_.empty();
   }
 
@@ -177,12 +177,12 @@
   ConnectionErrorWithReasonCallback error_with_reason_handler_;
   bool encountered_error_ = false;
 
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   internal::ControlMessageProxy control_message_proxy_;
   internal::ControlMessageHandler control_message_handler_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<InterfaceEndpointClient> weak_ptr_factory_;
 
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h
index f37343a5..431f575 100644
--- a/mojo/public/cpp/bindings/interface_ptr.h
+++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -14,8 +14,8 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
@@ -79,8 +79,8 @@
   // multiple task runners to a single thread for the purposes of task
   // scheduling.
   void Bind(InterfacePtrInfo<Interface> info,
-            scoped_refptr<base::SingleThreadTaskRunner> runner =
-                base::ThreadTaskRunnerHandle::Get()) {
+            scoped_refptr<base::SequencedTaskRunner> runner =
+                base::SequencedTaskRunnerHandle::Get()) {
     reset();
     if (info.is_valid())
       internal_state_.Bind(std::move(info), std::move(runner));
@@ -214,8 +214,8 @@
 template <typename Interface>
 InterfacePtr<Interface> MakeProxy(
     InterfacePtrInfo<Interface> info,
-    scoped_refptr<base::SingleThreadTaskRunner> runner =
-        base::ThreadTaskRunnerHandle::Get()) {
+    scoped_refptr<base::SequencedTaskRunner> runner =
+        base::SequencedTaskRunnerHandle::Get()) {
   InterfacePtr<Interface> ptr;
   if (info.is_valid())
     ptr.Bind(std::move(info), std::move(runner));
diff --git a/mojo/public/cpp/bindings/interface_request.h b/mojo/public/cpp/bindings/interface_request.h
index 94fc9a8c..54b18d7 100644
--- a/mojo/public/cpp/bindings/interface_request.h
+++ b/mojo/public/cpp/bindings/interface_request.h
@@ -10,8 +10,8 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
@@ -133,8 +133,8 @@
 template <typename Interface>
 InterfaceRequest<Interface> MakeRequest(
     InterfacePtr<Interface>* ptr,
-    scoped_refptr<base::SingleThreadTaskRunner> runner =
-        base::ThreadTaskRunnerHandle::Get()) {
+    scoped_refptr<base::SequencedTaskRunner> runner =
+        base::SequencedTaskRunnerHandle::Get()) {
   MessagePipe pipe;
   ptr->Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u),
             std::move(runner));
diff --git a/mojo/public/cpp/bindings/lib/associated_binding.cc b/mojo/public/cpp/bindings/lib/associated_binding.cc
index 6b1a3d2..eec391c 100644
--- a/mojo/public/cpp/bindings/lib/associated_binding.cc
+++ b/mojo/public/cpp/bindings/lib/associated_binding.cc
@@ -49,7 +49,7 @@
     MessageReceiverWithResponderStatus* receiver,
     std::unique_ptr<MessageReceiver> payload_validator,
     bool expect_sync_requests,
-    scoped_refptr<base::SingleThreadTaskRunner> runner,
+    scoped_refptr<base::SequencedTaskRunner> runner,
     uint32_t interface_version) {
   if (!handle.is_valid()) {
     endpoint_client_.reset();
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc b/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc
index 78281ed..833cd33 100644
--- a/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc
+++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr.cc
@@ -9,9 +9,9 @@
 void GetIsolatedInterface(ScopedInterfaceEndpointHandle handle) {
   MessagePipe pipe;
   scoped_refptr<internal::MultiplexRouter> router =
-      new internal::MultiplexRouter(std::move(pipe.handle0),
-                                    internal::MultiplexRouter::MULTI_INTERFACE,
-                                    false, base::ThreadTaskRunnerHandle::Get());
+      new internal::MultiplexRouter(
+          std::move(pipe.handle0), internal::MultiplexRouter::MULTI_INTERFACE,
+          false, base::SequencedTaskRunnerHandle::Get());
   router->AssociateInterface(std::move(handle));
 }
 
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
index 5544ce0..e726a699 100644
--- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
@@ -76,7 +76,7 @@
   }
 
   void Bind(AssociatedInterfacePtrInfo<Interface> info,
-            scoped_refptr<base::SingleThreadTaskRunner> runner) {
+            scoped_refptr<base::SequencedTaskRunner> runner) {
     DCHECK(!endpoint_client_);
     DCHECK(!proxy_);
     DCHECK_EQ(0u, version_);
diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc
index 2b2d3153..41195801 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.cc
+++ b/mojo/public/cpp/bindings/lib/binding_state.cc
@@ -74,7 +74,7 @@
 
 void BindingStateBase::BindInternal(
     ScopedMessagePipeHandle handle,
-    scoped_refptr<base::SingleThreadTaskRunner> runner,
+    scoped_refptr<base::SequencedTaskRunner> runner,
     const char* interface_name,
     std::unique_ptr<MessageReceiver> request_validator,
     bool passes_associated_kinds,
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h
index 888a3136..ba3163f5 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.h
+++ b/mojo/public/cpp/bindings/lib/binding_state.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/filter_chain.h"
@@ -77,7 +77,7 @@
 
  protected:
   void BindInternal(ScopedMessagePipeHandle handle,
-                    scoped_refptr<base::SingleThreadTaskRunner> runner,
+                    scoped_refptr<base::SequencedTaskRunner> runner,
                     const char* interface_name,
                     std::unique_ptr<MessageReceiver> request_validator,
                     bool passes_associated_kinds,
@@ -103,7 +103,7 @@
   ~BindingState() { Close(); }
 
   void Bind(ScopedMessagePipeHandle handle,
-            scoped_refptr<base::SingleThreadTaskRunner> runner) {
+            scoped_refptr<base::SequencedTaskRunner> runner) {
     BindingStateBase::BindInternal(
         std::move(handle), runner, Interface::Name_,
         base::MakeUnique<typename Interface::RequestValidator_>(),
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index 46051cb4..835e2831 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -130,7 +130,7 @@
 
 Connector::Connector(ScopedMessagePipeHandle message_pipe,
                      ConnectorConfig config,
-                     scoped_refptr<base::SingleThreadTaskRunner> runner)
+                     scoped_refptr<base::SequencedTaskRunner> runner)
     : message_pipe_(std::move(message_pipe)),
       task_runner_(std::move(runner)),
       nesting_observer_(RunLoopNestingObserver::GetForThread()),
@@ -152,7 +152,7 @@
       return;
   }
 
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CancelWait();
 }
 
@@ -162,7 +162,7 @@
 }
 
 ScopedMessagePipeHandle Connector::PassMessagePipe() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   CancelWait();
   internal::MayAutoLock locker(&lock_);
@@ -176,13 +176,13 @@
 }
 
 void Connector::RaiseError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   HandleError(true, true);
 }
 
 bool Connector::WaitForIncomingMessage(MojoDeadline deadline) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (error_)
     return false;
@@ -212,7 +212,7 @@
 }
 
 void Connector::PauseIncomingMethodCallProcessing() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (paused_)
     return;
@@ -222,7 +222,7 @@
 }
 
 void Connector::ResumeIncomingMethodCallProcessing() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!paused_)
     return;
@@ -232,7 +232,8 @@
 }
 
 bool Connector::Accept(Message* message) {
-  DCHECK(lock_ || thread_checker_.CalledOnValidThread());
+  if (!lock_)
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // It shouldn't hurt even if |error_| may be changed by a different thread at
   // the same time. The outcome is that we may write into |message_pipe_| after
@@ -281,7 +282,7 @@
 }
 
 void Connector::AllowWokenUpBySyncWatchOnSameThread() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   allow_woken_up_by_others_ = true;
 
@@ -290,7 +291,7 @@
 }
 
 bool Connector::SyncWatch(const bool* should_stop) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (error_)
     return false;
@@ -326,7 +327,7 @@
 }
 
 void Connector::OnHandleReadyInternal(MojoResult result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (result != MOJO_RESULT_OK) {
     HandleError(result != MOJO_RESULT_FAILED_PRECONDITION, false);
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index 6019b45..bd4b8a51 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -11,7 +11,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
@@ -39,7 +39,7 @@
  public:
   explicit ResponderThunk(
       const base::WeakPtr<InterfaceEndpointClient>& endpoint_client,
-      scoped_refptr<base::SingleThreadTaskRunner> runner)
+      scoped_refptr<base::SequencedTaskRunner> runner)
       : endpoint_client_(endpoint_client),
         accept_was_invoked_(false),
         task_runner_(std::move(runner)) {}
@@ -98,7 +98,7 @@
  private:
   base::WeakPtr<InterfaceEndpointClient> endpoint_client_;
   bool accept_was_invoked_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(ResponderThunk);
 };
@@ -134,7 +134,7 @@
     MessageReceiverWithResponderStatus* receiver,
     std::unique_ptr<MessageReceiver> payload_validator,
     bool expect_sync_requests,
-    scoped_refptr<base::SingleThreadTaskRunner> runner,
+    scoped_refptr<base::SequencedTaskRunner> runner,
     uint32_t interface_version)
     : expect_sync_requests_(expect_sync_requests),
       handle_(std::move(handle)),
@@ -161,7 +161,7 @@
 }
 
 InterfaceEndpointClient::~InterfaceEndpointClient() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (controller_)
     handle_.group_controller()->DetachEndpointClient(handle_);
@@ -174,7 +174,7 @@
 }
 
 ScopedInterfaceEndpointHandle InterfaceEndpointClient::PassHandle() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!has_pending_responders());
 
   if (!handle_.is_valid())
@@ -197,7 +197,7 @@
 }
 
 void InterfaceEndpointClient::RaiseError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!handle_.pending_association())
     handle_.group_controller()->RaiseError();
@@ -205,14 +205,14 @@
 
 void InterfaceEndpointClient::CloseWithReason(uint32_t custom_reason,
                                               const std::string& description) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   auto handle = PassHandle();
   handle.ResetWithReason(custom_reason, description);
 }
 
 bool InterfaceEndpointClient::Accept(Message* message) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!message->has_flag(Message::kFlagExpectsResponse));
   DCHECK(!handle_.pending_association());
 
@@ -235,7 +235,7 @@
 bool InterfaceEndpointClient::AcceptWithResponder(
     Message* message,
     std::unique_ptr<MessageReceiver> responder) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(message->has_flag(Message::kFlagExpectsResponse));
   DCHECK(!handle_.pending_association());
 
@@ -287,13 +287,13 @@
 }
 
 bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return filters_.Accept(message);
 }
 
 void InterfaceEndpointClient::NotifyError(
     const base::Optional<DisconnectReason>& reason) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (encountered_error_)
     return;
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
index ddfe785..c3d8360 100644
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -18,7 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/filter_chain.h"
@@ -93,7 +93,7 @@
   }
 
   void Bind(InterfacePtrInfo<Interface> info,
-            scoped_refptr<base::SingleThreadTaskRunner> runner) {
+            scoped_refptr<base::SequencedTaskRunner> runner) {
     DCHECK(!router_);
     DCHECK(!endpoint_client_);
     DCHECK(!proxy_);
@@ -214,7 +214,7 @@
   // read/write with the message pipe handle is needed. |handle_| is valid
   // between the Bind() call and the initialization of |router_|.
   ScopedMessagePipeHandle handle_;
-  scoped_refptr<base::SingleThreadTaskRunner> runner_;
+  scoped_refptr<base::SequencedTaskRunner> runner_;
 
   uint32_t version_;
 
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
index ff7c6782..d008ea94 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -12,9 +12,10 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
@@ -76,18 +77,16 @@
     disconnect_reason_ = disconnect_reason;
   }
 
-  base::SingleThreadTaskRunner* task_runner() const {
-    return task_runner_.get();
-  }
+  base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
 
   InterfaceEndpointClient* client() const { return client_; }
 
   void AttachClient(InterfaceEndpointClient* client,
-                    scoped_refptr<base::SingleThreadTaskRunner> runner) {
+                    scoped_refptr<base::SequencedTaskRunner> runner) {
     router_->AssertLockAcquired();
     DCHECK(!client_);
     DCHECK(!closed_);
-    DCHECK(runner->BelongsToCurrentThread());
+    DCHECK(runner->RunsTasksOnCurrentThread());
 
     task_runner_ = std::move(runner);
     client_ = client;
@@ -98,7 +97,7 @@
   void DetachClient() {
     router_->AssertLockAcquired();
     DCHECK(client_);
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
     DCHECK(!closed_);
 
     task_runner_ = nullptr;
@@ -130,20 +129,20 @@
   // AttachClient() call. They are called outside of the router's lock.
 
   bool SendMessage(Message* message) override {
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
     message->set_interface_id(id_);
     return router_->connector_.Accept(message);
   }
 
   void AllowWokenUpBySyncWatchOnSameThread() override {
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
     EnsureSyncWatcherExists();
     sync_watcher_->AllowWokenUpBySyncWatchOnSameThread();
   }
 
   bool SyncWatch(const bool* should_stop) override {
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
     EnsureSyncWatcherExists();
     return sync_watcher_->SyncWatch(should_stop);
@@ -162,7 +161,7 @@
   }
 
   void OnSyncEventSignaled() {
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
     scoped_refptr<MultiplexRouter> router_protector(router_);
 
     MayAutoLock locker(&router_->lock_);
@@ -184,7 +183,7 @@
   }
 
   void EnsureSyncWatcherExists() {
-    DCHECK(task_runner_->BelongsToCurrentThread());
+    DCHECK(task_runner_->RunsTasksOnCurrentThread());
     if (sync_watcher_)
       return;
 
@@ -225,7 +224,7 @@
   base::Optional<DisconnectReason> disconnect_reason_;
 
   // The task runner on which |client_|'s methods can be called.
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   // Not owned. It is null if no client is attached to this endpoint.
   InterfaceEndpointClient* client_;
 
@@ -322,7 +321,7 @@
     ScopedMessagePipeHandle message_pipe,
     Config config,
     bool set_interface_id_namesapce_bit,
-    scoped_refptr<base::SingleThreadTaskRunner> runner)
+    scoped_refptr<base::SequencedTaskRunner> runner)
     : set_interface_id_namespace_bit_(set_interface_id_namesapce_bit),
       task_runner_(runner),
       header_validator_(nullptr),
@@ -338,7 +337,7 @@
       encountered_error_(false),
       paused_(false),
       testing_mode_(false) {
-  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
 
   if (config == MULTI_INTERFACE)
     lock_.emplace();
@@ -389,7 +388,7 @@
 }
 
 void MultiplexRouter::SetMasterInterfaceName(const char* name) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   header_validator_->SetDescription(
       std::string(name) + " [master] MessageHeaderValidator");
   control_message_handler_.SetDescription(
@@ -487,7 +486,7 @@
 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient(
     const ScopedInterfaceEndpointHandle& handle,
     InterfaceEndpointClient* client,
-    scoped_refptr<base::SingleThreadTaskRunner> runner) {
+    scoped_refptr<base::SequencedTaskRunner> runner) {
   const InterfaceId id = handle.id();
 
   DCHECK(IsValidInterfaceId(id));
@@ -520,7 +519,7 @@
 }
 
 void MultiplexRouter::RaiseError() {
-  if (task_runner_->BelongsToCurrentThread()) {
+  if (task_runner_->RunsTasksOnCurrentThread()) {
     connector_.RaiseError();
   } else {
     task_runner_->PostTask(FROM_HERE,
@@ -529,7 +528,7 @@
 }
 
 void MultiplexRouter::CloseMessagePipe() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.CloseMessagePipe();
   // CloseMessagePipe() above won't trigger connection error handler.
   // Explicitly call OnPipeConnectionError() so that associated endpoints will
@@ -538,7 +537,7 @@
 }
 
 void MultiplexRouter::PauseIncomingMethodCallProcessing() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.PauseIncomingMethodCallProcessing();
 
   MayAutoLock locker(&lock_);
@@ -549,7 +548,7 @@
 }
 
 void MultiplexRouter::ResumeIncomingMethodCallProcessing() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.ResumeIncomingMethodCallProcessing();
 
   MayAutoLock locker(&lock_);
@@ -568,7 +567,7 @@
 }
 
 bool MultiplexRouter::HasAssociatedEndpoints() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   MayAutoLock locker(&lock_);
 
   if (endpoints_.size() > 1)
@@ -580,7 +579,7 @@
 }
 
 void MultiplexRouter::EnableTestingMode() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   MayAutoLock locker(&lock_);
 
   testing_mode_ = true;
@@ -588,7 +587,7 @@
 }
 
 bool MultiplexRouter::Accept(Message* message) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!message->DeserializeAssociatedEndpointHandles(this))
     return false;
@@ -662,7 +661,7 @@
 }
 
 void MultiplexRouter::OnPipeConnectionError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   scoped_refptr<MultiplexRouter> protector(this);
   MayAutoLock locker(&lock_);
@@ -689,7 +688,7 @@
 
 void MultiplexRouter::ProcessTasks(
     ClientCallBehavior client_call_behavior,
-    base::SingleThreadTaskRunner* current_task_runner) {
+    base::SequencedTaskRunner* current_task_runner) {
   AssertLockAcquired();
 
   if (posted_to_process_tasks_)
@@ -771,8 +770,9 @@
 bool MultiplexRouter::ProcessNotifyErrorTask(
     Task* task,
     ClientCallBehavior client_call_behavior,
-    base::SingleThreadTaskRunner* current_task_runner) {
-  DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
+    base::SequencedTaskRunner* current_task_runner) {
+  DCHECK(!current_task_runner ||
+         current_task_runner->RunsTasksOnCurrentThread());
   DCHECK(!paused_);
 
   AssertLockAcquired();
@@ -786,7 +786,7 @@
     return false;
   }
 
-  DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
+  DCHECK(endpoint->task_runner()->RunsTasksOnCurrentThread());
 
   InterfaceEndpointClient* client = endpoint->client();
   base::Optional<DisconnectReason> disconnect_reason(
@@ -807,8 +807,9 @@
 bool MultiplexRouter::ProcessIncomingMessage(
     Message* message,
     ClientCallBehavior client_call_behavior,
-    base::SingleThreadTaskRunner* current_task_runner) {
-  DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
+    base::SequencedTaskRunner* current_task_runner) {
+  DCHECK(!current_task_runner ||
+         current_task_runner->RunsTasksOnCurrentThread());
   DCHECK(!paused_);
   DCHECK(message);
   AssertLockAcquired();
@@ -849,7 +850,7 @@
   bool can_direct_call;
   if (message->has_flag(Message::kFlagIsSync)) {
     can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS &&
-                      endpoint->task_runner()->BelongsToCurrentThread();
+                      endpoint->task_runner()->RunsTasksOnCurrentThread();
   } else {
     can_direct_call = client_call_behavior == ALLOW_DIRECT_CLIENT_CALLS &&
                       endpoint->task_runner() == current_task_runner;
@@ -860,7 +861,7 @@
     return false;
   }
 
-  DCHECK(endpoint->task_runner()->BelongsToCurrentThread());
+  DCHECK(endpoint->task_runner()->RunsTasksOnCurrentThread());
 
   InterfaceEndpointClient* client = endpoint->client();
   bool result = false;
@@ -881,7 +882,7 @@
 }
 
 void MultiplexRouter::MaybePostToProcessTasks(
-    base::SingleThreadTaskRunner* task_runner) {
+    base::SequencedTaskRunner* task_runner) {
   AssertLockAcquired();
   if (posted_to_process_tasks_)
     return;
@@ -897,7 +898,7 @@
   // always called using base::Bind(), which holds a ref.
   MayAutoLock locker(&lock_);
   posted_to_process_tasks_ = false;
-  scoped_refptr<base::SingleThreadTaskRunner> runner(
+  scoped_refptr<base::SequencedTaskRunner> runner(
       std::move(posted_to_task_runner_));
   ProcessTasks(ALLOW_DIRECT_CLIENT_CALLS, runner.get());
 }
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
index 353bff6..a80be35d 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -17,9 +17,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/connector.h"
@@ -32,8 +32,14 @@
 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
+// TODO(sammc): Remove these includes. Various files are not including what they
+// use, but are instead depending on mojo headers including what they use.
+// To avoid unrelated changes, these includes are left for now.
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+
 namespace base {
-class SingleThreadTaskRunner;
+class SequencedTaskRunner;
 }
 
 namespace mojo {
@@ -76,7 +82,7 @@
   MultiplexRouter(ScopedMessagePipeHandle message_pipe,
                   Config config,
                   bool set_interface_id_namespace_bit,
-                  scoped_refptr<base::SingleThreadTaskRunner> runner);
+                  scoped_refptr<base::SequencedTaskRunner> runner);
 
   // Sets the master interface name for this router. Only used when reporting
   // message header or control message validation errors.
@@ -97,7 +103,7 @@
   InterfaceEndpointController* AttachEndpointClient(
       const ScopedInterfaceEndpointHandle& handle,
       InterfaceEndpointClient* endpoint_client,
-      scoped_refptr<base::SingleThreadTaskRunner> runner) override;
+      scoped_refptr<base::SequencedTaskRunner> runner) override;
   void DetachEndpointClient(
       const ScopedInterfaceEndpointHandle& handle) override;
   void RaiseError() override;
@@ -112,14 +118,14 @@
 
   // Extracts the underlying message pipe.
   ScopedMessagePipeHandle PassMessagePipe() {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     DCHECK(!HasAssociatedEndpoints());
     return connector_.PassMessagePipe();
   }
 
   // Blocks the current thread until the first incoming message, or |deadline|.
   bool WaitForIncomingMessage(MojoDeadline deadline) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return connector_.WaitForIncomingMessage(deadline);
   }
 
@@ -137,13 +143,13 @@
 
   // Is the router bound to a message pipe handle?
   bool is_valid() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return connector_.is_valid();
   }
 
   // TODO(yzshen): consider removing this getter.
   MessagePipeHandle handle() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return connector_.handle();
   }
 
@@ -191,7 +197,7 @@
   // of this object, if direct calls are allowed, the caller needs to hold on to
   // a ref outside of |lock_| before calling this method.
   void ProcessTasks(ClientCallBehavior client_call_behavior,
-                    base::SingleThreadTaskRunner* current_task_runner);
+                    base::SequencedTaskRunner* current_task_runner);
 
   // Processes the first queued sync message for the endpoint corresponding to
   // |id|; returns whether there are more sync messages for that endpoint in the
@@ -202,16 +208,14 @@
   bool ProcessFirstSyncMessageForEndpoint(InterfaceId id);
 
   // Returns true to indicate that |task|/|message| has been processed.
-  bool ProcessNotifyErrorTask(
-      Task* task,
-      ClientCallBehavior client_call_behavior,
-      base::SingleThreadTaskRunner* current_task_runner);
-  bool ProcessIncomingMessage(
-      Message* message,
-      ClientCallBehavior client_call_behavior,
-      base::SingleThreadTaskRunner* current_task_runner);
+  bool ProcessNotifyErrorTask(Task* task,
+                              ClientCallBehavior client_call_behavior,
+                              base::SequencedTaskRunner* current_task_runner);
+  bool ProcessIncomingMessage(Message* message,
+                              ClientCallBehavior client_call_behavior,
+                              base::SequencedTaskRunner* current_task_runner);
 
-  void MaybePostToProcessTasks(base::SingleThreadTaskRunner* task_runner);
+  void MaybePostToProcessTasks(base::SequencedTaskRunner* task_runner);
   void LockAndCallProcessTasks();
 
   // Updates the state of |endpoint|. If both the endpoint and its peer have
@@ -232,7 +236,7 @@
   // comments of kInterfaceIdNamespaceMask.
   const bool set_interface_id_namespace_bit_;
 
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   // Owned by |filters_| below.
   MessageHeaderValidator* header_validator_;
@@ -240,7 +244,7 @@
   FilterChain filters_;
   Connector connector_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // Protects the following members.
   // Not set in Config::SINGLE_INTERFACE* mode.
@@ -258,7 +262,7 @@
   std::map<InterfaceId, deque<Task*>> sync_message_tasks_;
 
   bool posted_to_process_tasks_;
-  scoped_refptr<base::SingleThreadTaskRunner> posted_to_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> posted_to_task_runner_;
 
   bool encountered_error_;
 
diff --git a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
index c134507..2f33cb2 100644
--- a/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
+++ b/mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
 #include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
 
@@ -103,7 +104,7 @@
       return;
     }
 
-    runner_ = base::ThreadTaskRunnerHandle::Get();
+    runner_ = base::SequencedTaskRunnerHandle::Get();
     if (!pending_association_) {
       runner_->PostTask(
           FROM_HERE,
@@ -191,7 +192,7 @@
       group_controller_ = std::move(group_controller);
 
       if (!association_event_handler_.is_null()) {
-        if (runner_->BelongsToCurrentThread()) {
+        if (runner_->RunsTasksOnCurrentThread()) {
           handler = std::move(association_event_handler_);
           runner_ = nullptr;
         } else {
@@ -227,7 +228,7 @@
       peer_state_ = nullptr;
 
       if (!association_event_handler_.is_null()) {
-        if (runner_->BelongsToCurrentThread()) {
+        if (runner_->RunsTasksOnCurrentThread()) {
           handler = std::move(association_event_handler_);
           runner_ = nullptr;
         } else {
@@ -245,7 +246,7 @@
   }
 
   void RunAssociationEventHandler(
-      scoped_refptr<base::SingleThreadTaskRunner> posted_to_runner,
+      scoped_refptr<base::SequencedTaskRunner> posted_to_runner,
       AssociationEvent event) {
     AssociationEventCallback handler;
 
@@ -271,7 +272,7 @@
   scoped_refptr<State> peer_state_;
 
   AssociationEventCallback association_event_handler_;
-  scoped_refptr<base::SingleThreadTaskRunner> runner_;
+  scoped_refptr<base::SequencedTaskRunner> runner_;
 
   InterfaceId id_ = kInvalidInterfaceId;
   scoped_refptr<AssociatedGroupController> group_controller_;
diff --git a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc b/mojo/public/cpp/bindings/lib/sync_event_watcher.cc
index b1c97e36..e64e604 100644
--- a/mojo/public/cpp/bindings/lib/sync_event_watcher.cc
+++ b/mojo/public/cpp/bindings/lib/sync_event_watcher.cc
@@ -16,19 +16,19 @@
       destroyed_(new base::RefCountedData<bool>(false)) {}
 
 SyncEventWatcher::~SyncEventWatcher() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (registered_)
     registry_->UnregisterEvent(event_);
   destroyed_->data = true;
 }
 
 void SyncEventWatcher::AllowWokenUpBySyncWatchOnSameThread() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   IncrementRegisterCount();
 }
 
 bool SyncEventWatcher::SyncWatch(const bool* should_stop) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   IncrementRegisterCount();
   if (!registered_) {
     DecrementRegisterCount();
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
index fd3df39..8ac451c7 100644
--- a/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
+++ b/mojo/public/cpp/bindings/lib/sync_handle_registry.cc
@@ -7,24 +7,31 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "base/threading/thread_local.h"
+#include "base/threading/sequence_local_storage_slot.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/c/system/core.h"
 
 namespace mojo {
 namespace {
 
-base::LazyInstance<base::ThreadLocalPointer<SyncHandleRegistry>>::Leaky
+base::LazyInstance<
+    base::SequenceLocalStorageSlot<scoped_refptr<SyncHandleRegistry>>>::Leaky
     g_current_sync_handle_watcher = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
 // static
 scoped_refptr<SyncHandleRegistry> SyncHandleRegistry::current() {
-  scoped_refptr<SyncHandleRegistry> result(
-      g_current_sync_handle_watcher.Pointer()->Get());
+  // SyncMessageFilter can be used on threads without sequence-local storage
+  // being available. Those receive a unique, standalone SyncHandleRegistry.
+  if (!base::SequencedTaskRunnerHandle::IsSet())
+    return new SyncHandleRegistry();
+
+  scoped_refptr<SyncHandleRegistry> result =
+      g_current_sync_handle_watcher.Get().Get();
   if (!result) {
     result = new SyncHandleRegistry();
-    DCHECK_EQ(result.get(), g_current_sync_handle_watcher.Pointer()->Get());
+    g_current_sync_handle_watcher.Get().Set(result);
   }
   return result;
 }
@@ -32,7 +39,7 @@
 bool SyncHandleRegistry::RegisterHandle(const Handle& handle,
                                         MojoHandleSignals handle_signals,
                                         const HandleCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (base::ContainsKey(handles_, handle))
     return false;
@@ -46,7 +53,7 @@
 }
 
 void SyncHandleRegistry::UnregisterHandle(const Handle& handle) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!base::ContainsKey(handles_, handle))
     return;
 
@@ -75,7 +82,7 @@
 }
 
 bool SyncHandleRegistry::Wait(const bool* should_stop[], size_t count) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   size_t num_ready_handles;
   Handle ready_handle;
@@ -109,27 +116,8 @@
   return false;
 }
 
-SyncHandleRegistry::SyncHandleRegistry() {
-  DCHECK(!g_current_sync_handle_watcher.Pointer()->Get());
-  g_current_sync_handle_watcher.Pointer()->Set(this);
-}
+SyncHandleRegistry::SyncHandleRegistry() = default;
 
-SyncHandleRegistry::~SyncHandleRegistry() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  // This object may be destructed after the thread local storage slot used by
-  // |g_current_sync_handle_watcher| is reset during thread shutdown.
-  // For example, another slot in the thread local storage holds a referrence to
-  // this object, and that slot is cleaned up after
-  // |g_current_sync_handle_watcher|.
-  if (!g_current_sync_handle_watcher.Pointer()->Get())
-    return;
-
-  // If this breaks, it is likely that the global variable is bulit into and
-  // accessed from multiple modules.
-  DCHECK_EQ(this, g_current_sync_handle_watcher.Pointer()->Get());
-
-  g_current_sync_handle_watcher.Pointer()->Set(nullptr);
-}
+SyncHandleRegistry::~SyncHandleRegistry() = default;
 
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc
index f20af56..294b8a1 100644
--- a/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc
+++ b/mojo/public/cpp/bindings/lib/sync_handle_watcher.cc
@@ -21,7 +21,7 @@
       destroyed_(new base::RefCountedData<bool>(false)) {}
 
 SyncHandleWatcher::~SyncHandleWatcher() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (registered_)
     registry_->UnregisterHandle(handle_);
 
@@ -29,12 +29,12 @@
 }
 
 void SyncHandleWatcher::AllowWokenUpBySyncWatchOnSameThread() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   IncrementRegisterCount();
 }
 
 bool SyncHandleWatcher::SyncWatch(const bool* should_stop) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   IncrementRegisterCount();
   if (!registered_) {
     DecrementRegisterCount();
diff --git a/mojo/public/cpp/bindings/sync_event_watcher.h b/mojo/public/cpp/bindings/sync_event_watcher.h
index 6e25484..1f1d265a 100644
--- a/mojo/public/cpp/bindings/sync_event_watcher.h
+++ b/mojo/public/cpp/bindings/sync_event_watcher.h
@@ -10,8 +10,8 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/sync_handle_registry.h"
 
@@ -58,7 +58,7 @@
 
   scoped_refptr<base::RefCountedData<bool>> destroyed_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(SyncEventWatcher);
 };
diff --git a/mojo/public/cpp/bindings/sync_handle_registry.h b/mojo/public/cpp/bindings/sync_handle_registry.h
index afb3b56b..de766151 100644
--- a/mojo/public/cpp/bindings/sync_handle_registry.h
+++ b/mojo/public/cpp/bindings/sync_handle_registry.h
@@ -11,22 +11,22 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/system/core.h"
 #include "mojo/public/cpp/system/wait_set.h"
 
 namespace mojo {
 
-// SyncHandleRegistry is a thread-local storage to register handles that want to
-// be watched together.
+// SyncHandleRegistry is a sequence-local storage to register handles that want
+// to be watched together.
 //
-// This class is not thread safe.
+// This class is thread unsafe.
 class MOJO_CPP_BINDINGS_EXPORT SyncHandleRegistry
     : public base::RefCounted<SyncHandleRegistry> {
  public:
-  // Returns a thread-local object.
+  // Returns a sequence-local object.
   static scoped_refptr<SyncHandleRegistry> current();
 
   using HandleCallback = base::Callback<void(MojoResult)>;
@@ -61,7 +61,7 @@
   std::map<Handle, HandleCallback> handles_;
   std::map<base::WaitableEvent*, base::Closure> events_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(SyncHandleRegistry);
 };
diff --git a/mojo/public/cpp/bindings/sync_handle_watcher.h b/mojo/public/cpp/bindings/sync_handle_watcher.h
index eff73dd..18df10c 100644
--- a/mojo/public/cpp/bindings/sync_handle_watcher.h
+++ b/mojo/public/cpp/bindings/sync_handle_watcher.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/sync_handle_registry.h"
 #include "mojo/public/cpp/system/core.h"
@@ -65,7 +65,7 @@
 
   scoped_refptr<base::RefCountedData<bool>> destroyed_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(SyncHandleWatcher);
 };
diff --git a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
index 67106bd..adb45ed 100644
--- a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
@@ -11,10 +11,11 @@
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -95,7 +96,8 @@
 
 class AssociatedInterfaceTest : public testing::Test {
  public:
-  AssociatedInterfaceTest() {}
+  AssociatedInterfaceTest()
+      : main_runner_(base::ThreadTaskRunnerHandle::Get()) {}
   ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); }
 
   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
@@ -117,10 +119,10 @@
     MessagePipe pipe;
     *router0 = new MultiplexRouter(std::move(pipe.handle0),
                                    MultiplexRouter::MULTI_INTERFACE, true,
-                                   base::ThreadTaskRunnerHandle::Get());
+                                   main_runner_);
     *router1 = new MultiplexRouter(std::move(pipe.handle1),
                                    MultiplexRouter::MULTI_INTERFACE, false,
-                                   base::ThreadTaskRunnerHandle::Get());
+                                   main_runner_);
   }
 
   void CreateIntegerSenderWithExistingRouters(
@@ -143,10 +145,10 @@
 
   // Okay to call from any thread.
   void QuitRunLoop(base::RunLoop* run_loop) {
-    if (loop_.task_runner()->BelongsToCurrentThread()) {
+    if (main_runner_->RunsTasksOnCurrentThread()) {
       run_loop->Quit();
     } else {
-      loop_.task_runner()->PostTask(
+      main_runner_->PostTask(
           FROM_HERE,
           base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                      base::Unretained(this), base::Unretained(run_loop)));
@@ -154,7 +156,8 @@
   }
 
  private:
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment task_environment;
+  scoped_refptr<base::SequencedTaskRunner> main_runner_;
 };
 
 void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
@@ -244,17 +247,15 @@
 class TestSender {
  public:
   TestSender()
-      : sender_thread_("TestSender"),
+      : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
         next_sender_(nullptr),
-        max_value_to_send_(-1) {
-    sender_thread_.Start();
-  }
+        max_value_to_send_(-1) {}
 
   // The following three methods are called on the corresponding sender thread.
   void SetUp(IntegerSenderAssociatedPtrInfo ptr_info,
              TestSender* next_sender,
              int32_t max_value_to_send) {
-    CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
 
     ptr_.Bind(std::move(ptr_info));
     next_sender_ = next_sender ? next_sender : this;
@@ -262,28 +263,28 @@
   }
 
   void Send(int32_t value) {
-    CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
 
     if (value > max_value_to_send_)
       return;
 
     ptr_->Send(value);
 
-    next_sender_->sender_thread()->task_runner()->PostTask(
+    next_sender_->task_runner()->PostTask(
         FROM_HERE,
         base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value));
   }
 
   void TearDown() {
-    CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
 
     ptr_.reset();
   }
 
-  base::Thread* sender_thread() { return &sender_thread_; }
+  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
 
  private:
-  base::Thread sender_thread_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   TestSender* next_sender_;
   int32_t max_value_to_send_;
 
@@ -292,15 +293,15 @@
 
 class TestReceiver {
  public:
-  TestReceiver() : receiver_thread_("TestReceiver"), expected_calls_(0) {
-    receiver_thread_.Start();
-  }
+  TestReceiver()
+      : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
+        expected_calls_(0) {}
 
   void SetUp(AssociatedInterfaceRequest<IntegerSender> request0,
              AssociatedInterfaceRequest<IntegerSender> request1,
              size_t expected_calls,
              const base::Closure& notify_finish) {
-    CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
 
     impl0_.reset(new IntegerSenderImpl(std::move(request0)));
     impl0_->set_notify_send_method_called(
@@ -314,13 +315,13 @@
   }
 
   void TearDown() {
-    CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
 
     impl0_.reset();
     impl1_.reset();
   }
 
-  base::Thread* receiver_thread() { return &receiver_thread_; }
+  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
   const std::vector<int32_t>& values() const { return values_; }
 
  private:
@@ -331,7 +332,7 @@
       notify_finish_.Run();
   }
 
-  base::Thread receiver_thread_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   size_t expected_calls_;
 
   std::unique_ptr<IntegerSenderImpl> impl0_;
@@ -392,7 +393,7 @@
 
   TestSender senders[4];
   for (size_t i = 0; i < 4; ++i) {
-    senders[i].sender_thread()->task_runner()->PostTask(
+    senders[i].task_runner()->PostTask(
         FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
                               base::Passed(&ptr_infos[i]), nullptr,
                               kMaxValue * (i + 1) / 4));
@@ -404,7 +405,7 @@
       2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                     base::Unretained(this), base::Unretained(&run_loop)));
   for (size_t i = 0; i < 2; ++i) {
-    receivers[i].receiver_thread()->task_runner()->PostTask(
+    receivers[i].task_runner()->PostTask(
         FROM_HERE,
         base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
                    base::Passed(&requests[2 * i]),
@@ -415,7 +416,7 @@
   }
 
   for (size_t i = 0; i < 4; ++i) {
-    senders[i].sender_thread()->task_runner()->PostTask(
+    senders[i].task_runner()->PostTask(
         FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]),
                               kMaxValue * i / 4 + 1));
   }
@@ -424,7 +425,7 @@
 
   for (size_t i = 0; i < 4; ++i) {
     base::RunLoop run_loop;
-    senders[i].sender_thread()->task_runner()->PostTaskAndReply(
+    senders[i].task_runner()->PostTaskAndReply(
         FROM_HERE,
         base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
@@ -434,7 +435,7 @@
 
   for (size_t i = 0; i < 2; ++i) {
     base::RunLoop run_loop;
-    receivers[i].receiver_thread()->task_runner()->PostTaskAndReply(
+    receivers[i].task_runner()->PostTaskAndReply(
         FROM_HERE,
         base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
@@ -477,7 +478,7 @@
 
   TestSender senders[4];
   for (size_t i = 0; i < 4; ++i) {
-    senders[i].sender_thread()->task_runner()->PostTask(
+    senders[i].task_runner()->PostTask(
         FROM_HERE,
         base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
                    base::Passed(&ptr_infos[i]),
@@ -490,7 +491,7 @@
       2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
                     base::Unretained(this), base::Unretained(&run_loop)));
   for (size_t i = 0; i < 2; ++i) {
-    receivers[i].receiver_thread()->task_runner()->PostTask(
+    receivers[i].task_runner()->PostTask(
         FROM_HERE,
         base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
                    base::Passed(&requests[2 * i]),
@@ -500,7 +501,7 @@
                               base::Unretained(&counter))));
   }
 
-  senders[0].sender_thread()->task_runner()->PostTask(
+  senders[0].task_runner()->PostTask(
       FROM_HERE,
       base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1));
 
@@ -508,7 +509,7 @@
 
   for (size_t i = 0; i < 4; ++i) {
     base::RunLoop run_loop;
-    senders[i].sender_thread()->task_runner()->PostTaskAndReply(
+    senders[i].task_runner()->PostTaskAndReply(
         FROM_HERE,
         base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
@@ -518,7 +519,7 @@
 
   for (size_t i = 0; i < 2; ++i) {
     base::RunLoop run_loop;
-    receivers[i].receiver_thread()->task_runner()->PostTaskAndReply(
+    receivers[i].task_runner()->PostTaskAndReply(
         FROM_HERE,
         base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
@@ -1060,8 +1061,6 @@
 
   // Test the thread safe pointer can be used from another thread.
   base::RunLoop run_loop;
-  base::Thread other_thread("service test thread");
-  other_thread.Start();
 
   auto run_method = base::Bind(
       [](const scoped_refptr<base::TaskRunner>& main_task_runner,
@@ -1085,7 +1084,8 @@
       },
       base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
       thread_safe_sender);
-  other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method);
+  base::CreateSequencedTaskRunnerWithTraits({})->PostTask(FROM_HERE,
+                                                          run_method);
 
   // Block until the method callback is called on the background thread.
   run_loop.Run();
@@ -1099,11 +1099,8 @@
 
 TEST_F(AssociatedInterfaceTest,
        ThreadSafeAssociatedInterfacePtrWithTaskRunner) {
-  // Start the thread from where we'll bind the interface pointer.
-  base::Thread other_thread("service test thread");
-  other_thread.Start();
-  const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner =
-      other_thread.message_loop()->task_runner();
+  const scoped_refptr<base::SequencedTaskRunner> other_thread_task_runner =
+      base::CreateSequencedTaskRunnerWithTraits({});
 
   ForwarderTestContext* context = new ForwarderTestContext();
   IntegerSenderAssociatedPtrInfo sender_info;
diff --git a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
index 68c7bd9..11a1ee7 100644
--- a/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc
@@ -8,11 +8,14 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
@@ -201,7 +204,7 @@
   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
 
  private:
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment task_environment;
 };
 
 void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
@@ -227,44 +230,52 @@
   EXPECT_TRUE(calc.is_bound());
 }
 
-TEST_F(InterfacePtrTest, EndToEnd) {
-  math::CalculatorPtr calc;
-  MathCalculatorImpl calc_impl(MakeRequest(&calc));
+class EndToEndInterfacePtrTest : public InterfacePtrTest {
+ public:
+  void RunTest(const scoped_refptr<base::SequencedTaskRunner> runner) {
+    base::RunLoop run_loop;
+    done_closure_ = run_loop.QuitClosure();
+    done_runner_ = base::ThreadTaskRunnerHandle::Get();
+    runner->PostTask(FROM_HERE,
+                     base::Bind(&EndToEndInterfacePtrTest::RunTestImpl,
+                                base::Unretained(this)));
+    run_loop.Run();
+  }
 
-  // Suppose this is instantiated in a process that has pipe1_.
-  MathCalculatorUI calculator_ui(std::move(calc));
+ private:
+  void RunTestImpl() {
+    math::CalculatorPtr calc;
+    calc_impl_ = base::MakeUnique<MathCalculatorImpl>(MakeRequest(&calc));
+    calculator_ui_ = base::MakeUnique<MathCalculatorUI>(std::move(calc));
+    calculator_ui_->Add(2.0, base::Bind(&EndToEndInterfacePtrTest::AddDone,
+                                        base::Unretained(this)));
+    calculator_ui_->Multiply(5.0,
+                             base::Bind(&EndToEndInterfacePtrTest::MultiplyDone,
+                                        base::Unretained(this)));
+    EXPECT_EQ(0.0, calculator_ui_->GetOutput());
+  }
 
-  base::RunLoop run_loop, run_loop2;
-  calculator_ui.Add(2.0, run_loop.QuitClosure());
-  calculator_ui.Multiply(5.0, run_loop2.QuitClosure());
-  run_loop.Run();
-  run_loop2.Run();
+  void AddDone() { EXPECT_EQ(2.0, calculator_ui_->GetOutput()); }
 
-  EXPECT_EQ(10.0, calculator_ui.GetOutput());
+  void MultiplyDone() {
+    EXPECT_EQ(10.0, calculator_ui_->GetOutput());
+    calculator_ui_.reset();
+    calc_impl_.reset();
+    done_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&done_closure_));
+  }
+
+  base::Closure done_closure_;
+  scoped_refptr<base::SingleThreadTaskRunner> done_runner_;
+  std::unique_ptr<MathCalculatorUI> calculator_ui_;
+  std::unique_ptr<MathCalculatorImpl> calc_impl_;
+};
+
+TEST_F(EndToEndInterfacePtrTest, EndToEnd) {
+  RunTest(base::ThreadTaskRunnerHandle::Get());
 }
 
-TEST_F(InterfacePtrTest, EndToEnd_Synchronous) {
-  math::CalculatorPtr calc;
-  MathCalculatorImpl calc_impl(MakeRequest(&calc));
-
-  // Suppose this is instantiated in a process that has pipe1_.
-  MathCalculatorUI calculator_ui(std::move(calc));
-
-  EXPECT_EQ(0.0, calculator_ui.GetOutput());
-
-  base::RunLoop run_loop;
-  calculator_ui.Add(2.0, run_loop.QuitClosure());
-  EXPECT_EQ(0.0, calculator_ui.GetOutput());
-  calc_impl.binding()->WaitForIncomingMethodCall();
-  run_loop.Run();
-  EXPECT_EQ(2.0, calculator_ui.GetOutput());
-
-  base::RunLoop run_loop2;
-  calculator_ui.Multiply(5.0, run_loop2.QuitClosure());
-  EXPECT_EQ(2.0, calculator_ui.GetOutput());
-  calc_impl.binding()->WaitForIncomingMethodCall();
-  run_loop2.Run();
-  EXPECT_EQ(10.0, calculator_ui.GetOutput());
+TEST_F(EndToEndInterfacePtrTest, EndToEndOnSequence) {
+  RunTest(base::CreateSequencedTaskRunnerWithTraits({}));
 }
 
 TEST_F(InterfacePtrTest, Movable) {
@@ -843,10 +854,6 @@
 
   base::RunLoop run_loop;
 
-  // Create and start the thread from where we'll call the interface pointer.
-  base::Thread other_thread("service test thread");
-  other_thread.Start();
-
   auto run_method = base::Bind(
       [](const scoped_refptr<base::TaskRunner>& main_task_runner,
          const base::Closure& quit_closure,
@@ -868,18 +875,16 @@
       },
       base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
       thread_safe_ptr);
-  other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method);
+  base::CreateSequencedTaskRunnerWithTraits({})->PostTask(FROM_HERE,
+                                                          run_method);
 
   // Block until the method callback is called on the background thread.
   run_loop.Run();
 }
 
 TEST_F(InterfacePtrTest, ThreadSafeInterfacePointerWithTaskRunner) {
-  // Create and start the thread from where we'll bind the interface pointer.
-  base::Thread other_thread("service test thread");
-  other_thread.Start();
-  const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner =
-      other_thread.message_loop()->task_runner();
+  const scoped_refptr<base::SequencedTaskRunner> other_thread_task_runner =
+      base::CreateSequencedTaskRunnerWithTraits({});
 
   math::CalculatorPtr ptr;
   auto request = mojo::MakeRequest(&ptr);
@@ -906,7 +911,7 @@
         },
         base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
         thread_safe_ptr, base::Passed(&request), &math_calc_impl);
-    other_thread.message_loop()->task_runner()->PostTask(FROM_HERE, run_method);
+    other_thread_task_runner->PostTask(FROM_HERE, run_method);
     run_loop.Run();
   }
 
diff --git a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
index 8950928..cd8c221 100644
--- a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
@@ -43,7 +43,12 @@
     endpoint1_ = router1_->CreateLocalEndpointHandle(id);
   }
 
-  void TearDown() override {}
+  void TearDown() override {
+    endpoint1_.reset();
+    endpoint0_.reset();
+    router1_ = nullptr;
+    router0_ = nullptr;
+  }
 
   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
 
diff --git a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc b/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
index 1bf3f7a..3235770 100644
--- a/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/report_bad_message_unittest.cc
@@ -88,10 +88,10 @@
       error_handler_.Run();
   }
 
+  base::MessageLoop message_loop;
   TestBadMessagesPtr proxy_;
   TestBadMessagesImpl impl_;
   base::Closure error_handler_;
-  base::MessageLoop message_loop;
 };
 
 TEST_F(ReportBadMessageTest, Request) {
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
index c140356..6a5d704 100644
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
@@ -7,8 +7,10 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/sequence_token.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -238,8 +240,9 @@
   DISALLOW_COPY_AND_ASSIGN(PtrWrapper);
 };
 
-// The type parameter for SyncMethodCommonTests for varying the Interface and
-// whether to use InterfacePtr or ThreadSafeInterfacePtr.
+// The type parameter for SyncMethodCommonTests and
+// SyncMethodOnSequenceCommonTests for varying the Interface and whether to use
+// InterfacePtr or ThreadSafeInterfacePtr.
 template <typename InterfaceT, bool use_thread_safe_ptr>
 struct TestParams {
   using Interface = InterfaceT;
@@ -256,15 +259,14 @@
 };
 
 template <typename Interface>
-class TestSyncServiceThread {
+class TestSyncServiceSequence {
  public:
-  TestSyncServiceThread()
-      : thread_("TestSyncServiceThread"), ping_called_(false) {
-    thread_.Start();
-  }
+  TestSyncServiceSequence()
+      : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
+        ping_called_(false) {}
 
   void SetUp(InterfaceRequest<Interface> request) {
-    CHECK(thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
     impl_.reset(new ImplTypeFor<Interface>(std::move(request)));
     impl_->set_ping_handler(
         [this](const typename Interface::PingCallback& callback) {
@@ -277,25 +279,25 @@
   }
 
   void TearDown() {
-    CHECK(thread_.task_runner()->BelongsToCurrentThread());
+    CHECK(task_runner()->RunsTasksOnCurrentThread());
     impl_.reset();
   }
 
-  base::Thread* thread() { return &thread_; }
+  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
   bool ping_called() const {
     base::AutoLock locker(lock_);
     return ping_called_;
   }
 
  private:
-  base::Thread thread_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   std::unique_ptr<ImplTypeFor<Interface>> impl_;
 
   mutable base::Lock lock_;
   bool ping_called_;
 
-  DISALLOW_COPY_AND_ASSIGN(TestSyncServiceThread);
+  DISALLOW_COPY_AND_ASSIGN(TestSyncServiceSequence);
 };
 
 class SyncMethodTest : public testing::Test {
@@ -304,7 +306,7 @@
   ~SyncMethodTest() override { base::RunLoop().RunUntilIdle(); }
 
  protected:
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment task_environment;
 };
 
 template <typename T>
@@ -386,6 +388,82 @@
   return base::Bind(&CallAsyncEchoCallback<Func>, func);
 }
 
+class SequencedTaskRunnerTestBase;
+
+void RunTestOnSequencedTaskRunner(
+    std::unique_ptr<SequencedTaskRunnerTestBase> test);
+
+class SequencedTaskRunnerTestBase {
+ public:
+  virtual ~SequencedTaskRunnerTestBase() = default;
+
+  void RunTest() {
+    SetUp();
+    Run();
+  }
+
+  virtual void Run() = 0;
+
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ protected:
+  void Done() {
+    TearDown();
+    task_runner_->PostTask(FROM_HERE, quit_closure_);
+    delete this;
+  }
+
+  base::Closure DoneClosure() {
+    return base::Bind(&SequencedTaskRunnerTestBase::Done,
+                      base::Unretained(this));
+  }
+
+ private:
+  friend void RunTestOnSequencedTaskRunner(
+      std::unique_ptr<SequencedTaskRunnerTestBase> test);
+
+  void Init(const base::Closure& quit_closure) {
+    task_runner_ = base::SequencedTaskRunnerHandle::Get();
+    quit_closure_ = quit_closure;
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  base::Closure quit_closure_;
+};
+
+// A helper class to launch tests on a SequencedTaskRunner. This is necessary
+// so gtest can instantiate copies for each |TypeParam|.
+template <typename TypeParam>
+class SequencedTaskRunnerTestLauncher : public testing::Test {
+  base::test::ScopedTaskEnvironment task_environment;
+};
+
+// Similar to SyncMethodCommonTest, but the test body runs on a
+// SequencedTaskRunner.
+template <typename TypeParam>
+class SyncMethodOnSequenceCommonTest : public SequencedTaskRunnerTestBase {
+ public:
+  void SetUp() override {
+    impl_ = base::MakeUnique<ImplTypeFor<typename TypeParam::Interface>>(
+        MakeRequest(&ptr_));
+  }
+
+ protected:
+  InterfacePtr<typename TypeParam::Interface> ptr_;
+  std::unique_ptr<ImplTypeFor<typename TypeParam::Interface>> impl_;
+};
+
+void RunTestOnSequencedTaskRunner(
+    std::unique_ptr<SequencedTaskRunnerTestBase> test) {
+  base::RunLoop run_loop;
+  test->Init(run_loop.QuitClosure());
+  base::CreateSequencedTaskRunnerWithTraits({base::WithBaseSyncPrimitives()})
+      ->PostTask(FROM_HERE, base::Bind(&SequencedTaskRunnerTestBase::RunTest,
+                                       base::Unretained(test.release())));
+  run_loop.Run();
+}
+
 // TestSync (without associated interfaces) and TestSyncMaster (with associated
 // interfaces) exercise MultiplexRouter with different configurations.
 // Each test is run once with an InterfacePtr and once with a
@@ -396,6 +474,7 @@
                                       TestParams<TestSyncMaster, true>,
                                       TestParams<TestSyncMaster, false>>;
 TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes);
+TYPED_TEST_CASE(SequencedTaskRunnerTestLauncher, InterfaceTypes);
 
 TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) {
   using Interface = typename TypeParam::Interface;
@@ -409,29 +488,65 @@
   run_loop.Run();
 }
 
+#define SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name) \
+  fixture_name##name##_SequencedTaskRunnerTestSuffix
+
+#define SEQUENCED_TASK_RUNNER_TYPED_TEST(fixture_name, name)        \
+  template <typename TypeParam>                                     \
+  class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name)   \
+      : public fixture_name<TypeParam> {                            \
+    void Run() override;                                            \
+  };                                                                \
+  TYPED_TEST(SequencedTaskRunnerTestLauncher, name) {               \
+    RunTestOnSequencedTaskRunner(                                   \
+        base::MakeUnique<SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(     \
+                             fixture_name, name) < TypeParam>> ()); \
+  }                                                                 \
+  template <typename TypeParam>                                     \
+  void SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name,          \
+                                             name)<TypeParam>::Run()
+
+#define SEQUENCED_TASK_RUNNER_TYPED_TEST_F(fixture_name, name)      \
+  template <typename TypeParam>                                     \
+  class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name);  \
+  TYPED_TEST(SequencedTaskRunnerTestLauncher, name) {               \
+    RunTestOnSequencedTaskRunner(                                   \
+        base::MakeUnique<SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(     \
+                             fixture_name, name) < TypeParam>> ()); \
+  }                                                                 \
+  template <typename TypeParam>                                     \
+  class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name)   \
+      : public fixture_name<TypeParam>
+
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 CallSyncMethodAsynchronously) {
+  this->ptr_->Echo(
+      123, base::Bind(&ExpectValueAndRunClosure, 123, this->DoneClosure()));
+}
+
 TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) {
   using Interface = typename TypeParam::Interface;
   InterfacePtr<Interface> interface_ptr;
   InterfaceRequest<Interface> request = MakeRequest(&interface_ptr);
   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
 
-  TestSyncServiceThread<Interface> service_thread;
-  service_thread.thread()->task_runner()->PostTask(
+  TestSyncServiceSequence<Interface> service_sequence;
+  service_sequence.task_runner()->PostTask(
       FROM_HERE,
-      base::Bind(&TestSyncServiceThread<Interface>::SetUp,
-                 base::Unretained(&service_thread), base::Passed(&request)));
+      base::Bind(&TestSyncServiceSequence<Interface>::SetUp,
+                 base::Unretained(&service_sequence), base::Passed(&request)));
   ASSERT_TRUE(ptr->Ping());
-  ASSERT_TRUE(service_thread.ping_called());
+  ASSERT_TRUE(service_sequence.ping_called());
 
   int32_t output_value = -1;
   ASSERT_TRUE(ptr->Echo(42, &output_value));
   ASSERT_EQ(42, output_value);
 
   base::RunLoop run_loop;
-  service_thread.thread()->task_runner()->PostTaskAndReply(
+  service_sequence.task_runner()->PostTaskAndReply(
       FROM_HERE,
-      base::Bind(&TestSyncServiceThread<Interface>::TearDown,
-                 base::Unretained(&service_thread)),
+      base::Bind(&TestSyncServiceSequence<Interface>::TearDown,
+                 base::Unretained(&service_sequence)),
       run_loop.QuitClosure());
   run_loop.Run();
 }
@@ -450,6 +565,17 @@
   EXPECT_EQ(42, output_value);
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 ReenteredBySyncMethodBinding) {
+  // Test that an interface pointer waiting for a sync call response can be
+  // reentered by a binding serving sync methods on the same thread.
+
+  int32_t output_value = -1;
+  ASSERT_TRUE(this->ptr_->Echo(42, &output_value));
+  EXPECT_EQ(42, output_value);
+  this->Done();
+}
+
 TYPED_TEST(SyncMethodCommonTest, InterfacePtrDestroyedDuringSyncCall) {
   // Test that it won't result in crash or hang if an interface pointer is
   // destroyed while it is waiting for a sync call response.
@@ -465,6 +591,20 @@
   ASSERT_FALSE(ptr->Ping());
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 InterfacePtrDestroyedDuringSyncCall) {
+  // Test that it won't result in crash or hang if an interface pointer is
+  // destroyed while it is waiting for a sync call response.
+
+  auto* ptr = &this->ptr_;
+  this->impl_->set_ping_handler([ptr](const TestSync::PingCallback& callback) {
+    ptr->reset();
+    callback.Run();
+  });
+  ASSERT_FALSE(this->ptr_->Ping());
+  this->Done();
+}
+
 TYPED_TEST(SyncMethodCommonTest, BindingDestroyedDuringSyncCall) {
   // Test that it won't result in crash or hang if a binding is
   // closed (and therefore the message pipe handle is closed) while the
@@ -481,6 +621,22 @@
   ASSERT_FALSE(ptr->Ping());
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 BindingDestroyedDuringSyncCall) {
+  // Test that it won't result in crash or hang if a binding is
+  // closed (and therefore the message pipe handle is closed) while the
+  // corresponding interface pointer is waiting for a sync call response.
+
+  auto& impl = *this->impl_;
+  this->impl_->set_ping_handler(
+      [&impl](const TestSync::PingCallback& callback) {
+        impl.binding()->Close();
+        callback.Run();
+      });
+  ASSERT_FALSE(this->ptr_->Ping());
+  this->Done();
+}
+
 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithInOrderResponses) {
   // Test that we can call a sync method on an interface ptr, while there is
   // already a sync call ongoing. The responses arrive in order.
@@ -509,6 +665,34 @@
   EXPECT_EQ(123, result_value);
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 NestedSyncCallsWithInOrderResponses) {
+  // Test that we can call a sync method on an interface ptr, while there is
+  // already a sync call ongoing. The responses arrive in order.
+
+  // The same variable is used to store the output of the two sync calls, in
+  // order to test that responses are handled in the correct order.
+  int32_t result_value = -1;
+
+  bool first_call = true;
+  auto& ptr = this->ptr_;
+  auto& impl = *this->impl_;
+  impl.set_echo_handler(
+      [&first_call, &ptr, &result_value](
+          int32_t value, const TestSync::EchoCallback& callback) {
+        if (first_call) {
+          first_call = false;
+          ASSERT_TRUE(ptr->Echo(456, &result_value));
+          EXPECT_EQ(456, result_value);
+        }
+        callback.Run(value);
+      });
+
+  ASSERT_TRUE(ptr->Echo(123, &result_value));
+  EXPECT_EQ(123, result_value);
+  this->Done();
+}
+
 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithOutOfOrderResponses) {
   // Test that we can call a sync method on an interface ptr, while there is
   // already a sync call ongoing. The responses arrive out of order.
@@ -537,6 +721,34 @@
   EXPECT_EQ(123, result_value);
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
+                                 NestedSyncCallsWithOutOfOrderResponses) {
+  // Test that we can call a sync method on an interface ptr, while there is
+  // already a sync call ongoing. The responses arrive out of order.
+
+  // The same variable is used to store the output of the two sync calls, in
+  // order to test that responses are handled in the correct order.
+  int32_t result_value = -1;
+
+  bool first_call = true;
+  auto& ptr = this->ptr_;
+  auto& impl = *this->impl_;
+  impl.set_echo_handler(
+      [&first_call, &ptr, &result_value](
+          int32_t value, const TestSync::EchoCallback& callback) {
+        callback.Run(value);
+        if (first_call) {
+          first_call = false;
+          ASSERT_TRUE(ptr->Echo(456, &result_value));
+          EXPECT_EQ(456, result_value);
+        }
+      });
+
+  ASSERT_TRUE(ptr->Echo(123, &result_value));
+  EXPECT_EQ(123, result_value);
+  this->Done();
+}
+
 TYPED_TEST(SyncMethodCommonTest, AsyncResponseQueuedDuringSyncCall) {
   // Test that while an interface pointer is waiting for the response to a sync
   // call, async responses are queued until the sync call completes.
@@ -594,6 +806,52 @@
   EXPECT_TRUE(async_echo_response_dispatched);
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
+                                   AsyncResponseQueuedDuringSyncCall) {
+  // Test that while an interface pointer is waiting for the response to a sync
+  // call, async responses are queued until the sync call completes.
+
+  void Run() override {
+    this->impl_->set_async_echo_handler(
+        [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
+          async_echo_request_value_ = value;
+          async_echo_request_callback_ = callback;
+          OnAsyncEchoReceived();
+        });
+
+    this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
+                            async_echo_response_dispatched_ = true;
+                            EXPECT_EQ(123, result);
+                            EXPECT_TRUE(async_echo_response_dispatched_);
+                            this->Done();
+                          }));
+  }
+
+  // Called when the AsyncEcho request reaches the service side.
+  void OnAsyncEchoReceived() {
+    this->impl_->set_echo_handler(
+        [this](int32_t value, const TestSync::EchoCallback& callback) {
+          // Send back the async response first.
+          EXPECT_FALSE(async_echo_request_callback_.is_null());
+          async_echo_request_callback_.Run(async_echo_request_value_);
+
+          callback.Run(value);
+        });
+
+    int32_t result_value = -1;
+    ASSERT_TRUE(this->ptr_->Echo(456, &result_value));
+    EXPECT_EQ(456, result_value);
+
+    // Although the AsyncEcho response arrives before the Echo response, it
+    // should be queued and not yet dispatched.
+    EXPECT_FALSE(async_echo_response_dispatched_);
+  }
+
+  int32_t async_echo_request_value_ = -1;
+  TestSync::AsyncEchoCallback async_echo_request_callback_;
+  bool async_echo_response_dispatched_ = false;
+};
+
 TYPED_TEST(SyncMethodCommonTest, AsyncRequestQueuedDuringSyncCall) {
   // Test that while an interface pointer is waiting for the response to a sync
   // call, async requests for a binding running on the same thread are queued
@@ -645,6 +903,44 @@
   EXPECT_TRUE(async_echo_response_dispatched);
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
+                                   AsyncRequestQueuedDuringSyncCall) {
+  // Test that while an interface pointer is waiting for the response to a sync
+  // call, async requests for a binding running on the same thread are queued
+  // until the sync call completes.
+  void Run() override {
+    this->impl_->set_async_echo_handler(
+        [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
+          async_echo_request_dispatched_ = true;
+          callback.Run(value);
+        });
+
+    this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
+                            EXPECT_EQ(123, result);
+                            this->Done();
+                          }));
+
+    this->impl_->set_echo_handler(
+        [this](int32_t value, const TestSync::EchoCallback& callback) {
+          // Although the AsyncEcho request is sent before the Echo request, it
+          // shouldn't be dispatched yet at this point, because there is an
+          // ongoing
+          // sync call on the same thread.
+          EXPECT_FALSE(async_echo_request_dispatched_);
+          callback.Run(value);
+        });
+
+    int32_t result_value = -1;
+    ASSERT_TRUE(this->ptr_->Echo(456, &result_value));
+    EXPECT_EQ(456, result_value);
+
+    // Although the AsyncEcho request is sent before the Echo request, it
+    // shouldn't be dispatched yet.
+    EXPECT_FALSE(async_echo_request_dispatched_);
+  }
+  bool async_echo_request_dispatched_ = false;
+};
+
 TYPED_TEST(SyncMethodCommonTest,
            QueuedMessagesProcessedBeforeErrorNotification) {
   // Test that while an interface pointer is waiting for the response to a sync
@@ -675,19 +971,17 @@
   bool async_echo_response_dispatched = false;
   bool connection_error_dispatched = false;
   base::RunLoop run_loop2;
-  ptr->AsyncEcho(
-      123,
-      BindAsyncEchoCallback(
-          [&async_echo_response_dispatched, &connection_error_dispatched, &ptr,
-              &run_loop2](int32_t result) {
-            async_echo_response_dispatched = true;
-            // At this point, error notification should not be dispatched
-            // yet.
-            EXPECT_FALSE(connection_error_dispatched);
-            EXPECT_FALSE(ptr.encountered_error());
-            EXPECT_EQ(123, result);
-            run_loop2.Quit();
-          }));
+  ptr->AsyncEcho(123, BindAsyncEchoCallback([&async_echo_response_dispatched,
+                                             &connection_error_dispatched, &ptr,
+                                             &run_loop2](int32_t result) {
+                   async_echo_response_dispatched = true;
+                   // At this point, error notification should not be dispatched
+                   // yet.
+                   EXPECT_FALSE(connection_error_dispatched);
+                   EXPECT_FALSE(ptr.encountered_error());
+                   EXPECT_EQ(123, result);
+                   run_loop2.Quit();
+                 }));
   // Run until the AsyncEcho request reaches the service side.
   run_loop1.Run();
 
@@ -702,9 +996,9 @@
       });
 
   base::RunLoop run_loop3;
-  ptr.set_connection_error_handler(
-      base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched,
-                 run_loop3.QuitClosure()));
+  ptr.set_connection_error_handler(base::Bind(&SetFlagAndRunClosure,
+                                              &connection_error_dispatched,
+                                              run_loop3.QuitClosure()));
 
   int32_t result_value = -1;
   ASSERT_FALSE(ptr->Echo(456, &result_value));
@@ -728,6 +1022,74 @@
   EXPECT_TRUE(ptr.encountered_error());
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST_F(
+    SyncMethodOnSequenceCommonTest,
+    QueuedMessagesProcessedBeforeErrorNotification) {
+  // Test that while an interface pointer is waiting for the response to a sync
+  // call, async responses are queued. If the message pipe is disconnected
+  // before the queued messages are processed, the connection error
+  // notification is delayed until all the queued messages are processed.
+
+  void Run() override {
+    this->impl_->set_async_echo_handler(
+        [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
+          OnAsyncEchoReachedService(value, callback);
+        });
+
+    this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
+                            async_echo_response_dispatched_ = true;
+                            // At this point, error notification should not be
+                            // dispatched
+                            // yet.
+                            EXPECT_FALSE(connection_error_dispatched_);
+                            EXPECT_FALSE(this->ptr_.encountered_error());
+                            EXPECT_EQ(123, result);
+                            EXPECT_TRUE(async_echo_response_dispatched_);
+                          }));
+  }
+
+  void OnAsyncEchoReachedService(int32_t value,
+                                 const TestSync::AsyncEchoCallback& callback) {
+    async_echo_request_value_ = value;
+    async_echo_request_callback_ = callback;
+    this->impl_->set_echo_handler(
+        [this](int32_t value, const TestSync::EchoCallback& callback) {
+          // Send back the async response first.
+          EXPECT_FALSE(async_echo_request_callback_.is_null());
+          async_echo_request_callback_.Run(async_echo_request_value_);
+
+          this->impl_->binding()->Close();
+        });
+
+    this->ptr_.set_connection_error_handler(
+        base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched_,
+                   LambdaBinder<>::BindLambda(
+                       [this]() { OnErrorNotificationDispatched(); })));
+
+    int32_t result_value = -1;
+    ASSERT_FALSE(this->ptr_->Echo(456, &result_value));
+    EXPECT_EQ(-1, result_value);
+    ASSERT_FALSE(connection_error_dispatched_);
+    EXPECT_FALSE(this->ptr_.encountered_error());
+
+    // Although the AsyncEcho response arrives before the Echo response, it
+    // should
+    // be queued and not yet dispatched.
+    EXPECT_FALSE(async_echo_response_dispatched_);
+  }
+
+  void OnErrorNotificationDispatched() {
+    ASSERT_TRUE(connection_error_dispatched_);
+    EXPECT_TRUE(this->ptr_.encountered_error());
+    this->Done();
+  }
+
+  int32_t async_echo_request_value_ = -1;
+  TestSync::AsyncEchoCallback async_echo_request_callback_;
+  bool async_echo_response_dispatched_ = false;
+  bool connection_error_dispatched_ = false;
+};
+
 TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) {
   // Test that while an interface pointer is waiting for the response to a sync
   // call, an invalid incoming message will disconnect the message pipe, cause
@@ -776,6 +1138,50 @@
   }
 }
 
+SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
+                                   InvalidMessageDuringSyncCall) {
+  // Test that while an interface pointer is waiting for the response to a sync
+  // call, an invalid incoming message will disconnect the message pipe, cause
+  // the sync call to return false, and run the connection error handler
+  // asynchronously.
+
+  void Run() override {
+    MessagePipe pipe;
+
+    using InterfaceType = typename TypeParam::Interface;
+    this->ptr_.Bind(
+        InterfacePtrInfo<InterfaceType>(std::move(pipe.handle0), 0u));
+
+    MessagePipeHandle raw_binding_handle = pipe.handle1.get();
+    this->impl_ = base::MakeUnique<ImplTypeFor<InterfaceType>>(
+        InterfaceRequest<InterfaceType>(std::move(pipe.handle1)));
+
+    this->impl_->set_echo_handler(
+        [raw_binding_handle](int32_t value,
+                             const TestSync::EchoCallback& callback) {
+          // Write a 1-byte message, which is considered invalid.
+          char invalid_message = 0;
+          MojoResult result =
+              WriteMessageRaw(raw_binding_handle, &invalid_message, 1u, nullptr,
+                              0u, MOJO_WRITE_MESSAGE_FLAG_NONE);
+          ASSERT_EQ(MOJO_RESULT_OK, result);
+          callback.Run(value);
+        });
+
+    this->ptr_.set_connection_error_handler(
+        LambdaBinder<>::BindLambda([this]() {
+          connection_error_dispatched_ = true;
+          this->Done();
+        }));
+
+    int32_t result_value = -1;
+    ASSERT_FALSE(this->ptr_->Echo(456, &result_value));
+    EXPECT_EQ(-1, result_value);
+    ASSERT_FALSE(connection_error_dispatched_);
+  }
+  bool connection_error_dispatched_ = false;
+};
+
 TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) {
   // Test that an interface pointer waiting for a sync call response can be
   // reentered by an associated binding serving sync methods on the same thread.
diff --git a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
index 98b8cae..f8d072d 100644
--- a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
+++ b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
@@ -52,7 +52,7 @@
   // Any message sent through this forwarding interface will dispatch its reply,
   // if any, back to the thread which called the corresponding interface method.
   ThreadSafeForwarder(
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner,
       const ForwardMessageCallback& forward,
       const ForwardMessageWithResponderCallback& forward_with_responder,
       const AssociatedGroup& associated_group)
@@ -208,7 +208,7 @@
    public:
     explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder)
         : responder_(std::move(responder)),
-          caller_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+          caller_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
 
    private:
     bool Accept(Message* message) {
@@ -230,11 +230,11 @@
     }
 
     std::unique_ptr<MessageReceiver> responder_;
-    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
+    scoped_refptr<base::SequencedTaskRunner> caller_task_runner_;
   };
 
   ProxyType proxy_;
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   const ForwardMessageCallback forward_;
   const ForwardMessageWithResponderCallback forward_with_responder_;
   AssociatedGroup associated_group_;
@@ -272,7 +272,7 @@
   // that TaskRunner.
   static scoped_refptr<ThreadSafeInterfacePtrBase> Create(
       PtrInfoType ptr_info,
-      const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) {
+      const scoped_refptr<base::SequencedTaskRunner>& bind_task_runner) {
     scoped_refptr<PtrWrapper> wrapper = new PtrWrapper(bind_task_runner);
     wrapper->BindOnTaskRunner(std::move(ptr_info));
     return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder());
@@ -295,13 +295,13 @@
       : public base::RefCountedThreadSafe<PtrWrapper, PtrWrapperDeleter> {
    public:
     explicit PtrWrapper(InterfacePtrType ptr)
-        : PtrWrapper(base::ThreadTaskRunnerHandle::Get()) {
+        : PtrWrapper(base::SequencedTaskRunnerHandle::Get()) {
       ptr_ = std::move(ptr);
       associated_group_ = *ptr_.internal_state()->associated_group();
     }
 
     explicit PtrWrapper(
-        const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+        const scoped_refptr<base::SequencedTaskRunner>& task_runner)
         : task_runner_(task_runner) {}
 
     void BindOnTaskRunner(AssociatedInterfacePtrInfo<InterfaceType> ptr_info) {
@@ -362,7 +362,7 @@
     }
 
     InterfacePtrType ptr_;
-    const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+    const scoped_refptr<base::SequencedTaskRunner> task_runner_;
     AssociatedGroup associated_group_;
 
     DISALLOW_COPY_AND_ASSIGN(PtrWrapper);
diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc
index 17d1198..4d3f3be 100644
--- a/mojo/public/cpp/system/simple_watcher.cc
+++ b/mojo/public/cpp/system/simple_watcher.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/heap_profiler.h"
 #include "mojo/public/c/system/watcher.h"
 
@@ -22,7 +23,7 @@
   // |handle| for |signals|.
   static scoped_refptr<Context> Create(
       base::WeakPtr<SimpleWatcher> watcher,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      scoped_refptr<base::SequencedTaskRunner> task_runner,
       WatcherHandle watcher_handle,
       Handle handle,
       MojoHandleSignals signals,
@@ -71,7 +72,7 @@
   friend class base::RefCountedThreadSafe<Context>;
 
   Context(base::WeakPtr<SimpleWatcher> weak_watcher,
-          scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+          scoped_refptr<base::SequencedTaskRunner> task_runner,
           int watch_id)
       : weak_watcher_(weak_watcher),
         task_runner_(task_runner),
@@ -109,7 +110,7 @@
   }
 
   const base::WeakPtr<SimpleWatcher> weak_watcher_;
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   const int watch_id_;
 
   base::Lock lock_;
@@ -120,16 +121,17 @@
 
 SimpleWatcher::SimpleWatcher(const tracked_objects::Location& from_here,
                              ArmingPolicy arming_policy,
-                             scoped_refptr<base::SingleThreadTaskRunner> runner)
+                             scoped_refptr<base::SequencedTaskRunner> runner)
     : arming_policy_(arming_policy),
       task_runner_(std::move(runner)),
-      is_default_task_runner_(task_runner_ ==
-                              base::ThreadTaskRunnerHandle::Get()),
+      is_default_task_runner_(base::ThreadTaskRunnerHandle::IsSet() &&
+                              task_runner_ ==
+                                  base::ThreadTaskRunnerHandle::Get()),
       heap_profiler_tag_(from_here.file_name()),
       weak_factory_(this) {
   MojoResult rv = CreateWatcher(&Context::CallNotify, &watcher_handle_);
   DCHECK_EQ(MOJO_RESULT_OK, rv);
-  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
 }
 
 SimpleWatcher::~SimpleWatcher() {
@@ -138,14 +140,14 @@
 }
 
 bool SimpleWatcher::IsWatching() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return context_ != nullptr;
 }
 
 MojoResult SimpleWatcher::Watch(Handle handle,
                                 MojoHandleSignals signals,
                                 const ReadyCallback& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!IsWatching());
   DCHECK(!callback.is_null());
 
@@ -171,7 +173,7 @@
 }
 
 void SimpleWatcher::Cancel() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // The watcher may have already been cancelled if the handle was closed.
   if (!context_)
@@ -200,7 +202,7 @@
 }
 
 MojoResult SimpleWatcher::Arm(MojoResult* ready_result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   uint32_t num_ready_contexts = 1;
   uintptr_t ready_context;
   MojoResult local_ready_result;
@@ -220,7 +222,7 @@
 }
 
 void SimpleWatcher::ArmOrNotify() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Already cancelled, nothing to do.
   if (!IsWatching())
@@ -238,7 +240,7 @@
 }
 
 void SimpleWatcher::OnHandleReady(int watch_id, MojoResult result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // This notification may be for a previously watched context, in which case
   // we just ignore it.
diff --git a/mojo/public/cpp/system/simple_watcher.h b/mojo/public/cpp/system/simple_watcher.h
index 9001884..8136892 100644
--- a/mojo/public/cpp/system/simple_watcher.h
+++ b/mojo/public/cpp/system/simple_watcher.h
@@ -10,21 +10,21 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequence_checker.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/c/system/types.h"
 #include "mojo/public/cpp/system/system_export.h"
 #include "mojo/public/cpp/system/watcher.h"
 
 namespace base {
-class SingleThreadTaskRunner;
+class SequencedTaskRunner;
 }
 
 namespace mojo {
 
 // This provides a convenient thread-bound watcher implementation to safely
 // watch a single handle, dispatching state change notifications to an arbitrary
-// SingleThreadTaskRunner running on the same thread as the SimpleWatcher.
+// SequencedTaskRunner running on the same thread as the SimpleWatcher.
 //
 // SimpleWatcher exposes the concept of "arming" from the low-level Watcher API.
 // In general, a SimpleWatcher must be "armed" in order to dispatch a single
@@ -80,8 +80,8 @@
 
   SimpleWatcher(const tracked_objects::Location& from_here,
                 ArmingPolicy arming_policy,
-                scoped_refptr<base::SingleThreadTaskRunner> runner =
-                    base::ThreadTaskRunnerHandle::Get());
+                scoped_refptr<base::SequencedTaskRunner> runner =
+                    base::SequencedTaskRunnerHandle::Get());
   ~SimpleWatcher();
 
   // Indicates if the SimpleWatcher is currently watching a handle.
@@ -166,17 +166,17 @@
 
   void OnHandleReady(int watch_id, MojoResult result);
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // The policy used to determine how this SimpleWatcher is armed.
   const ArmingPolicy arming_policy_;
 
   // The TaskRunner of this SimpleWatcher's owning thread. This field is safe to
   // access from any thread.
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
-  // Whether |task_runner_| is the same as base::ThreadTaskRunnerHandle::Get()
-  // for the thread.
+  // Whether |task_runner_| is the same as
+  // base::SequencedTaskRunnerHandle::Get() for the thread.
   const bool is_default_task_runner_;
 
   ScopedWatcherHandle watcher_handle_;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index ef154f9..4ba004e6 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -42,7 +42,7 @@
 # in addition to use_openssl_certs or use_nss_certs, in that case byte certs
 # are used internally but OpenSSL or NSS are used for certificate verification.
 # TODO(mattm): crbug.com/671420: Implement and enable this for all platforms.
-use_byte_certs = is_mac || is_android || is_nacl || is_ios
+use_byte_certs = is_mac || is_android || is_nacl || is_ios || is_win
 
 buildflag_header("features") {
   header = "net_features.h"
@@ -608,6 +608,8 @@
       "cert/x509_util_mac.h",
       "cert/x509_util_nss.cc",
       "cert/x509_util_nss.h",
+      "cert/x509_util_win.cc",
+      "cert/x509_util_win.h",
       "cert_net/cert_net_fetcher_impl.cc",
       "cert_net/cert_net_fetcher_impl.h",
       "cert_net/nss_ocsp.cc",
@@ -3460,6 +3462,7 @@
     "data/parse_certificate_unittest/serial_negative.pem",
     "data/parse_certificate_unittest/serial_zero_padded.pem",
     "data/parse_certificate_unittest/serial_zero_padded_21_bytes.pem",
+    "data/parse_certificate_unittest/signature_algorithm_null.pem",
     "data/parse_certificate_unittest/subject_alt_name.pem",
     "data/parse_certificate_unittest/subject_t61string.pem",
     "data/parse_certificate_unittest/subject_t61string_1-32.pem",
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index fec9c33c..2a82ac6 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -487,7 +487,7 @@
   base::FilePath certs_dir =
       GetTestNetDataDirectory().AppendASCII("parse_certificate_unittest");
   scoped_refptr<X509Certificate> bad_cert =
-      ImportCertFromFile(certs_dir, "extensions_data_after_sequence.pem");
+      ImportCertFromFile(certs_dir, "signature_algorithm_null.pem");
   ASSERT_TRUE(bad_cert);
 
   scoped_refptr<X509Certificate> ok_cert(
@@ -515,7 +515,7 @@
   base::FilePath certs_dir =
       GetTestNetDataDirectory().AppendASCII("parse_certificate_unittest");
   scoped_refptr<X509Certificate> bad_cert =
-      ImportCertFromFile(certs_dir, "extensions_data_after_sequence.pem");
+      ImportCertFromFile(certs_dir, "signature_algorithm_null.pem");
   ASSERT_TRUE(bad_cert);
 
   scoped_refptr<X509Certificate> ok_cert(
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc
index 6a46ea01..e94c1fc6 100644
--- a/net/cert/cert_verify_proc_win.cc
+++ b/net/cert/cert_verify_proc_win.cc
@@ -27,6 +27,7 @@
 #include "net/cert/known_roots_win.h"
 #include "net/cert/test_root_certs.h"
 #include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util_win.h"
 
 #if !defined(CERT_TRUST_HAS_WEAK_SIGNATURE)
 // This was introduced in Windows 8 / Windows Server 2012, but retroactively
@@ -52,22 +53,12 @@
   }
 };
 
-struct FreeCertContextFunctor {
-  void operator()(PCCERT_CONTEXT context) const {
-    if (context)
-      CertFreeCertificateContext(context);
-  }
-};
-
 typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
     ScopedHCERTCHAINENGINE;
 
 typedef std::unique_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor>
     ScopedPCCERT_CHAIN_CONTEXT;
 
-typedef std::unique_ptr<const CERT_CONTEXT, FreeCertContextFunctor>
-    ScopedPCCERT_CONTEXT;
-
 //-----------------------------------------------------------------------------
 
 int MapSecurityError(SECURITY_STATUS err) {
@@ -331,7 +322,8 @@
     if (has_root_ca)
       verified_chain.push_back(element[num_elements]->pCertContext);
     scoped_refptr<X509Certificate> verified_cert_with_chain =
-        X509Certificate::CreateFromHandle(verified_cert, verified_chain);
+        x509_util::CreateX509CertificateFromCertContexts(verified_cert,
+                                                         verified_chain);
     if (verified_cert_with_chain)
       verify_result->verified_cert = std::move(verified_cert_with_chain);
     else
@@ -870,9 +862,11 @@
   // CRLSet.
   ScopedThreadLocalCRLSet thread_local_crlset(crl_set);
 
-  PCCERT_CONTEXT cert_handle = cert->os_cert_handle();
-  if (!cert_handle)
-    return ERR_UNEXPECTED;
+  ScopedPCCERT_CONTEXT cert_list = x509_util::CreateCertContextWithChain(cert);
+  if (!cert_list) {
+    verify_result->cert_status |= CERT_STATUS_INVALID;
+    return ERR_CERT_INVALID;
+  }
 
   // Build and validate certificate chain.
   CERT_CHAIN_PARA chain_para;
@@ -896,7 +890,7 @@
   std::unique_ptr<CERT_POLICIES_INFO, base::FreeDeleter> policies_info;
   LPSTR ev_policy_oid = NULL;
   if (flags & CertVerifier::VERIFY_EV_CERT) {
-    GetCertPoliciesInfo(cert_handle, &policies_info);
+    GetCertPoliciesInfo(cert_list.get(), &policies_info);
     if (policies_info.get()) {
       EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
       for (DWORD i = 0; i < policies_info->cPolicyInfo; ++i) {
@@ -947,8 +941,6 @@
   if (TestRootCerts::HasInstance())
     chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
 
-  ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert());
-
   // Add stapled OCSP response data, which will be preferred over online checks
   // and used when in cache-only mode.
   if (!ocsp_response.empty()) {
@@ -1119,7 +1111,7 @@
       chain_context->TrustStatus.dwErrorStatus);
 
   // Flag certificates that have a Subject common name with a NULL character.
-  if (CertSubjectCommonNameHasNull(cert_handle))
+  if (CertSubjectCommonNameHasNull(cert_list.get()))
     verify_result->cert_status |= CERT_STATUS_INVALID;
 
   base::string16 hostname16 = base::ASCIIToUTF16(hostname);
diff --git a/net/cert/known_roots_win.cc b/net/cert/known_roots_win.cc
index 0a1d3ac..d24896e 100644
--- a/net/cert/known_roots_win.cc
+++ b/net/cert/known_roots_win.cc
@@ -6,13 +6,14 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "crypto/sha2.h"
-#include "net/cert/x509_certificate.h"
+#include "net/base/hash_value.h"
 #include "net/cert/x509_certificate_known_roots_win.h"
+#include "net/cert/x509_util_win.h"
 
 namespace net {
 
 bool IsKnownRoot(PCCERT_CONTEXT cert) {
-  SHA256HashValue hash = X509Certificate::CalculateFingerprint256(cert);
+  SHA256HashValue hash = x509_util::CalculateFingerprint256(cert);
   bool is_builtin =
       IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0],
                                 sizeof(kKnownRootCertSHA256Hashes));
diff --git a/net/cert/test_root_certs_win.cc b/net/cert/test_root_certs_win.cc
index e13f173..3c900ca 100644
--- a/net/cert/test_root_certs_win.cc
+++ b/net/cert/test_root_certs_win.cc
@@ -8,6 +8,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/win/win_util.h"
 #include "net/cert/x509_certificate.h"
 
@@ -142,9 +143,12 @@
   // happen.
   g_capi_injector.Get();
 
-  BOOL ok = CertAddCertificateContextToStore(
-      temporary_roots_, certificate->os_cert_handle(),
-      CERT_STORE_ADD_NEW, NULL);
+  std::string der_cert;
+  X509Certificate::GetDEREncoded(certificate->os_cert_handle(), &der_cert);
+  BOOL ok = CertAddEncodedCertificateToStore(
+      temporary_roots_, X509_ASN_ENCODING,
+      reinterpret_cast<const BYTE*>(der_cert.data()),
+      base::checked_cast<DWORD>(der_cert.size()), CERT_STORE_ADD_NEW, NULL);
   if (!ok) {
     // If the certificate is already added, return successfully.
     return GetLastError() == static_cast<DWORD>(CRYPT_E_EXISTS);
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h
index 4fb0b3e..af5a03a 100644
--- a/net/cert/x509_certificate.h
+++ b/net/cert/x509_certificate.h
@@ -235,45 +235,6 @@
   // |valid_issuers| is a list of DER-encoded X.509 DistinguishedNames.
   bool IsIssuedByEncoded(const std::vector<std::string>& valid_issuers);
 
-#if defined(OS_WIN)
-  // Returns a new PCCERT_CONTEXT containing this certificate and its
-  // intermediate certificates, or NULL on failure. The returned
-  // PCCERT_CONTEXT *MUST NOT* be stored in an X509Certificate, as this will
-  // cause os_cert_handle() to return incorrect results. This function is only
-  // necessary if the CERT_CONTEXT.hCertStore member will be accessed or
-  // enumerated, which is generally true for any CryptoAPI functions involving
-  // certificate chains, including validation or certificate display.
-  //
-  // Remarks:
-  // Depending on the CryptoAPI function, Windows may need to access the
-  // HCERTSTORE that the passed-in PCCERT_CONTEXT belongs to, such as to
-  // locate additional intermediates. However, all certificate handles are added
-  // to a NULL HCERTSTORE, allowing the system to manage the resources. As a
-  // result, intermediates for |cert_handle_| cannot be located simply via
-  // |cert_handle_->hCertStore|, as it refers to a magic value indicating
-  // "only this certificate".
-  //
-  // To avoid this problems, a new in-memory HCERTSTORE is created containing
-  // just this certificate and its intermediates. The handle to the version of
-  // the current certificate in the new HCERTSTORE is then returned, with the
-  // PCCERT_CONTEXT's HCERTSTORE set to be automatically freed when the returned
-  // certificate handle is freed.
-  //
-  // This function is only needed when the HCERTSTORE of the os_cert_handle()
-  // will be accessed, which is generally only during certificate validation
-  // or display. While the returned PCCERT_CONTEXT and its HCERTSTORE can
-  // safely be used on multiple threads if no further modifications happen, it
-  // is generally preferable for each thread that needs such a context to
-  // obtain its own, rather than risk thread-safety issues by sharing.
-  //
-  // Because of how X509Certificate caching is implemented, attempting to
-  // create an X509Certificate from the returned PCCERT_CONTEXT may result in
-  // the original handle (and thus the originall HCERTSTORE) being returned by
-  // os_cert_handle(). For this reason, the returned PCCERT_CONTEXT *MUST NOT*
-  // be stored in an X509Certificate.
-  PCCERT_CONTEXT CreateOSCertChainForCert() const;
-#endif
-
 #if defined(USE_OPENSSL_CERTS)
   // Returns a handle to a global, in-memory certificate store. We
   // use it for test code, e.g. importing the test server's certificate.
diff --git a/net/cert/x509_certificate_win.cc b/net/cert/x509_certificate_win.cc
index 05eec4e..eee2f90 100644
--- a/net/cert/x509_certificate_win.cc
+++ b/net/cert/x509_certificate_win.cc
@@ -17,6 +17,7 @@
 #include "crypto/scoped_capi_types.h"
 #include "crypto/sha2.h"
 #include "net/base/net_errors.h"
+#include "net/cert/x509_util_win.h"
 #include "third_party/boringssl/src/include/openssl/sha.h"
 
 using base::Time;
@@ -199,40 +200,6 @@
   return has_san;
 }
 
-PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const {
-  // Create an in-memory certificate store to hold this certificate and
-  // any intermediate certificates in |intermediate_ca_certs_|. The store
-  // will be referenced in the returned PCCERT_CONTEXT, and will not be freed
-  // until the PCCERT_CONTEXT is freed.
-  ScopedHCERTSTORE store(CertOpenStore(
-      CERT_STORE_PROV_MEMORY, 0, NULL,
-      CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
-  if (!store.get())
-    return NULL;
-
-  // NOTE: This preserves all of the properties of |os_cert_handle()| except
-  // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
-  // properties that hold access to already-opened private keys. If a handle
-  // has already been unlocked (eg: PIN prompt), then the first time that the
-  // identity is used for client auth, it may prompt the user again.
-  PCCERT_CONTEXT primary_cert;
-  BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(),
-                                             CERT_STORE_ADD_ALWAYS,
-                                             &primary_cert);
-  if (!ok || !primary_cert)
-    return NULL;
-
-  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
-    CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i],
-                                     CERT_STORE_ADD_ALWAYS, NULL);
-  }
-
-  // Note: |store| is explicitly not released, as the call to CertCloseStore()
-  // when |store| goes out of scope will not actually free the store. Instead,
-  // the store will be freed when |primary_cert| is freed.
-  return primary_cert;
-}
-
 // static
 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
                                     std::string* encoded) {
@@ -308,20 +275,7 @@
 
 // static
 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) {
-  DCHECK(NULL != cert->pbCertEncoded);
-  DCHECK_NE(0u, cert->cbCertEncoded);
-
-  SHA256HashValue sha256;
-  size_t sha256_size = sizeof(sha256.data);
-
-  // Use crypto::SHA256HashString for two reasons:
-  // * < Windows Vista does not have universal SHA-256 support.
-  // * More efficient on Windows > Vista (less overhead since non-default CSP
-  // is not needed).
-  base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
-                             cert->cbCertEncoded);
-  crypto::SHA256HashString(der_cert, sha256.data, sha256_size);
-  return sha256;
+  return x509_util::CalculateFingerprint256(cert);
 }
 
 SHA256HashValue X509Certificate::CalculateCAFingerprint256(
@@ -458,16 +412,7 @@
 
 // static
 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) {
-  bool valid_signature = !!CryptVerifyCertificateSignatureEx(
-      NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
-      reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)),
-      CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
-      reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), 0, NULL);
-  if (!valid_signature)
-    return false;
-  return !!CertCompareCertificateName(X509_ASN_ENCODING,
-                                      &cert_handle->pCertInfo->Subject,
-                                      &cert_handle->pCertInfo->Issuer);
+  return x509_util::IsSelfSigned(cert_handle);
 }
 
 }  // namespace net
diff --git a/net/cert/x509_util_win.cc b/net/cert/x509_util_win.cc
new file mode 100644
index 0000000..4b1f74d
--- /dev/null
+++ b/net/cert/x509_util_win.cc
@@ -0,0 +1,149 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/x509_util_win.h"
+
+#include "crypto/scoped_capi_types.h"
+#include "crypto/sha2.h"
+#include "net/cert/x509_certificate.h"
+#include "net/net_features.h"
+#include "third_party/boringssl/src/include/openssl/pool.h"
+
+namespace net {
+
+namespace x509_util {
+
+namespace {
+
+using ScopedHCERTSTORE = crypto::ScopedCAPIHandle<
+    HCERTSTORE,
+    crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0>>;
+
+}  // namespace
+
+scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
+    PCCERT_CONTEXT os_cert,
+    const std::vector<PCCERT_CONTEXT>& os_chain) {
+#if BUILDFLAG(USE_BYTE_CERTS)
+  if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded)
+    return nullptr;
+  bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
+      X509Certificate::CreateOSCertHandleFromBytes(
+          reinterpret_cast<const char*>(os_cert->pbCertEncoded),
+          os_cert->cbCertEncoded));
+  if (!cert_handle)
+    return nullptr;
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
+  X509Certificate::OSCertHandles intermediates_raw;
+  for (PCCERT_CONTEXT os_intermediate : os_chain) {
+    if (!os_intermediate || !os_intermediate->pbCertEncoded ||
+        !os_intermediate->cbCertEncoded)
+      return nullptr;
+    bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
+        X509Certificate::CreateOSCertHandleFromBytes(
+            reinterpret_cast<const char*>(os_intermediate->pbCertEncoded),
+            os_intermediate->cbCertEncoded));
+    if (!intermediate_cert_handle)
+      return nullptr;
+    intermediates_raw.push_back(intermediate_cert_handle.get());
+    intermediates.push_back(std::move(intermediate_cert_handle));
+  }
+  scoped_refptr<X509Certificate> result(
+      X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw));
+  return result;
+#else
+  return X509Certificate::CreateFromHandle(os_cert, os_chain);
+#endif
+}
+
+ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) {
+  // Create an in-memory certificate store to hold the certificate and its
+  // intermediate certificates. The store will be referenced in the returned
+  // PCCERT_CONTEXT, and will not be freed until the PCCERT_CONTEXT is freed.
+  ScopedHCERTSTORE store(
+      CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL,
+                    CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
+  if (!store.get())
+    return nullptr;
+
+  PCCERT_CONTEXT primary_cert = nullptr;
+
+#if BUILDFLAG(USE_BYTE_CERTS)
+  BOOL ok = CertAddEncodedCertificateToStore(
+      store.get(), X509_ASN_ENCODING,
+      CRYPTO_BUFFER_data(cert->os_cert_handle()),
+      base::checked_cast<DWORD>(CRYPTO_BUFFER_len(cert->os_cert_handle())),
+      CERT_STORE_ADD_ALWAYS, &primary_cert);
+  if (!ok || !primary_cert)
+    return nullptr;
+  ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
+
+  for (X509Certificate::OSCertHandle intermediate :
+       cert->GetIntermediateCertificates()) {
+    ok = CertAddEncodedCertificateToStore(
+        store.get(), X509_ASN_ENCODING, CRYPTO_BUFFER_data(intermediate),
+        base::checked_cast<DWORD>(CRYPTO_BUFFER_len(intermediate)),
+        CERT_STORE_ADD_ALWAYS, NULL);
+    if (!ok)
+      return nullptr;
+  }
+#else
+  PCCERT_CONTEXT os_cert_handle = cert->os_cert_handle();
+  const std::vector<PCCERT_CONTEXT>& intermediate_ca_certs =
+      cert->GetIntermediateCertificates();
+
+  // NOTE: This preserves all of the properties of |os_cert_handle| except
+  // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
+  // properties that hold access to already-opened private keys. If a handle
+  // has already been unlocked (eg: PIN prompt), then the first time that the
+  // identity is used for client auth, it may prompt the user again.
+  BOOL ok = CertAddCertificateContextToStore(
+      store.get(), os_cert_handle, CERT_STORE_ADD_ALWAYS, &primary_cert);
+  if (!ok || !primary_cert)
+    return nullptr;
+  ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
+
+  for (PCCERT_CONTEXT intermediate : intermediate_ca_certs) {
+    CertAddCertificateContextToStore(store.get(), intermediate,
+                                     CERT_STORE_ADD_ALWAYS, NULL);
+  }
+#endif
+
+  // Note: |primary_cert| retains a reference to |store|, so the store will
+  // actually be freed when |primary_cert| is freed.
+  return scoped_primary_cert;
+}
+
+SHA256HashValue CalculateFingerprint256(PCCERT_CONTEXT cert) {
+  DCHECK(NULL != cert->pbCertEncoded);
+  DCHECK_NE(0u, cert->cbCertEncoded);
+
+  SHA256HashValue sha256;
+
+  // Use crypto::SHA256HashString for two reasons:
+  // * < Windows Vista does not have universal SHA-256 support.
+  // * More efficient on Windows > Vista (less overhead since non-default CSP
+  // is not needed).
+  base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
+                             cert->cbCertEncoded);
+  crypto::SHA256HashString(der_cert, sha256.data, sizeof(sha256.data));
+  return sha256;
+}
+
+bool IsSelfSigned(PCCERT_CONTEXT cert_handle) {
+  bool valid_signature = !!CryptVerifyCertificateSignatureEx(
+      NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
+      reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)),
+      CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
+      reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), 0, NULL);
+  if (!valid_signature)
+    return false;
+  return !!CertCompareCertificateName(X509_ASN_ENCODING,
+                                      &cert_handle->pCertInfo->Subject,
+                                      &cert_handle->pCertInfo->Issuer);
+}
+
+}  // namespace x509_util
+
+}  // namespace net
diff --git a/net/cert/x509_util_win.h b/net/cert/x509_util_win.h
new file mode 100644
index 0000000..e3d0d947
--- /dev/null
+++ b/net/cert/x509_util_win.h
@@ -0,0 +1,93 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_X509_UTIL_WIN_H_
+#define NET_CERT_X509_UTIL_WIN_H_
+
+#include <memory>
+#include <vector>
+
+#include <windows.h>
+
+#include "base/memory/ref_counted.h"
+#include "crypto/wincrypt_shim.h"
+#include "net/base/hash_value.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class X509Certificate;
+
+struct FreeCertContextFunctor {
+  void operator()(PCCERT_CONTEXT context) const {
+    if (context)
+      CertFreeCertificateContext(context);
+  }
+};
+
+using ScopedPCCERT_CONTEXT =
+    std::unique_ptr<const CERT_CONTEXT, FreeCertContextFunctor>;
+
+namespace x509_util {
+
+// Creates an X509Certificate representing |os_cert| with intermediates
+// |os_chain|.
+NET_EXPORT scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
+    PCCERT_CONTEXT os_cert,
+    const std::vector<PCCERT_CONTEXT>& os_chain);
+
+// Returns a new PCCERT_CONTEXT containing the certificate and its
+// intermediate certificates, or NULL on failure. This function is only
+// necessary if the CERT_CONTEXT.hCertStore member will be accessed or
+// enumerated, which is generally true for any CryptoAPI functions involving
+// certificate chains, including validation or certificate display.
+//
+// While the returned PCCERT_CONTEXT and its HCERTSTORE can safely be used on
+// multiple threads if no further modifications happen, it is generally
+// preferable for each thread that needs such a context to obtain its own,
+// rather than risk thread-safety issues by sharing.
+//
+// ------------------------------------------------------------------------
+// The following remarks only apply when USE_BYTE_CERTS=false (e.g., when
+// using x509_certificate_win).
+// TODO(mattm): remove references to USE_BYTE_CERTS and clean up the rest of
+// the comment when x509_certificate_win is deleted.
+//
+// The returned PCCERT_CONTEXT *MUST NOT* be stored in an X509Certificate, as
+// this will cause os_cert_handle() to return incorrect results.
+//
+// Depending on the CryptoAPI function, Windows may need to access the
+// HCERTSTORE that the passed-in PCCERT_CONTEXT belongs to, such as to
+// locate additional intermediates. However, all X509Certificate handles are
+// added to a NULL HCERTSTORE, allowing the system to manage the resources.  As
+// a result, intermediates for |cert->os_cert_handle()| cannot be located
+// simply via |cert->os_cert_handle()->hCertStore|, as it refers to a magic
+// value indicating "only this certificate".
+//
+// To avoid this problems, a new in-memory HCERTSTORE is created containing
+// just this certificate and its intermediates. The handle to the version of
+// the current certificate in the new HCERTSTORE is then returned, with the
+// PCCERT_CONTEXT's HCERTSTORE set to be automatically freed when the returned
+// certificate handle is freed.
+//
+// Because of how X509Certificate caching is implemented, attempting to
+// create an X509Certificate from the returned PCCERT_CONTEXT may result in
+// the original handle (and thus the originall HCERTSTORE) being returned by
+// os_cert_handle(). For this reason, the returned PCCERT_CONTEXT *MUST NOT*
+// be stored in an X509Certificate.
+NET_EXPORT ScopedPCCERT_CONTEXT
+CreateCertContextWithChain(const X509Certificate* cert);
+
+// Calculates the SHA-256 fingerprint of the certificate.  Returns an empty
+// (all zero) fingerprint on failure.
+NET_EXPORT SHA256HashValue CalculateFingerprint256(PCCERT_CONTEXT cert);
+
+// Returns true if the certificate is self-signed.
+NET_EXPORT bool IsSelfSigned(PCCERT_CONTEXT cert_handle);
+
+}  // namespace x509_util
+
+}  // namespace net
+
+#endif  // NET_CERT_X509_UTIL_WIN_H_
diff --git a/net/data/parse_certificate_unittest/signature_algorithm_null.pem b/net/data/parse_certificate_unittest/signature_algorithm_null.pem
new file mode 100644
index 0000000..c1b4164
--- /dev/null
+++ b/net/data/parse_certificate_unittest/signature_algorithm_null.pem
@@ -0,0 +1,11 @@
+#-----BEGIN SIGNATURE_ALGORITHM-----
+    SEQUENCE {
+      NULL {}
+    }
+#-----END SIGNATURE_ALGORITHM-----
+
+
+-----BEGIN CERTIFICATE-----
+MIICTTCCAbagAwIBAgIJAPuwTC6rEJsMMAIFADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE0MDQyMzIwNTA0MFoXDTE3MDQyMjIwNTA0MFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2CvIpjLkYv9N89CtWYtFp73xR78JWHsivTWulyWGlKCAwLQfdpFnRjHQEIS3Ih5wI5FyyOlteTqFd4APxJUWdcVKcUzIYz+j8mOcKk+a+svBcW4ohSigJx5lHK4H1VtvLUPtK5CxjK8kba7pFzoFwb+4HK5lOxtYwtmu1qpniPECAwEAAaNQME4wHQYDVR0OBBYEFIt11azLCL4OH2W3+la+bKd12oWvMB8GA1UdIwQYMBaAFIt11azLCL4OH2W3+la+bKd12oWvMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAO+h4bZXWPWr3ExksG8KIriKr9I0y9XxxZ88t0RzCw4fi6b6JXOQ0q0iRwj+VritHniV4a0+aEKRy/c/3AgywCgikWuLldH4RHTlgaskfafMuYybcnu9regrhVFeYqnKReAR+H49lTR8LEqycJA+EFBpVLR+78J0JsghcWTJlgCY=
+-----END CERTIFICATE-----
+
diff --git a/net/data/parse_certificate_unittest/v3_certificate_template.txt b/net/data/parse_certificate_unittest/v3_certificate_template.txt
index 4f0b36e..42b0bd4 100644
--- a/net/data/parse_certificate_unittest/v3_certificate_template.txt
+++ b/net/data/parse_certificate_unittest/v3_certificate_template.txt
@@ -13,11 +13,13 @@
 #-----BEGIN SERIAL-----
     INTEGER { `00fbb04c2eab109b0c` }
 #-----END SERIAL-----
+#-----BEGIN SIGNATURE_ALGORITHM-----
     SEQUENCE {
       # sha1WithRSAEncryption
       OBJECT_IDENTIFIER { 1.2.840.113549.1.1.5 }
       NULL {}
     }
+#-----END SIGNATURE_ALGORITHM-----
     SEQUENCE {
       SET {
         SEQUENCE {
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index 36ccd96..607eb1b 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -200,13 +200,12 @@
   impl_.SetSpdyServers(&spdy_servers3, false);
 
   // Verify the entries are in the same order.
+  impl_.GetSpdyServerList(&spdy_server_list, kMaxSupportsSpdyServerHosts);
+  EXPECT_EQ(2U, spdy_server_list.GetSize());
+
   ASSERT_TRUE(spdy_server_list.GetString(0, &string_value_g));
   ASSERT_EQ(spdy_server_g, string_value_g);
-  ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_p));
-  ASSERT_EQ(spdy_server_p, string_value_p);
-  ASSERT_TRUE(spdy_server_list.GetString(2, &string_value_m));
-  ASSERT_EQ(spdy_server_m, string_value_m);
-  ASSERT_TRUE(spdy_server_list.GetString(3, &string_value_d));
+  ASSERT_TRUE(spdy_server_list.GetString(1, &string_value_d));
   ASSERT_EQ(spdy_server_d, string_value_d);
 
   // Verify photos and mail servers don't support SPDY and other servers support
diff --git a/net/ssl/client_cert_store_win.cc b/net/ssl/client_cert_store_win.cc
index b82a94b..2383765 100644
--- a/net/ssl/client_cert_store_win.cc
+++ b/net/ssl/client_cert_store_win.cc
@@ -16,10 +16,12 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "crypto/wincrypt_shim.h"
 #include "net/cert/x509_util.h"
+#include "net/cert/x509_util_win.h"
 #include "net/ssl/ssl_platform_key_win.h"
 #include "net/ssl/ssl_private_key.h"
 
@@ -160,7 +162,7 @@
     }
 
     // Grab the intermediates, if any.
-    X509Certificate::OSCertHandles intermediates;
+    std::vector<PCCERT_CONTEXT> intermediates;
     for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) {
       PCCERT_CONTEXT chain_intermediate =
           chain_context->rgpChain[0]->rgpElement[i]->pCertContext;
@@ -180,18 +182,21 @@
     // The leaf or a intermediate may also have a weak signature algorithm but,
     // in that case, assume it is a configuration error.
     if (!intermediates.empty() &&
-        X509Certificate::IsSelfSigned(intermediates.back())) {
+        x509_util::IsSelfSigned(intermediates.back())) {
       CertFreeCertificateContext(intermediates.back());
       intermediates.pop_back();
     }
 
+    // TODO(mattm): The following comment is only true when not using
+    // USE_BYTE_CERTS. Remove it once the non-byte-certs code is also removed.
     // TODO(svaldez): cert currently wraps cert_context2 which may be backed
     // by a smartcard with threading difficulties. Instead, create a fresh
     // X509Certificate with CreateFromBytes and route cert_context2 into the
     // SSLPrivateKey. Probably changing CertificateList to be a
     // pair<X509Certificate, SSLPrivateKeyCallback>.
-    scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
-        cert_context2, intermediates);
+    scoped_refptr<X509Certificate> cert =
+        x509_util::CreateX509CertificateFromCertContexts(cert_context2,
+                                                         intermediates);
     if (cert) {
       selected_identities->push_back(base::MakeUnique<ClientCertIdentityWin>(
           std::move(cert),
@@ -259,11 +264,18 @@
   for (size_t i = 0; i < input_certs.size(); ++i) {
     // Add the certificate to the test store.
     PCCERT_CONTEXT cert = NULL;
-    if (!CertAddCertificateContextToStore(test_store,
-                                          input_certs[i]->os_cert_handle(),
-                                          CERT_STORE_ADD_NEW, &cert)) {
+    std::string der_cert;
+    X509Certificate::GetDEREncoded(input_certs[i]->os_cert_handle(), &der_cert);
+    if (!CertAddEncodedCertificateToStore(
+            test_store, X509_ASN_ENCODING,
+            reinterpret_cast<const BYTE*>(der_cert.data()),
+            base::checked_cast<DWORD>(der_cert.size()), CERT_STORE_ADD_NEW,
+            &cert)) {
       return false;
     }
+    // Hold the reference to the certificate (since we requested a copy).
+    ScopedPCCERT_CONTEXT scoped_cert(cert);
+
     // Add dummy private key data to the certificate - otherwise the certificate
     // would be discarded by the filtering routines.
     CRYPT_KEY_PROV_INFO private_key_data;
@@ -273,10 +285,6 @@
                                            0, &private_key_data)) {
       return false;
     }
-    // Decrement the reference count of the certificate (since we requested a
-    // copy).
-    if (!CertFreeCertificateContext(cert))
-      return false;
   }
 
   GetClientCertsImpl(test_store.get(), request, selected_identities);
diff --git a/services/service_manager/public/cpp/binder_registry.h b/services/service_manager/public/cpp/binder_registry.h
index e499b7a..70034170 100644
--- a/services/service_manager/public/cpp/binder_registry.h
+++ b/services/service_manager/public/cpp/binder_registry.h
@@ -32,11 +32,11 @@
   ~BinderRegistryWithParams() = default;
 
   template <typename Interface>
-  void AddInterface(const base::Callback<void(const BindSourceInfo&,
-                                              mojo::InterfaceRequest<Interface>,
-                                              BinderArgs...)>& callback,
-                    const scoped_refptr<base::SingleThreadTaskRunner>&
-                        task_runner = nullptr) {
+  void AddInterface(
+      const base::Callback<void(const BindSourceInfo&,
+                                mojo::InterfaceRequest<Interface>,
+                                BinderArgs...)>& callback,
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner = nullptr) {
     SetInterfaceBinder(
         Interface::Name_,
         base::MakeUnique<CallbackBinder<Interface, BinderArgs...>>(
@@ -46,16 +46,15 @@
       const std::string& interface_name,
       const base::Callback<void(mojo::ScopedMessagePipeHandle, BinderArgs...)>&
           callback,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner =
-          nullptr) {
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner = nullptr) {
     SetInterfaceBinder(interface_name,
                        base::MakeUnique<GenericCallbackBinder<BinderArgs...>>(
                            callback, task_runner));
   }
-  void AddInterface(const std::string& interface_name,
-                    const Binder& callback,
-                    const scoped_refptr<base::SingleThreadTaskRunner>&
-                        task_runner = nullptr) {
+  void AddInterface(
+      const std::string& interface_name,
+      const Binder& callback,
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner = nullptr) {
     SetInterfaceBinder(interface_name,
                        base::MakeUnique<GenericCallbackBinder<BinderArgs...>>(
                            callback, task_runner));
diff --git a/services/service_manager/public/cpp/connector.cc b/services/service_manager/public/cpp/connector.cc
index 5c75a6a..9d3da79 100644
--- a/services/service_manager/public/cpp/connector.cc
+++ b/services/service_manager/public/cpp/connector.cc
@@ -14,7 +14,7 @@
 
 Connector::Connector(mojom::ConnectorPtrInfo unbound_state)
     : unbound_state_(std::move(unbound_state)), weak_factory_(this) {
-  thread_checker_.DetachFromThread();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 Connector::Connector(mojom::ConnectorPtr connector)
@@ -109,7 +109,7 @@
 // Connector, private:
 
 void Connector::OnConnectionError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.reset();
 }
 
@@ -144,8 +144,8 @@
       return false;
     }
 
-    // Bind the ThreadChecker to this thread.
-    DCHECK(thread_checker_.CalledOnValidThread());
+    // Bind the SequenceChecker to this thread.
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
     connector_.Bind(std::move(unbound_state_));
     connector_.set_connection_error_handler(
diff --git a/services/service_manager/public/cpp/connector.h b/services/service_manager/public/cpp/connector.h
index 4abfcce..152b310 100644
--- a/services/service_manager/public/cpp/connector.h
+++ b/services/service_manager/public/cpp/connector.h
@@ -9,7 +9,7 @@
 #include <memory>
 
 #include "base/callback.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
 #include "services/service_manager/public/cpp/export.h"
 #include "services/service_manager/public/cpp/identity.h"
 #include "services/service_manager/public/interfaces/connector.mojom.h"
@@ -149,7 +149,7 @@
   mojom::ConnectorPtrInfo unbound_state_;
   mojom::ConnectorPtr connector_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   std::map<std::string, BinderOverrideMap> local_binder_overrides_;
   StartServiceCallback start_service_callback_;
diff --git a/services/service_manager/public/cpp/interface_binder.h b/services/service_manager/public/cpp/interface_binder.h
index 3daab552..5420efe 100644
--- a/services/service_manager/public/cpp/interface_binder.h
+++ b/services/service_manager/public/cpp/interface_binder.h
@@ -47,7 +47,7 @@
                                            mojo::InterfaceRequest<Interface>)>;
 
   CallbackBinder(const BindCallback& callback,
-                 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+                 const scoped_refptr<base::SequencedTaskRunner>& task_runner)
       : callback_(callback), task_runner_(task_runner) {}
   ~CallbackBinder() override {}
 
@@ -75,7 +75,7 @@
   }
 
   const BindCallback callback_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   DISALLOW_COPY_AND_ASSIGN(CallbackBinder);
 };
 
@@ -89,12 +89,12 @@
 
   GenericCallbackBinder(
       const BindCallback& callback,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner)
       : callback_(callback), task_runner_(task_runner) {}
   GenericCallbackBinder(
       const base::Callback<void(mojo::ScopedMessagePipeHandle, BinderArgs...)>&
           callback,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner)
       : callback_(base::Bind(&BindCallbackAdapter<BinderArgs...>, callback)),
         task_runner_(task_runner) {}
   ~GenericCallbackBinder() override {}
@@ -125,7 +125,7 @@
   }
 
   const BindCallback callback_;
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   DISALLOW_COPY_AND_ASSIGN(GenericCallbackBinder);
 };
 
diff --git a/services/service_manager/public/cpp/service_context.cc b/services/service_manager/public/cpp/service_context.cc
index c0adcbd..48dcf7db 100644
--- a/services/service_manager/public/cpp/service_context.cc
+++ b/services/service_manager/public/cpp/service_context.cc
@@ -47,7 +47,7 @@
     const std::string& service_name,
     const std::string& interface_name,
     const BinderRegistry::Binder& binder,
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+    const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
   if (!g_overridden_binder_registries.Get()) {
     g_overridden_binder_registries.Get() =
         base::MakeUnique<ServiceNameToBinderRegistryMap>();
diff --git a/services/service_manager/public/cpp/service_context.h b/services/service_manager/public/cpp/service_context.h
index 4d6d72a0..c524864 100644
--- a/services/service_manager/public/cpp/service_context.h
+++ b/services/service_manager/public/cpp/service_context.h
@@ -114,7 +114,7 @@
       const std::string& service_name,
       const std::string& interface_name,
       const BinderRegistry::Binder& binder,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner = nullptr);
+      const scoped_refptr<base::SequencedTaskRunner>& task_runner = nullptr);
 
   // Clears all overridden interface binders for service |service_name| set via
   // SetGlobalBinderForTesting().
diff --git a/services/service_manager/public/cpp/service_context_ref.cc b/services/service_manager/public/cpp/service_context_ref.cc
index 086231b..cf28aeb 100644
--- a/services/service_manager/public/cpp/service_context_ref.cc
+++ b/services/service_manager/public/cpp/service_context_ref.cc
@@ -7,9 +7,9 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/sequence_checker.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 
 namespace service_manager {
 
@@ -17,17 +17,17 @@
  public:
   ServiceContextRefImpl(
       base::WeakPtr<ServiceContextRefFactory> factory,
-      scoped_refptr<base::SingleThreadTaskRunner> service_task_runner)
+      scoped_refptr<base::SequencedTaskRunner> service_task_runner)
       : factory_(factory), service_task_runner_(service_task_runner) {
     // This object is not thread-safe but may be used exclusively on a different
     // thread from the one which constructed it.
-    thread_checker_.DetachFromThread();
+    DETACH_FROM_SEQUENCE(sequence_checker_);
   }
 
   ~ServiceContextRefImpl() override {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-    if (service_task_runner_->BelongsToCurrentThread() && factory_) {
+    if (service_task_runner_->RunsTasksOnCurrentThread() && factory_) {
       factory_->Release();
     } else {
       service_task_runner_->PostTask(
@@ -38,9 +38,9 @@
  private:
   // ServiceContextRef:
   std::unique_ptr<ServiceContextRef> Clone() override {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-    if (service_task_runner_->BelongsToCurrentThread() && factory_) {
+    if (service_task_runner_->RunsTasksOnCurrentThread() && factory_) {
       factory_->AddRef();
     } else {
       service_task_runner_->PostTask(
@@ -52,8 +52,8 @@
   }
 
   base::WeakPtr<ServiceContextRefFactory> factory_;
-  scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
-  base::ThreadChecker thread_checker_;
+  scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(ServiceContextRefImpl);
 };
@@ -69,7 +69,7 @@
 std::unique_ptr<ServiceContextRef> ServiceContextRefFactory::CreateRef() {
   AddRef();
   return base::MakeUnique<ServiceContextRefImpl>(
-      weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get());
+      weak_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get());
 }
 
 void ServiceContextRefFactory::AddRef() {
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index 25bd5bc1..252e46b6 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -248,6 +248,7 @@
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeFirstCopyCallback
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
 -ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.ShouldRotateAfterRecreateLayers
 -ScreenshotControllerTest.BreaksCapture
 -ScreenshotControllerTest.MultipleDisplays
 -SystemGestureEventFilterTest.ControlWindowGetsMultiFingerGestureEvents
diff --git a/testing/buildbot/filters/ash_unittests_mus.filter b/testing/buildbot/filters/ash_unittests_mus.filter
index 5a02a51..9cb4f59 100644
--- a/testing/buildbot/filters/ash_unittests_mus.filter
+++ b/testing/buildbot/filters/ash_unittests_mus.filter
@@ -67,6 +67,7 @@
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalPrimaryDisplayDuringAnimationChangedRootWindow
 -ScreenRotationAnimatorSmoothAnimationTest.RemoveExternalSecondaryDisplayBeforeSecondCopyCallback
 -ScreenRotationAnimatorSmoothAnimationTest.RotatesToDifferentRotationWithCopyCallback
+-ScreenRotationAnimatorSmoothAnimationTest.ShouldRotateAfterRecreateLayers
 -ShellTest2.DontCrashWhenWindowDeleted
 -ToastManagerTest.NullMessageHasNoDismissButton
 -ToastManagerTest.QueueMessage
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter
index b1533fc0..8115bfe9 100644
--- a/testing/buildbot/filters/fuchsia.base_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -28,6 +28,9 @@
 -DiscardableSharedMemoryTest.MappedSize
 -DiscardableSharedMemoryTest.Purge
 -DiscardableSharedMemoryTest.ZeroSize
+-EventWriterTest.HeapDumpAggregation
+-EventWriterTest.HeapDumpNoBacktraceNoType
+-EventWriterTest.SerializeHeapProfileEventData
 -FeatureListTest.StoreAndRetrieveAssociatedFeaturesFromSharedMemory
 -FeatureListTest.StoreAndRetrieveFeaturesFromSharedMemory
 -FieldTrialListTest.AddTrialsToAllocator
@@ -43,15 +46,15 @@
 -FileLockingTest.UnlockOnTerminate
 -FilePathTest.FromUTF8Unsafe_And_AsUTF8Unsafe
 -FilePathWatcherTest.DeleteAndRecreate
--FilePathWatcherTest.DeletedFile
 -FilePathWatcherTest.DeleteDuringNotify
+-FilePathWatcherTest.DeletedFile
 -FilePathWatcherTest.DirectoryChain
 -FilePathWatcherTest.DisappearingDirectory
 -FilePathWatcherTest.FileAttributesChanged
 -FilePathWatcherTest.ModifiedFile
 -FilePathWatcherTest.MoveChild
--FilePathWatcherTest.MovedFile
 -FilePathWatcherTest.MoveParent
+-FilePathWatcherTest.MovedFile
 -FilePathWatcherTest.MultipleWatchersSingleFile
 -FilePathWatcherTest.NewFile
 -FilePathWatcherTest.NonExistentDirectory
@@ -152,10 +155,11 @@
 -PersistentMemoryAllocatorTest.IteratorParallelismTest
 -PersistentMemoryAllocatorTest.PageTest
 -PersistentMemoryAllocatorTest.ParallelismTest
--PersistentSampleMapTest.Accumulate_LargeValuesDontOverflow
 -PersistentSampleMapTest.AccumulateTest
+-PersistentSampleMapTest.Accumulate_LargeValuesDontOverflow
 -PlatformThreadTest.ThreadPriorityCurrentThread
 -ProcessMemoryDumpTest.CountResidentBytes
+-ProcessMemoryDumpTest.TakeAllDumpsFrom
 -ProcessTest.Move
 -ProcessTest.Terminate
 -ProcessTest.TerminateCurrentProcessImmediatelyWithNonZeroExitCode
@@ -174,6 +178,7 @@
 -ProcessUtilTest.LaunchProcess
 -ProcessUtilTest.PreExecHook
 -ProcessUtilTest.SpawnChild
+-RTLTest.WrapPathWithLTRFormatting
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.AvoidsDeadlockOnShutdown/0
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.AvoidsDeadlockOnShutdownWithSequencedBlockingTasks/0
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.ContinueOnShutdown/0
@@ -184,7 +189,6 @@
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.ShutsDownCleanWithContinueOnShutdown/0
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.SkipOnShutdown/0
 -RedirectionToTaskScheduler/SequencedWorkerPoolTest.SpuriousWorkSignal/0
--RTLTest.WrapPathWithLTRFormatting
 -SafeNumerics.SignedIntegerMath
 -SharedMemoryProcessTest.SharedMemoryAcrossProcesses
 -SharedMemoryTest.AnonymousExecutable
@@ -222,6 +226,7 @@
 -VerifyPathControlledByUserTest.Symlinks
 -VerifyPathControlledByUserTest.WriteBitChecks
 
+
 # https://crbug.com/734216
 -MemoryDumpSchedulerTest.StartStopQuickly
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 673896f..c5316cd 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2780,5 +2780,4 @@
 crbug.com/733357 [ Win Mac ] inspector/elements/styles-4/styles-history.html [ Failure Pass ]
 crbug.com/733448 virtual/mojo-loading/http/tests/inspector/extensions/extensions-network.html [ Failure Pass ]
 crbug.com/733448 http/tests/inspector/extensions/extensions-network.html [ Failure Pass ]
-crbug.com/729075 [ Mac10.11 Retina ] css3/blending/background-blend-mode-gif-color-2.html [ Failure Pass ]
 crbug.com/733524 [ Mac ] virtual/mojo-loading/http/tests/security/contentSecurityPolicy/report-cross-origin-no-cookies.php [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html
index 176ce09..cdfa61b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Limits on colSpan/rowSpan</title>
+<meta name="timeout" content="long">
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <div id=log></div>
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/css3/blending/background-blend-mode-gif-color-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/css3/blending/background-blend-mode-gif-color-2-expected.png
deleted file mode 100644
index 4a7c8a9..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/css3/blending/background-blend-mode-gif-color-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/blending/background-blend-mode-gif-color-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/blending/background-blend-mode-gif-color-2-expected.png
deleted file mode 100644
index 60746df..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/css3/blending/background-blend-mode-gif-color-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index 4fa977c3..b307c84 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -1347,104 +1347,6 @@
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(WebBlendMode blend_mode)
-    : CSSValue(kIdentifierClass) {
-  switch (blend_mode) {
-    case WebBlendMode::kNormal:
-      value_id_ = CSSValueNormal;
-      break;
-    case WebBlendMode::kMultiply:
-      value_id_ = CSSValueMultiply;
-      break;
-    case WebBlendMode::kScreen:
-      value_id_ = CSSValueScreen;
-      break;
-    case WebBlendMode::kOverlay:
-      value_id_ = CSSValueOverlay;
-      break;
-    case WebBlendMode::kDarken:
-      value_id_ = CSSValueDarken;
-      break;
-    case WebBlendMode::kLighten:
-      value_id_ = CSSValueLighten;
-      break;
-    case WebBlendMode::kColorDodge:
-      value_id_ = CSSValueColorDodge;
-      break;
-    case WebBlendMode::kColorBurn:
-      value_id_ = CSSValueColorBurn;
-      break;
-    case WebBlendMode::kHardLight:
-      value_id_ = CSSValueHardLight;
-      break;
-    case WebBlendMode::kSoftLight:
-      value_id_ = CSSValueSoftLight;
-      break;
-    case WebBlendMode::kDifference:
-      value_id_ = CSSValueDifference;
-      break;
-    case WebBlendMode::kExclusion:
-      value_id_ = CSSValueExclusion;
-      break;
-    case WebBlendMode::kHue:
-      value_id_ = CSSValueHue;
-      break;
-    case WebBlendMode::kSaturation:
-      value_id_ = CSSValueSaturation;
-      break;
-    case WebBlendMode::kColor:
-      value_id_ = CSSValueColor;
-      break;
-    case WebBlendMode::kLuminosity:
-      value_id_ = CSSValueLuminosity;
-      break;
-  }
-}
-
-template <>
-inline WebBlendMode CSSIdentifierValue::ConvertTo() const {
-  switch (value_id_) {
-    case CSSValueNormal:
-      return WebBlendMode::kNormal;
-    case CSSValueMultiply:
-      return WebBlendMode::kMultiply;
-    case CSSValueScreen:
-      return WebBlendMode::kScreen;
-    case CSSValueOverlay:
-      return WebBlendMode::kOverlay;
-    case CSSValueDarken:
-      return WebBlendMode::kDarken;
-    case CSSValueLighten:
-      return WebBlendMode::kLighten;
-    case CSSValueColorDodge:
-      return WebBlendMode::kColorDodge;
-    case CSSValueColorBurn:
-      return WebBlendMode::kColorBurn;
-    case CSSValueHardLight:
-      return WebBlendMode::kHardLight;
-    case CSSValueSoftLight:
-      return WebBlendMode::kSoftLight;
-    case CSSValueDifference:
-      return WebBlendMode::kDifference;
-    case CSSValueExclusion:
-      return WebBlendMode::kExclusion;
-    case CSSValueHue:
-      return WebBlendMode::kHue;
-    case CSSValueSaturation:
-      return WebBlendMode::kSaturation;
-    case CSSValueColor:
-      return WebBlendMode::kColor;
-    case CSSValueLuminosity:
-      return WebBlendMode::kLuminosity;
-    default:
-      break;
-  }
-
-  NOTREACHED();
-  return WebBlendMode::kNormal;
-}
-
-template <>
 inline CSSIdentifierValue::CSSIdentifierValue(LineCap e)
     : CSSValue(kIdentifierClass) {
   switch (e) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index 4488382..85ba864c 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1705,11 +1705,13 @@
     {
       name: "mix-blend-mode",
       name_for_methods: "BlendMode",
-      type_name: "blink::WebBlendMode",
-      field_size: 5,
-      field_template: "storage_only",
+      type_name: "WebBlendMode",
+      field_template: "keyword",
+      keywords: ["normal", "multiply", "screen", "overlay", "darken", "lighten",
+       "color-dodge", "color-burn", "hard-light", "soft-light", "difference", 
+       "exclusion", "hue", "saturation", "color", "luminosity"], 
       field_group: "rare-non-inherited",
-      default_value: "WebBlendMode::kNormal",
+      default_value: "normal",
       include_paths: ["public/platform/WebBlendMode.h"],
     },
     {
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.cpp b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
index 1a0d1b1..828f181d 100644
--- a/third_party/WebKit/Source/core/dom/ModuleScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
@@ -34,15 +34,15 @@
     AccessControlStatus access_control_status,
     const TextPosition& start_position) {
   // https://html.spec.whatwg.org/#creating-a-module-script
-  // Step 1. Let script be a new module script that this algorithm will
-  // subsequently initialize.
-  // Step 2. Set script's settings object to the environment settings object
-  // provided.
-  // Note: "script's settings object" will be "modulator".
-
-  v8::HandleScope scope(modulator->GetScriptState()->GetIsolate());
-  ExceptionState exception_state(modulator->GetScriptState()->GetIsolate(),
-                                 ExceptionState::kExecutionContext,
+  // Step 1. "Let script be a new module script that this algorithm will
+  // subsequently initialize, with its module record initially set to null."
+  // [spec text] Step 2. "Set script's settings object to the environment
+  // settings object provided." [spec text] Note: "script's settings object"
+  // will be "modulator".
+  ScriptState* script_state = modulator->GetScriptState();
+  ScriptState::Scope scope(script_state);
+  v8::Isolate* isolate = script_state->GetIsolate();
+  ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
                                  "ModuleScript", "Create");
 
   // Delegate to Modulator::CompileModule to process Steps 3-5.
@@ -50,26 +50,48 @@
       source_text, base_url.GetString(), access_control_status, start_position,
       exception_state);
 
-  // CreateInternal processes Steps 7-13.
+  // CreateInternal processes Steps 8-13.
   // [nospec] We initialize the other ModuleScript members anyway by running
-  // Steps 7-13 before Step 6. In a case that compile failed, we will
+  // Steps 8-13 before Step 6. In a case that compile failed, we will
   // immediately turn the script into errored state. Thus the members will not
   // be used for the speced algorithms, but may be used from inspector.
   ModuleScript* script =
       CreateInternal(source_text, modulator, result, base_url, nonce,
                      parser_state, credentials_mode, start_position);
 
-  // Step 6. If result is a List of errors, then:
+  // Step 6. "If result is a List of errors, then:" [spec text]
   if (exception_state.HadException()) {
     DCHECK(result.IsNull());
 
-    // Step 6.1. Error script with errors[0].
+    // Step 6.1. "Error script with errors[0]." [spec text]
     v8::Local<v8::Value> error = exception_state.GetException();
     exception_state.ClearException();
-    script->SetErrorAndClearRecord(
-        ScriptValue(modulator->GetScriptState(), error));
+    script->SetErrorAndClearRecord(ScriptValue(script_state, error));
 
-    // Step 6.2. Return script.
+    // Step 6.2. "Return script." [spec text]
+    return script;
+  }
+
+  // Step 7. "For each string requested of record.[[RequestedModules]]:" [spec
+  // text]
+  for (const auto& requested :
+       modulator->ModuleRequestsFromScriptModule(result)) {
+    // Step 7.1. "Let url be the result of resolving a module specifier given
+    // module script and requested."[spec text] Step 7.2. "If url is failure:"
+    // [spec text]
+    // TODO(kouhei): Cache the url here instead of issuing
+    // ResolveModuleSpecifier later again in ModuleTreeLinker.
+    if (modulator->ResolveModuleSpecifier(requested, base_url).IsValid())
+      continue;
+
+    // Step 7.2.1. "Let error be a new TypeError exception." [spec text]
+    v8::Local<v8::Value> error = V8ThrowException::CreateTypeError(
+        isolate, "Failed to resolve module specifier '" + requested + "'");
+
+    // Step 7.2.2. "Set the parse error of script to error." [spec text]
+    script->SetErrorAndClearRecord(ScriptValue(script_state, error));
+
+    // Step 7.2.3. "Return script." [spec text]
     return script;
   }
 
@@ -99,7 +121,6 @@
     WebURLRequest::FetchCredentialsMode credentials_mode,
     const TextPosition& start_position) {
   // https://html.spec.whatwg.org/#creating-a-module-script
-  // Step 7. Set script's state to "uninstantiated".
   // Step 8. Set script's module record to result.
   // Step 9. Set script's base URL to the script base URL provided.
   // Step 10. Set script's cryptographic nonce to the cryptographic nonce
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
index 5ada705..fc32f24 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -1219,49 +1219,6 @@
   return 0;
 }
 
-static Node* PreviousNodeConsideringAtomicNodes(const Node& start) {
-  if (start.previousSibling()) {
-    Node* node = start.previousSibling();
-    while (!IsAtomicNode(node) && node->lastChild())
-      node = node->lastChild();
-    return node;
-  }
-  return start.parentNode();
-}
-
-static Node* NextNodeConsideringAtomicNodes(const Node& start) {
-  if (!IsAtomicNode(&start) && start.hasChildren())
-    return start.firstChild();
-  if (start.nextSibling())
-    return start.nextSibling();
-  const Node* node = &start;
-  while (node && !node->nextSibling())
-    node = node->parentNode();
-  if (node)
-    return node->nextSibling();
-  return nullptr;
-}
-
-Node* PreviousAtomicLeafNode(const Node& start) {
-  Node* node = PreviousNodeConsideringAtomicNodes(start);
-  while (node) {
-    if (IsAtomicNode(node))
-      return node;
-    node = PreviousNodeConsideringAtomicNodes(*node);
-  }
-  return nullptr;
-}
-
-Node* NextAtomicLeafNode(const Node& start) {
-  Node* node = NextNodeConsideringAtomicNodes(start);
-  while (node) {
-    if (IsAtomicNode(node))
-      return node;
-    node = NextNodeConsideringAtomicNodes(*node);
-  }
-  return nullptr;
-}
-
 // Returns the visible position at the beginning of a node
 VisiblePosition VisiblePositionBeforeNode(Node& node) {
   DCHECK(!NeedsLayoutTreeUpdate(node));
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.h b/third_party/WebKit/Source/core/editing/EditingUtilities.h
index b01cc28e..e97d873 100644
--- a/third_party/WebKit/Source/core/editing/EditingUtilities.h
+++ b/third_party/WebKit/Source/core/editing/EditingUtilities.h
@@ -134,14 +134,6 @@
 CORE_EXPORT Element* TableElementJustBefore(const VisiblePosition&);
 CORE_EXPORT Element* TableElementJustBefore(const VisiblePositionInFlatTree&);
 
-// Returns the next leaf node or nullptr if there are no more. Delivers leaf
-// nodes as if the whole DOM tree were a linear chain of its leaf nodes.
-Node* NextAtomicLeafNode(const Node& start);
-
-// Returns the previous leaf node or nullptr if there are no more. Delivers leaf
-// nodes as if the whole DOM tree were a linear chain of its leaf nodes.
-Node* PreviousAtomicLeafNode(const Node& start);
-
 template <typename Strategy>
 ContainerNode* ParentCrossingShadowBoundaries(const Node&);
 template <>
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
index 890cf5637..5a820f3 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
@@ -85,6 +85,53 @@
   return HighestEditableRoot(position);
 }
 
+Node* PreviousNodeConsideringAtomicNodes(const Node& start) {
+  if (start.previousSibling()) {
+    Node* node = start.previousSibling();
+    while (!IsAtomicNode(node) && node->lastChild())
+      node = node->lastChild();
+    return node;
+  }
+  return start.parentNode();
+}
+
+Node* NextNodeConsideringAtomicNodes(const Node& start) {
+  if (!IsAtomicNode(&start) && start.hasChildren())
+    return start.firstChild();
+  if (start.nextSibling())
+    return start.nextSibling();
+  const Node* node = &start;
+  while (node && !node->nextSibling())
+    node = node->parentNode();
+  if (node)
+    return node->nextSibling();
+  return nullptr;
+}
+
+// Returns the previous leaf node or nullptr if there are no more. Delivers leaf
+// nodes as if the whole DOM tree were a linear chain of its leaf nodes.
+Node* PreviousAtomicLeafNode(const Node& start) {
+  Node* node = PreviousNodeConsideringAtomicNodes(start);
+  while (node) {
+    if (IsAtomicNode(node))
+      return node;
+    node = PreviousNodeConsideringAtomicNodes(*node);
+  }
+  return nullptr;
+}
+
+// Returns the next leaf node or nullptr if there are no more. Delivers leaf
+// nodes as if the whole DOM tree were a linear chain of its leaf nodes.
+Node* NextAtomicLeafNode(const Node& start) {
+  Node* node = NextNodeConsideringAtomicNodes(start);
+  while (node) {
+    if (IsAtomicNode(node))
+      return node;
+    node = NextNodeConsideringAtomicNodes(*node);
+  }
+  return nullptr;
+}
+
 Node* PreviousLeafWithSameEditability(Node* node, EditableType editable_type) {
   const bool editable = HasEditableStyle(*node, editable_type);
   for (Node* runner = PreviousAtomicLeafNode(*node); runner;
@@ -212,6 +259,21 @@
                     visible_position);
 }
 
+Node* FindNodeInPreviousLine(const Node& start_node,
+                             const VisiblePosition& visible_position,
+                             EditableType editable_type) {
+  // TODO(editing-dev): We should make |PreviousLeafWithSameEditability()| to
+  // take |const Node&|.
+  for (Node* runner = PreviousLeafWithSameEditability(
+           const_cast<Node*>(&start_node), editable_type);
+       runner;
+       runner = PreviousLeafWithSameEditability(runner, editable_type)) {
+    if (!InSameLine(*runner, visible_position))
+      return runner;
+  }
+  return nullptr;
+}
+
 }  // namespace
 
 // FIXME: consolidate with code in previousLinePosition.
@@ -222,13 +284,8 @@
   DCHECK(visible_position.IsValid()) << visible_position;
   ContainerNode* highest_root =
       HighestEditableRoot(visible_position.DeepEquivalent(), editable_type);
-  Node* previous_node = PreviousLeafWithSameEditability(node, editable_type);
-
-  while (previous_node && InSameLine(*previous_node, visible_position)) {
-    previous_node =
-        PreviousLeafWithSameEditability(previous_node, editable_type);
-  }
-
+  Node* const previous_node =
+      FindNodeInPreviousLine(*node, visible_position, editable_type);
   for (Node* runner = previous_node; runner && !runner->IsShadowRoot();
        runner = PreviousLeafWithSameEditability(runner, editable_type)) {
     if (HighestEditableRoot(FirstPositionInOrBeforeNode(runner),
diff --git a/third_party/WebKit/Source/core/exported/BUILD.gn b/third_party/WebKit/Source/core/exported/BUILD.gn
index 619fdd4e..3bf6fd6 100644
--- a/third_party/WebKit/Source/core/exported/BUILD.gn
+++ b/third_party/WebKit/Source/core/exported/BUILD.gn
@@ -51,6 +51,8 @@
     "WebNode.cpp",
     "WebOptionElement.cpp",
     "WebPageImportanceSignals.cpp",
+    "WebPagePopupImpl.cpp",
+    "WebPagePopupImpl.h",
     "WebPerformance.cpp",
     "WebPluginContainerBase.cpp",
     "WebPluginContainerBase.h",
diff --git a/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImplTest.cpp b/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImplTest.cpp
index 31b45bb5..2506615 100644
--- a/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImplTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebAssociatedURLLoaderImplTest.cpp
@@ -32,6 +32,7 @@
 
 #include <memory>
 #include "core/frame/FrameTestHelpers.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "platform/wtf/PtrUtil.h"
@@ -237,7 +238,9 @@
     return !actual_response_.HttpHeaderField(header_name_string).IsEmpty();
   }
 
-  WebFrame* MainFrame() const { return helper_.WebView()->MainFrame(); }
+  WebLocalFrameBase* MainFrame() const {
+    return helper_.WebView()->MainFrameImpl();
+  }
 
  protected:
   String frame_file_path_;
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/WebPagePopupImpl.cpp
rename to third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
index 08bc2c9..335b16e 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
@@ -27,7 +27,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/WebPagePopupImpl.h"
+#include "core/exported/WebPagePopupImpl.h"
 
 #include "core/dom/AXObjectCacheBase.h"
 #include "core/dom/ContextFeatures.h"
@@ -40,6 +40,7 @@
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/Settings.h"
 #include "core/frame/VisualViewport.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/input/EventHandler.h"
 #include "core/layout/api/LayoutAPIShim.h"
 #include "core/layout/api/LayoutViewItem.h"
@@ -63,7 +64,6 @@
 #include "public/web/WebFrameClient.h"
 #include "public/web/WebViewClient.h"
 #include "public/web/WebWidgetClient.h"
-#include "web/WebLocalFrameImpl.h"
 
 namespace blink {
 
@@ -202,12 +202,12 @@
 
   void SetTouchAction(LocalFrame* frame, TouchAction touch_action) override {
     DCHECK(frame);
-    WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
-    WebFrameWidgetBase* widget = web_frame->LocalRoot()->FrameWidget();
+    WebLocalFrameBase* web_frame = WebLocalFrameBase::FromFrame(frame);
+    WebFrameWidget* widget = web_frame->LocalRoot()->FrameWidget();
     if (!widget)
       return;
 
-    if (WebWidgetClient* client = widget->Client())
+    if (WebWidgetClient* client = ToWebFrameWidgetBase(widget)->Client())
       client->SetTouchAction(static_cast<WebTouchAction>(touch_action));
   }
 
@@ -219,9 +219,10 @@
   void SetToolTip(LocalFrame&,
                   const String& tooltip_text,
                   TextDirection dir) override {
-    if (popup_->WidgetClient())
+    if (popup_->WidgetClient()) {
       popup_->WidgetClient()->SetToolTipText(tooltip_text,
                                              ToWebTextDirection(dir));
+    }
   }
 
   WebPagePopupImpl* popup_;
@@ -416,9 +417,10 @@
 }
 
 void WebPagePopupImpl::Paint(WebCanvas* canvas, const WebRect& rect) {
-  if (!closing_)
+  if (!closing_) {
     PageWidgetDelegate::Paint(*page_, canvas, rect,
                               *page_->DeprecatedLocalMainFrame());
+  }
 }
 
 void WebPagePopupImpl::Resize(const WebSize& new_size_in_viewport) {
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.h b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
similarity index 94%
rename from third_party/WebKit/Source/web/WebPagePopupImpl.h
rename to third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
index db26808..d9421d07 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
@@ -31,6 +31,7 @@
 #ifndef WebPagePopupImpl_h
 #define WebPagePopupImpl_h
 
+#include "core/CoreExport.h"
 #include "core/page/PagePopup.h"
 #include "core/page/PageWidgetDelegate.h"
 #include "platform/wtf/RefCounted.h"
@@ -51,10 +52,11 @@
 class WebViewBase;
 class LocalDOMWindow;
 
-class WebPagePopupImpl final : public WebPagePopup,
-                               public PageWidgetEventHandler,
-                               public PagePopup,
-                               public RefCounted<WebPagePopupImpl> {
+class CORE_EXPORT WebPagePopupImpl final
+    : public NON_EXPORTED_BASE(WebPagePopup),
+      public NON_EXPORTED_BASE(PageWidgetEventHandler),
+      public NON_EXPORTED_BASE(PagePopup),
+      public NON_EXPORTED_BASE(RefCounted<WebPagePopupImpl>) {
   WTF_MAKE_NONCOPYABLE(WebPagePopupImpl);
   USING_FAST_MALLOC(WebPagePopupImpl);
 
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
index bb30a26..c77d0e9 100644
--- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
@@ -133,19 +133,6 @@
   return WebPerformance();
 }
 
-void WebRemoteFrameImpl::Reload(WebFrameLoadType) {
-  NOTREACHED();
-}
-
-void WebRemoteFrameImpl::ReloadWithOverrideURL(const WebURL& override_url,
-                                               WebFrameLoadType) {
-  NOTREACHED();
-}
-
-void WebRemoteFrameImpl::LoadRequest(const WebURLRequest&) {
-  NOTREACHED();
-}
-
 void WebRemoteFrameImpl::StopLoading() {
   // TODO(dcheng,japhet): Calling this method should stop loads
   // in all subframes, both remote and local.
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h
index 5fcf354e..d0d4a76 100644
--- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.h
@@ -42,10 +42,6 @@
   WebView* View() const override;
   WebDocument GetDocument() const override;
   WebPerformance Performance() const override;
-  void Reload(WebFrameLoadType) override;
-  void ReloadWithOverrideURL(const WebURL& override_url,
-                             WebFrameLoadType) override;
-  void LoadRequest(const WebURLRequest&) override;
   void StopLoading() override;
   void EnableViewSourceMode(bool enable) override;
   bool IsViewSourceModeEnabled() const override;
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
index c1922e8..fb1b3b9 100644
--- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
@@ -97,7 +97,7 @@
 
 }  // namespace
 
-void LoadFrame(WebFrame* frame, const std::string& url) {
+void LoadFrame(WebLocalFrame* frame, const std::string& url) {
   WebURLRequest url_request(URLTestHelpers::ToKURL(url));
   frame->LoadRequest(url_request);
   PumpPendingRequestsForFrameToLoad(frame);
@@ -110,22 +110,21 @@
   PumpPendingRequestsForFrameToLoad(frame);
 }
 
-void LoadHistoryItem(WebFrame* frame,
+void LoadHistoryItem(WebLocalFrame* frame,
                      const WebHistoryItem& item,
                      WebHistoryLoadType load_type,
                      WebCachePolicy cache_policy) {
-  WebURLRequest request =
-      frame->ToWebLocalFrame()->RequestFromHistoryItem(item, cache_policy);
-  frame->ToWebLocalFrame()->Load(request, WebFrameLoadType::kBackForward, item);
+  WebURLRequest request = frame->RequestFromHistoryItem(item, cache_policy);
+  frame->Load(request, WebFrameLoadType::kBackForward, item);
   PumpPendingRequestsForFrameToLoad(frame);
 }
 
-void ReloadFrame(WebFrame* frame) {
+void ReloadFrame(WebLocalFrame* frame) {
   frame->Reload(WebFrameLoadType::kReload);
   PumpPendingRequestsForFrameToLoad(frame);
 }
 
-void ReloadFrameBypassingCache(WebFrame* frame) {
+void ReloadFrameBypassingCache(WebLocalFrame* frame) {
   frame->Reload(WebFrameLoadType::kReloadBypassingCache);
   PumpPendingRequestsForFrameToLoad(frame);
 }
@@ -294,7 +293,7 @@
   Initialize(web_frame_client, web_view_client, web_widget_client,
              update_settings_func);
 
-  LoadFrame(WebView()->MainFrame(), url);
+  LoadFrame(WebView()->MainFrameImpl(), url);
 
   return WebView();
 }
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.h b/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
index a3adb6d..179ce165 100644
--- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
+++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
@@ -66,22 +66,22 @@
 class TestWebWidgetClient;
 class TestWebViewClient;
 
-// Loads a url into the specified WebFrame for testing purposes. Pumps any
+// Loads a url into the specified WebLocalFrame for testing purposes. Pumps any
 // pending resource requests, as well as waiting for the threaded parser to
 // finish, before returning.
-void LoadFrame(WebFrame*, const std::string& url);
+void LoadFrame(WebLocalFrame*, const std::string& url);
 // Same as above, but for WebLocalFrame::LoadHTMLString().
 void LoadHTMLString(WebLocalFrame*,
                     const std::string& html,
                     const WebURL& base_url);
-// Same as above, but for WebFrame::loadHistoryItem().
-void LoadHistoryItem(WebFrame*,
+// Same as above, but for WebLocalFrame::RequestFromHistoryItem/Load.
+void LoadHistoryItem(WebLocalFrame*,
                      const WebHistoryItem&,
                      WebHistoryLoadType,
                      WebCachePolicy);
-// Same as above, but for WebFrame::reload().
-void ReloadFrame(WebFrame*);
-void ReloadFrameBypassingCache(WebFrame*);
+// Same as above, but for WebLocalFrame::Reload().
+void ReloadFrame(WebLocalFrame*);
+void ReloadFrameBypassingCache(WebLocalFrame*);
 
 // Pumps pending resource requests while waiting for a frame to load. Consider
 // using one of the above helper methods whenever possible.
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
index cccc8da..ad0859d0 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -78,11 +78,19 @@
         exception_state);
   }
 
+  void SetModuleRequests(const Vector<String>& requests) {
+    requests_ = requests;
+  }
+  Vector<String> ModuleRequestsFromScriptModule(ScriptModule) override {
+    return requests_;
+  }
+
   DECLARE_TRACE();
 
  private:
   RefPtr<ScriptState> script_state_;
   RefPtr<SecurityOrigin> security_origin_;
+  Vector<String> requests_;
 };
 
 DEFINE_TRACE(ModuleScriptLoaderTestModulator) {
@@ -101,13 +109,13 @@
   LocalFrame& GetFrame() { return dummy_page_holder_->GetFrame(); }
   Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
   ResourceFetcher* Fetcher() { return fetcher_.Get(); }
-  Modulator* GetModulator() { return modulator_.Get(); }
+  ModuleScriptLoaderTestModulator* GetModulator() { return modulator_.Get(); }
 
  protected:
   ScopedTestingPlatformSupport<FetchTestingPlatformSupport> platform_;
   std::unique_ptr<DummyPageHolder> dummy_page_holder_;
   Persistent<ResourceFetcher> fetcher_;
-  Persistent<Modulator> modulator_;
+  Persistent<ModuleScriptLoaderTestModulator> modulator_;
 };
 
 void ModuleScriptLoaderTest::SetUp() {
@@ -138,6 +146,24 @@
             ModuleInstantiationState::kUninstantiated);
 }
 
+TEST_F(ModuleScriptLoaderTest, InvalidSpecifier) {
+  ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
+  KURL url(KURL(),
+           "data:text/javascript,import 'invalid';export default 'grapes';");
+  ModuleScriptFetchRequest module_request(
+      url, String(), kParserInserted, WebURLRequest::kFetchCredentialsModeOmit);
+  TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
+  GetModulator()->SetModuleRequests({"invalid"});
+  registry->Fetch(module_request, ModuleGraphLevel::kTopLevelModuleFetch,
+                  GetModulator(), Fetcher(), client);
+
+  EXPECT_TRUE(client->WasNotifyFinished())
+      << "ModuleScriptLoader should finish synchronously.";
+  ASSERT_TRUE(client->GetModuleScript());
+  EXPECT_EQ(client->GetModuleScript()->State(),
+            ModuleInstantiationState::kErrored);
+}
+
 TEST_F(ModuleScriptLoaderTest, fetchInvalidURL) {
   ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
   KURL url;
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
index 2aeabe8..c5586d4 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -1342,9 +1342,11 @@
   DCHECK(element);
 
   if (!element->IsTextControl() && !HasEditableStyle(*element->ToNode())) {
-    // To fulfill the expectation of spatial-navigation/snav-input.html
+    // To fulfill the expectation of spatial-navigation/snav-textarea.html
     // we clear selection when spatnav moves focus away from a text-field.
-    FocusedFrame()->Selection().Clear();
+    // TODO(hugoh@opera.com): crbug.com/734552 remove Selection.Clear()
+    if (FocusedFrame())
+      FocusedFrame()->Selection().Clear();
   }
   element->focus(FocusParams(SelectionBehaviorOnFocus::kReset, type, nullptr));
   return true;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 1932c2b..9ae5c30 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -814,15 +814,6 @@
     SET_NESTED_VAR(rare_non_inherited_data_, grid_data_, grid_auto_flow_, flow);
   }
 
-  // mix-blend-mode
-  static WebBlendMode InitialBlendMode() { return WebBlendMode::kNormal; }
-  WebBlendMode BlendMode() const {
-    return static_cast<WebBlendMode>(rare_non_inherited_data_->blend_mode_);
-  }
-  void SetBlendMode(WebBlendMode v) {
-    rare_non_inherited_data_.Access()->blend_mode_ = static_cast<unsigned>(v);
-  }
-
   // offset-anchor
   static LengthPoint InitialOffsetAnchor() {
     return LengthPoint(Length(kAuto), Length(kAuto));
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js b/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
index e554026..63fa9511 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
@@ -252,8 +252,9 @@
     this._contentRequested = true;
 
     if (this.request) {
-      this._content = await this.request.requestContent();
-      this._contentEncoded = this.request.contentEncoded;
+      var contentData = await this.request.contentData();
+      this._content = contentData.content;
+      this._contentEncoded = contentData.encoded;
     } else {
       var response = await this._resourceTreeModel.target().pageAgent().invoke_getResourceContent(
           {frameId: this.frameId, url: this.url});
diff --git a/third_party/WebKit/Source/modules/exported/BUILD.gn b/third_party/WebKit/Source/modules/exported/BUILD.gn
index f58d39c..372abf31 100644
--- a/third_party/WebKit/Source/modules/exported/BUILD.gn
+++ b/third_party/WebKit/Source/modules/exported/BUILD.gn
@@ -14,6 +14,7 @@
     "WebEmbeddedWorkerImpl.h",
     "WebIDBKey.cpp",
     "WebIDBKeyRange.cpp",
+    "WebLeakDetector.cpp",
     "WebMediaDeviceChangeObserver.cpp",
     "WebMediaDevicesRequest.cpp",
     "WebMediaStreamRegistry.cpp",
diff --git a/third_party/WebKit/Source/web/WebLeakDetector.cpp b/third_party/WebKit/Source/modules/exported/WebLeakDetector.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/WebLeakDetector.cpp
rename to third_party/WebKit/Source/modules/exported/WebLeakDetector.cpp
index 86565a9..15e2ab58 100644
--- a/third_party/WebKit/Source/web/WebLeakDetector.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebLeakDetector.cpp
@@ -32,6 +32,7 @@
 
 #include "bindings/core/v8/V8GCController.h"
 #include "core/editing/spellcheck/SpellChecker.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/workers/InProcessWorkerMessagingProxy.h"
 #include "core/workers/WorkerThread.h"
 #include "modules/compositorworker/AbstractAnimationWorkletThread.h"
@@ -41,7 +42,6 @@
 #include "public/platform/Platform.h"
 #include "public/platform/WebThread.h"
 #include "public/web/WebFrame.h"
-#include "web/WebLocalFrameImpl.h"
 
 namespace blink {
 
@@ -100,7 +100,7 @@
   //
   // Stop the spellchecker to prevent this.
   if (frame->IsWebLocalFrame()) {
-    WebLocalFrameImpl* local_frame = ToWebLocalFrameImpl(frame);
+    WebLocalFrameBase* local_frame = ToWebLocalFrameBase(frame);
     local_frame->GetFrame()->GetSpellChecker().PrepareForLeakDetection();
   }
 
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index f087bc3..65cc2e9 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -58,11 +58,8 @@
     "WebFrameWidgetImpl.h",
     "WebHitTestResult.cpp",
     "WebKit.cpp",
-    "WebLeakDetector.cpp",
     "WebLocalFrameImpl.cpp",
     "WebLocalFrameImpl.h",
-    "WebPagePopupImpl.cpp",
-    "WebPagePopupImpl.h",
     "WebViewImpl.cpp",
     "WebViewImpl.h",
   ]
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
index 71d710b..f5bc097 100644
--- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -41,6 +41,7 @@
 #include "core/editing/InputMethodController.h"
 #include "core/editing/PlainTextRange.h"
 #include "core/events/WebInputEventConversion.h"
+#include "core/exported/WebPagePopupImpl.h"
 #include "core/exported/WebPluginContainerBase.h"
 #include "core/exported/WebRemoteFrameImpl.h"
 #include "core/exported/WebViewBase.h"
@@ -74,7 +75,6 @@
 #include "public/web/WebRange.h"
 #include "public/web/WebWidgetClient.h"
 #include "web/WebDevToolsAgentImpl.h"
-#include "web/WebPagePopupImpl.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h
index 08957dd..27ab5af4 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.h
+++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -33,6 +33,7 @@
 
 #include <memory>
 #include "core/editing/spellcheck/SpellCheckerClientImpl.h"
+#include "core/exported/WebPagePopupImpl.h"
 #include "core/exported/WebViewBase.h"
 #include "core/frame/ResizeViewportAnchor.h"
 #include "core/page/ChromeClient.h"
@@ -68,7 +69,6 @@
 #include "public/web/WebNavigationPolicy.h"
 #include "public/web/WebPageImportanceSignals.h"
 #include "web/WebExport.h"
-#include "web/WebPagePopupImpl.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp b/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
index 77d2535..f07e039 100644
--- a/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ActivityLoggerTest.cpp
@@ -80,7 +80,7 @@
                               ->MainFrameImpl()
                               ->GetFrame()
                               ->GetScriptController();
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 "about:blank");
   }
 
diff --git a/third_party/WebKit/Source/web/tests/CompositorWorkerTest.cpp b/third_party/WebKit/Source/web/tests/CompositorWorkerTest.cpp
index 02540fb..d60d92f 100644
--- a/third_party/WebKit/Source/web/tests/CompositorWorkerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/CompositorWorkerTest.cpp
@@ -53,7 +53,8 @@
   }
 
   void NavigateTo(const String& url) {
-    FrameTestHelpers::LoadFrame(GetWebView()->MainFrame(), url.Utf8().data());
+    FrameTestHelpers::LoadFrame(GetWebView()->MainFrameImpl(),
+                                url.Utf8().data());
   }
 
   void ForceFullCompositingUpdate() {
diff --git a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
index e8bf322..bb6ac93 100644
--- a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
@@ -115,7 +115,7 @@
   }
 
   void Serialize(const char* url) {
-    FrameTestHelpers::LoadFrame(helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(helper_.WebView()->MainFrameImpl(),
                                 KURL(base_url_, url).GetString().Utf8().data());
     FrameSerializer serializer(resources_, *this);
     Frame* frame = helper_.WebView()->MainFrameImpl()->GetFrame();
diff --git a/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp b/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
index d360af9a..d4c73b0b 100644
--- a/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ImeOnFocusTest.cpp
@@ -100,7 +100,7 @@
   WebViewBase* web_view =
       web_view_helper_.Initialize(nullptr, nullptr, &client);
   web_view->Resize(WebSize(800, 1200));
-  LoadFrame(web_view->MainFrame(), base_url_ + file_name);
+  LoadFrame(web_view->MainFrameImpl(), base_url_ + file_name);
   document_ = web_view_helper_.WebView()
                   ->MainFrameImpl()
                   ->GetDocument()
@@ -117,7 +117,8 @@
     RegisterMockedURLLoadFromBase(WebString::FromUTF8(base_url_),
                                   testing::WebTestDataPath(),
                                   WebString::FromUTF8(frame));
-    WebFrame* child_frame = web_view->MainFrame()->FirstChild();
+    WebLocalFrame* child_frame =
+        web_view->MainFrame()->FirstChild()->ToWebLocalFrame();
     LoadFrame(child_frame, base_url_ + frame);
   }
 
diff --git a/third_party/WebKit/Source/web/tests/MHTMLTest.cpp b/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
index ce9a833..42907457 100644
--- a/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
+++ b/third_party/WebKit/Source/web/tests/MHTMLTest.cpp
@@ -34,6 +34,7 @@
 #include "core/frame/FrameTestHelpers.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Location.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/page/Page.h"
 #include "platform/SerializedResource.h"
 #include "platform/SharedBuffer.h"
@@ -105,7 +106,7 @@
   }
 
   void LoadURLInTopFrame(const WebURL& url) {
-    FrameTestHelpers::LoadFrame(helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(helper_.WebView()->MainFrameImpl(),
                                 url.GetString().Utf8().data());
   }
 
diff --git a/third_party/WebKit/Source/web/tests/PrerenderingTest.cpp b/third_party/WebKit/Source/web/tests/PrerenderingTest.cpp
index cb75b42d..a8ea0ab 100644
--- a/third_party/WebKit/Source/web/tests/PrerenderingTest.cpp
+++ b/third_party/WebKit/Source/web/tests/PrerenderingTest.cpp
@@ -171,12 +171,12 @@
     web_view_helper_.Initialize();
     web_view_helper_.WebView()->SetPrerendererClient(&prerenderer_client_);
 
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 std::string(base_url) + file_name);
   }
 
   void NavigateAway() {
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 "about:blank");
   }
 
diff --git a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
index 9e97553..75ce3f1 100644
--- a/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScreenWakeLockTest.cpp
@@ -97,7 +97,7 @@
   }
 
   void LoadFrame() {
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 "http://example.com/foo.html");
     web_view_helper_.WebView()->UpdateAllLifecyclePhases();
   }
diff --git a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
index 5f166ce..5ac808b 100644
--- a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
+++ b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp
@@ -86,7 +86,7 @@
   }
 
   void NavigateTo(const std::string& url) {
-    FrameTestHelpers::LoadFrame(GetWebView()->MainFrame(), url);
+    FrameTestHelpers::LoadFrame(GetWebView()->MainFrameImpl(), url);
   }
 
   void LoadHTML(const std::string& html) {
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index e4c82c7..7bc48f4 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -136,7 +136,7 @@
   }
 
   void NavigateTo(const std::string& url) {
-    FrameTestHelpers::LoadFrame(WebViewImpl()->MainFrame(), url);
+    FrameTestHelpers::LoadFrame(WebViewImpl()->MainFrameImpl(), url);
   }
 
   void ForceFullCompositingUpdate() {
@@ -909,7 +909,7 @@
   item.SetVisualViewportScrollOffset(WebFloatPoint(100, 120));
   item.SetPageScaleFactor(2);
 
-  FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrame(), item,
+  FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrameImpl(), item,
                                     kWebHistoryDifferentDocumentLoad,
                                     WebCachePolicy::kUseProtocolCachePolicy);
 
@@ -940,7 +940,7 @@
   item.SetScrollOffset(WebPoint(120, 180));
   item.SetPageScaleFactor(2);
 
-  FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrame(), item,
+  FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrameImpl(), item,
                                     kWebHistoryDifferentDocumentLoad,
                                     WebCachePolicy::kUseProtocolCachePolicy);
 
@@ -2373,7 +2373,7 @@
   web_view_impl->ResizeWithBrowserControls(WebSize(page_width, page_height),
                                            browser_controls_height, true);
 
-  FrameTestHelpers::LoadFrame(web_view_impl->MainFrame(), "about:blank");
+  FrameTestHelpers::LoadFrame(web_view_impl->MainFrameImpl(), "about:blank");
   web_view_impl->UpdateAllLifecyclePhases();
 
   Document* document =
diff --git a/third_party/WebKit/Source/web/tests/WebDocumentSubresourceFilterTest.cpp b/third_party/WebKit/Source/web/tests/WebDocumentSubresourceFilterTest.cpp
index efa0915..57cd983a9 100644
--- a/third_party/WebKit/Source/web/tests/WebDocumentSubresourceFilterTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebDocumentSubresourceFilterTest.cpp
@@ -9,6 +9,7 @@
 
 #include "core/dom/Element.h"
 #include "core/frame/FrameTestHelpers.h"
+#include "core/frame/WebLocalFrameBase.h"
 #include "core/html/HTMLImageElement.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/testing/UnitTestHelpers.h"
@@ -106,7 +107,9 @@
   }
 
   const std::string& BaseURL() const { return base_url_; }
-  WebFrame* MainFrame() { return web_view_helper_.WebView()->MainFrame(); }
+  WebLocalFrameBase* MainFrame() {
+    return web_view_helper_.WebView()->MainFrameImpl();
+  }
   const std::vector<std::string>& QueriedSubresourcePaths() const {
     return client_.SubresourceFilter()->QueriedSubresourcePaths();
   }
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 76a6b11..c7b997a 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -483,7 +483,7 @@
 
   // If the frame navigates, pending scripts should be removed, but the callback
   // should always be ran.
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "bar.html");
   EXPECT_TRUE(callback_helper.DidComplete());
   EXPECT_EQ(String(), callback_helper.StringValue());
@@ -637,7 +637,7 @@
   web_view_helper.InitializeAndLoad(chrome_url_ + "history.html");
 
   // Try to run JS against the chrome-style URL.
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               "javascript:document.body.appendChild(document."
                               "createTextNode('Clobbered'))");
 
@@ -657,7 +657,7 @@
 
   // Try to run JS against the chrome-style URL after prohibiting it.
   WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs("chrome");
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               "javascript:document.body.appendChild(document."
                               "createTextNode('Clobbered'))");
 
@@ -679,11 +679,11 @@
 
   // Setting host to "hostname:" should be treated as "hostname:0".
   FrameTestHelpers::LoadFrame(
-      web_view_helper.WebView()->MainFrame(),
+      web_view_helper.WebView()->MainFrameImpl(),
       "javascript:location.host = 'internal.test:'; void 0;");
 
   FrameTestHelpers::LoadFrame(
-      web_view_helper.WebView()->MainFrame(),
+      web_view_helper.WebView()->MainFrameImpl(),
       "javascript:document.body.textContent = location.href; void 0;");
 
   std::string content =
@@ -700,11 +700,11 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + file_name);
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               "javascript:location.port = ''; void 0;");
 
   FrameTestHelpers::LoadFrame(
-      web_view_helper.WebView()->MainFrame(),
+      web_view_helper.WebView()->MainFrameImpl(),
       "javascript:document.body.textContent = location.href; void 0;");
 
   std::string content =
@@ -1274,7 +1274,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
   web_view_helper.WebView()->SetDefaultPageScaleLimits(0.25f, 5);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "fixed_layout.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1316,7 +1316,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
   web_view_helper.WebView()->SetDefaultPageScaleLimits(0.25f, 5);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "wide_document.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1514,7 +1514,7 @@
   web_view_helper.WebView()->GetSettings()->SetWideViewportQuirkEnabled(true);
   web_view_helper.WebView()->GetSettings()->SetUseWideViewport(true);
   FrameTestHelpers::LoadFrame(
-      web_view_helper.WebView()->MainFrame(),
+      web_view_helper.WebView()->MainFrameImpl(),
       base_url_ + "viewport/viewport-legacy-xhtmlmp.html");
 
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2059,7 +2059,7 @@
   web_view_helper.WebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "large-div.html");
   web_view_helper.WebView()->UpdateAllLifecyclePhases();
 
@@ -2113,7 +2113,7 @@
       true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "wide_document_width_viewport.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2142,7 +2142,7 @@
       true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport-height-1000.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2171,7 +2171,7 @@
       true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport/viewport-30.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2248,7 +2248,7 @@
   web_view_helper.WebView()->GetSettings()->SetWideViewportQuirkEnabled(true);
   web_view_helper.WebView()->GetSettings()->SetViewportMetaLayoutSizeQuirk(
       true);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport-zero-values.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2279,7 +2279,7 @@
 
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "body-overflow-hidden.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2300,7 +2300,7 @@
 
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "body-overflow-hidden-short.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2327,7 +2327,7 @@
   web_view_helper.WebView()
       ->GetSettings()
       ->SetIgnoreMainFrameOverflowHiddenQuirk(true);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "body-overflow-hidden.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2350,7 +2350,7 @@
   web_view_helper.WebView()->GetSettings()->SetViewportMetaZeroValuesQuirk(
       true);
   web_view_helper.WebView()->GetSettings()->SetWideViewportQuirkEnabled(true);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport-nonzero-values.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2461,7 +2461,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
   web_view_helper.WebView()->SetDefaultPageScaleLimits(0.25f, 5);
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "fixed_layout.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2954,7 +2954,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(640, 480));
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport-and-media.html");
 
   Document* document =
@@ -2980,7 +2980,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(800, 600));
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "viewport-lengths.html");
 
   LocalFrameView* view =
@@ -3207,7 +3207,7 @@
                              nullptr, &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(view_width, view_height));
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "large-div.html");
 
   LocalFrameView* view =
@@ -4197,11 +4197,11 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "form.html", &web_frame_client);
 
-  web_view_helper.WebView()->MainFrame()->Reload(
+  web_view_helper.WebView()->MainFrameImpl()->Reload(
       WebFrameLoadType::kReloadBypassingCache);
   // start another reload before request is delivered.
   FrameTestHelpers::ReloadFrameBypassingCache(
-      web_view_helper.WebView()->MainFrame());
+      web_view_helper.WebView()->MainFrameImpl());
 }
 
 class ClearScrollStateOnCommitWebFrameClient
@@ -4234,7 +4234,7 @@
   web_view_helper.WebView()->SetPageScaleFactor(kPageScaleFactor);
 
   // Reload the page and end up at the same url. State should not be propagated.
-  web_view_helper.WebView()->MainFrame()->ReloadWithOverrideURL(
+  web_view_helper.WebView()->MainFrameImpl()->ReloadWithOverrideURL(
       ToKURL(base_url_ + first_url), WebFrameLoadType::kReload);
   FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
       web_view_helper.WebView()->MainFrame());
@@ -4244,7 +4244,7 @@
   EXPECT_EQ(1.0f, web_view_helper.WebView()->PageScaleFactor());
 
   // Reload the page using the cache. State should not be propagated.
-  web_view_helper.WebView()->MainFrame()->ReloadWithOverrideURL(
+  web_view_helper.WebView()->MainFrameImpl()->ReloadWithOverrideURL(
       ToKURL(base_url_ + second_url), WebFrameLoadType::kReload);
   FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
       web_view_helper.WebView()->MainFrame());
@@ -4254,7 +4254,7 @@
   EXPECT_EQ(1.0f, web_view_helper.WebView()->PageScaleFactor());
 
   // Reload the page while bypassing the cache. State should not be propagated.
-  web_view_helper.WebView()->MainFrame()->ReloadWithOverrideURL(
+  web_view_helper.WebView()->MainFrameImpl()->ReloadWithOverrideURL(
       ToKURL(base_url_ + third_url), WebFrameLoadType::kReloadBypassingCache);
   FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
       web_view_helper.WebView()->MainFrame());
@@ -4272,10 +4272,10 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize();
   WebURLRequest request(ToKURL(base_url_ + "fixed_layout.html"));
-  web_view_helper.WebView()->MainFrame()->LoadRequest(request);
+  web_view_helper.WebView()->MainFrameImpl()->LoadRequest(request);
   // start reload before first request is delivered.
   FrameTestHelpers::ReloadFrameBypassingCache(
-      web_view_helper.WebView()->MainFrame());
+      web_view_helper.WebView()->MainFrameImpl());
 
   WebDataSource* data_source =
       web_view_helper.WebView()->MainFrameImpl()->DataSource();
@@ -4535,7 +4535,7 @@
 
   // Refresh, we should get two release notifications and two more create
   // notifications.
-  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrame());
+  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrameImpl());
   ASSERT_EQ(4u, create_notifications.size());
   ASSERT_EQ(2u, release_notifications.size());
 
@@ -4782,7 +4782,7 @@
   web_view_helper.InitializeAndLoad(base_url_ + "hello_world.html",
                                     &web_frame_client);
 
-  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrame());
+  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrameImpl());
 }
 
 class FindUpdateWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
@@ -5920,7 +5920,7 @@
   void RunTestWithNoSelection(const char* test_file) {
     RegisterMockedHttpURLLoad(test_file);
     web_view_helper_.WebView()->SetFocus(true);
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 base_url_ + test_file);
     web_view_helper_.WebView()->UpdateAllLifecyclePhases();
 
@@ -5937,7 +5937,7 @@
   void RunTest(const char* test_file) {
     RegisterMockedHttpURLLoad(test_file);
     web_view_helper_.WebView()->SetFocus(true);
-    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+    FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                                 base_url_ + test_file);
     web_view_helper_.WebView()->UpdateAllLifecyclePhases();
 
@@ -6441,7 +6441,7 @@
 
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad("about:blank", &web_frame_client);
-  WebFrame* frame = web_view_helper.WebView()->MainFrame();
+  WebLocalFrame* frame = web_view_helper.WebView()->MainFrameImpl();
 
   // Load a url as a history navigation that will return an error.
   // TestSubstituteDataWebFrameClient will start a SubstituteData load in
@@ -6968,7 +6968,7 @@
   EXPECT_EQ(0, web_frame_client.did_access_initial_document_);
 
   // Access the initial document from a javascript: URL.
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               "javascript:document.body.appendChild(document."
                               "createTextNode('Modified'))");
   EXPECT_EQ(1, web_frame_client.did_access_initial_document_);
@@ -7301,7 +7301,7 @@
   web_view_helper.InitializeAndLoad(base_url_ + "page_with_blank_iframe.html");
   WebLocalFrameBase* main_frame = web_view_helper.LocalMainFrame();
   const FrameLoader& main_frame_loader = main_frame->GetFrame()->Loader();
-  WebFrame* child_frame = main_frame->FirstChild();
+  WebLocalFrame* child_frame = main_frame->FirstChild()->ToWebLocalFrame();
   ASSERT_TRUE(child_frame);
 
   // Start a history navigation, then have a different frame commit a
@@ -7331,7 +7331,7 @@
   web_view_helper.InitializeAndLoad(base_url_ + "reload_post.html");
   WebLocalFrame* frame = web_view_helper.WebView()->MainFrameImpl();
 
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               "javascript:document.forms[0].submit()");
   // Pump requests one more time after the javascript URL has executed to
   // trigger the actual POST load request.
@@ -7524,7 +7524,7 @@
                                     &ConfigureLoadsImagesAutomatically);
 
   WebCache::Clear();
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "foo_with_image.html");
 
   // 2 images are requested, and each triggers 2 willSendRequest() calls,
@@ -7688,7 +7688,7 @@
   frame->ExecuteScript(WebScriptSource(WebString::FromUTF8(
       "document.body.appendChild(document.createElement('iframe'))")));
 
-  WebFrame* iframe = frame->FirstChild();
+  WebLocalFrame* iframe = frame->FirstChild()->ToWebLocalFrame();
   ASSERT_EQ(&client.ChildClient(), ToWebLocalFrameBase(iframe)->Client());
 
   std::string url1 = base_url_ + "history.html";
@@ -7712,7 +7712,7 @@
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad("about:blank", &client);
 
-  WebFrame* frame = web_view_helper.WebView()->MainFrame();
+  WebLocalFrame* frame = web_view_helper.WebView()->MainFrameImpl();
 
   std::string url1 = base_url_ + "history.html";
   FrameTestHelpers::LoadFrame(
@@ -7723,7 +7723,7 @@
           "';"
           "document.body.appendChild(f)");
 
-  WebFrame* iframe = frame->FirstChild();
+  WebLocalFrame* iframe = frame->FirstChild()->ToWebLocalFrame();
   EXPECT_EQ(url1, iframe->GetDocument().Url().GetString().Utf8());
 
   std::string url2 = base_url_ + "find.html";
@@ -7743,7 +7743,7 @@
                              nullptr, &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(100, 100));
-  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper.WebView()->MainFrameImpl(),
                               base_url_ + "non-scrollable.html");
 
   PaintLayerCompositor* compositor = web_view_helper.WebView()->Compositor();
@@ -7771,7 +7771,7 @@
 
   FrameTestHelpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize();
-  WebFrame* frame = web_view_helper.WebView()->MainFrame();
+  WebLocalFrame* frame = web_view_helper.WebView()->MainFrameImpl();
   const FrameLoader& main_frame_loader =
       web_view_helper.WebView()->MainFrameImpl()->GetFrame()->Loader();
   WebURLRequest request(ToKURL(url));
@@ -10668,7 +10668,7 @@
   helper.Initialize(&client);
   helper.Resize(WebSize(640, 480));
   FrameTestHelpers::LoadFrame(
-      helper.WebView()->MainFrame(),
+      helper.WebView()->MainFrameImpl(),
       base_url_ + "promote_img_in_viewport_priority.html");
 
   // Ensure the image in the viewport got promoted after the request was sent.
diff --git a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
index bd885d48..c2b64dad 100644
--- a/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebInputEventConversionTest.cpp
@@ -843,7 +843,7 @@
   FloatSize elastic_overscroll(10, -20);
   web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(),
                                 elastic_overscroll, 1.0f, 0.0f);
-  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrame());
+  FrameTestHelpers::ReloadFrame(web_view_helper.WebView()->MainFrameImpl());
   LocalFrameView* view = ToLocalFrame(web_view->GetPage()->MainFrame())->View();
 
   // Just elastic overscroll.
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index df90500..0d94a87 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -362,9 +362,9 @@
       KURL(ToKURL(base_url_), "non_existent.png"));
   std::string url = RegisterMockedHttpURLLoad("image-broken.html");
 
-  WebView* web_view = web_view_helper_.Initialize();
+  WebViewBase* web_view = web_view_helper_.Initialize();
   web_view->GetSettings()->SetLoadsImagesAutomatically(true);
-  LoadFrame(web_view->MainFrame(), url);
+  LoadFrame(web_view->MainFrameImpl(), url);
   web_view->Resize(WebSize(400, 400));
 
   std::string image_url = "http://www.test.com/non_existent.png";
@@ -379,9 +379,9 @@
       KURL(ToKURL(base_url_), "non_existent.png"));
   std::string url = RegisterMockedHttpURLLoad("input-image-broken.html");
 
-  WebView* web_view = web_view_helper_.Initialize();
+  WebViewBase* web_view = web_view_helper_.Initialize();
   web_view->GetSettings()->SetLoadsImagesAutomatically(true);
-  LoadFrame(web_view->MainFrame(), url);
+  LoadFrame(web_view->MainFrameImpl(), url);
   web_view->Resize(WebSize(400, 400));
 
   std::string image_url = "http://www.test.com/non_existent.png";
@@ -578,8 +578,8 @@
   std::string url = base_url_ + "specify_size.html?" + "50px" + ":" + "50px";
   URLTestHelpers::RegisterMockedURLLoad(
       ToKURL(url), testing::WebTestDataPath("specify_size.html"));
-  WebView* web_view = web_view_helper_.Initialize();
-  LoadFrame(web_view->MainFrame(), url);
+  WebViewBase* web_view = web_view_helper_.Initialize();
+  LoadFrame(web_view->MainFrameImpl(), url);
   web_view->Resize(WebSize(100, 100));
   WebPoint hit_point(75, 75);
 
@@ -633,8 +633,8 @@
 
 TEST_P(WebViewTest, HitTestResultForTapWithTapAreaPageScaleAndPan) {
   std::string url = RegisterMockedHttpURLLoad("hit_test.html");
-  WebView* web_view = web_view_helper_.Initialize();
-  LoadFrame(web_view->MainFrame(), url);
+  WebViewBase* web_view = web_view_helper_.Initialize();
+  LoadFrame(web_view->MainFrameImpl(), url);
   web_view->Resize(WebSize(100, 100));
   WebPoint hit_point(55, 55);
 
@@ -3201,7 +3201,7 @@
   RegisterMockedHttpURLLoad("add_frame_in_unload.html");
   web_view_helper_.InitializeAndLoad(base_url_ + "add_frame_in_unload.html",
                                      &frame_client);
-  FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                               "about:blank");
   EXPECT_EQ(0, frame_client.Count());
   web_view_helper_.Reset();
@@ -3213,7 +3213,7 @@
   RegisterMockedHttpURLLoad("add_frame_in_unload.html");
   web_view_helper_.InitializeAndLoad(
       base_url_ + "add_frame_in_unload_wrapper.html", &frame_client);
-  FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrame(),
+  FrameTestHelpers::LoadFrame(web_view_helper_.WebView()->MainFrameImpl(),
                               "about:blank");
   EXPECT_EQ(1, frame_client.Count());
   web_view_helper_.Reset();
@@ -3549,10 +3549,10 @@
 
 TEST_P(WebViewTest, AutoResizeSubtreeLayout) {
   std::string url = RegisterMockedHttpURLLoad("subtree-layout.html");
-  WebView* web_view = web_view_helper_.Initialize();
+  WebViewBase* web_view = web_view_helper_.Initialize();
 
   web_view->EnableAutoResizeMode(WebSize(200, 200), WebSize(200, 200));
-  LoadFrame(web_view->MainFrame(), url);
+  LoadFrame(web_view->MainFrameImpl(), url);
 
   LocalFrameView* frame_view =
       web_view_helper_.WebView()->MainFrameImpl()->GetFrameView();
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
index ddc16e1..4d6894af6 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
@@ -170,7 +170,7 @@
                 continue
 
             # File is being changed, detect if it's exportable.
-            if CHROMIUM_WPT_DIR in line:
+            if CHROMIUM_WPT_DIR in line and not line.endswith('-expected.txt'):
                 in_exportable_diff = True
                 filtered_patch.append(line)
             else:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py
index 58bea25..b9ace308 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit_unittest.py
@@ -22,3 +22,14 @@
         cl = GerritCL({'change_id': 1}, MockGerritAPI(None, None, None))
         actual_patch = cl.filter_transform_patch(sample_patch)
         self.assertEqual(actual_patch, expected_patch)
+
+    def test_filter_transform_patch_removes_baselines(self):
+        host = Host()
+        finder = PathFinder(host.filesystem)
+        resources_path = finder.path_from_tools_scripts('webkitpy', 'w3c', 'resources')
+        sample_patch = host.filesystem.read_text_file(host.filesystem.join(resources_path, 'sample2.patch'))
+        expected_patch = host.filesystem.read_text_file(host.filesystem.join(resources_path, 'expected2.patch'))
+
+        cl = GerritCL({'change_id': 1}, MockGerritAPI(None, None, None))
+        actual_patch = cl.filter_transform_patch(sample_patch)
+        self.assertEqual(actual_patch, expected_patch)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/expected2.patch b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/expected2.patch
new file mode 100644
index 0000000..506adfe
--- /dev/null
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/expected2.patch
@@ -0,0 +1,28 @@
+From 84953cf3aade2a112b9b9930d6fa72ece370cae5 Mon Sep 17 00:00:00 2001
+From: Jeff Carpenter <jeffcarp@chromium.org>
+Date: Mon, 19 Jun 2017 15:19:03 -0700
+Subject: [PATCH] wip
+
+---
+ .../service_worker/service_worker_client_utils.cc  | 47 ++++++++++++----------
+ third_party/WebKit/LayoutTests/TestExpectations    |  2 +
+ ...lients-matchall-client-types.https-expected.txt |  5 +++
+ .../clients-matchall-client-types.https.html       |  2 +-
+ 5 files changed, 34 insertions(+), 23 deletions(-)
+ create mode 100644 service-workers/service-worker/clients-matchall-client-types.https-expected.txt
+
+diff --git a/service-workers/service-worker/clients-matchall-client-types.https.html b/service-workers/service-worker/clients-matchall-client-types.https.html
+index 5bb50ec3db7f..6cd9ae3f68f9 100644
+--- a/service-workers/service-worker/clients-matchall-client-types.https.html
++++ b/service-workers/service-worker/clients-matchall-client-types.https.html
+@@ -38,7 +38,7 @@ function test_matchall(frame, expected, query_options) {
+       throw new Error(data);
+     }
+ 
+-    assert_equals(data.length, expected.length, 'result count');
++    assert_equals(data.length, expected.length, 'expecting ' + expected + ': result count');
+ 
+     for (var i = 0; i < data.length; ++i) {
+       assert_array_equals(data[i], expected[i]);
+-- 
+2.13.1.518.g3df882009-goog
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/sample2.patch b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/sample2.patch
new file mode 100644
index 0000000..f972a9c8
--- /dev/null
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/resources/sample2.patch
@@ -0,0 +1,184 @@
+From 84953cf3aade2a112b9b9930d6fa72ece370cae5 Mon Sep 17 00:00:00 2001
+From: Jeff Carpenter <jeffcarp@chromium.org>
+Date: Mon, 19 Jun 2017 15:19:03 -0700
+Subject: [PATCH] wip
+
+---
+ .../service_worker/service_worker_client_utils.cc  | 47 ++++++++++++----------
+ third_party/WebKit/LayoutTests/TestExpectations    |  2 +
+ ...lients-matchall-client-types.https-expected.txt |  5 +++
+ .../clients-matchall-client-types.https.html       |  2 +-
+ 5 files changed, 34 insertions(+), 23 deletions(-)
+ create mode 100644 third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https-expected.txt
+
+diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
+index 3a9318b83fc8..a8f677d5374a 100644
+--- a/content/browser/service_worker/service_worker_client_utils.cc
++++ b/content/browser/service_worker/service_worker_client_utils.cc
+@@ -106,6 +106,7 @@ class OpenURLObserver : public WebContentsObserver {
+ };
+ 
+ ServiceWorkerClientInfo GetWindowClientInfoOnUI(
++    const GURL& document_url,
+     int render_process_id,
+     int render_frame_id,
+     base::TimeTicks create_time,
+@@ -121,14 +122,15 @@ ServiceWorkerClientInfo GetWindowClientInfoOnUI(
+   // expecting.
+   return ServiceWorkerClientInfo(
+       client_uuid, render_frame_host->GetVisibilityState(),
+-      render_frame_host->IsFocused(), render_frame_host->GetLastCommittedURL(),
++      render_frame_host->IsFocused(), document_url,
+       render_frame_host->GetParent() ? REQUEST_CONTEXT_FRAME_TYPE_NESTED
+                                      : REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+       render_frame_host->frame_tree_node()->last_focus_time(), create_time,
+       blink::kWebServiceWorkerClientTypeWindow);
+ }
+ 
+-ServiceWorkerClientInfo FocusOnUI(int render_process_id,
++ServiceWorkerClientInfo FocusOnUI(const GURL& document_url,
++                                  int render_process_id,
+                                   int render_frame_id,
+                                   base::TimeTicks create_time,
+                                   const std::string& client_uuid) {
+@@ -153,8 +155,8 @@ ServiceWorkerClientInfo FocusOnUI(int render_process_id,
+   // Move the web contents to the foreground.
+   web_contents->Activate();
+ 
+-  return GetWindowClientInfoOnUI(render_process_id, render_frame_id,
+-                                 create_time, client_uuid);
++  return GetWindowClientInfoOnUI(document_url, render_process_id,
++                                 render_frame_id, create_time, client_uuid);
+ }
+ 
+ // This is only called for main frame navigations in OpenWindowOnUI().
+@@ -282,9 +284,9 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
+     }
+     BrowserThread::PostTaskAndReplyWithResult(
+         BrowserThread::UI, FROM_HERE,
+-        base::Bind(&GetWindowClientInfoOnUI, provider_host->process_id(),
+-                   provider_host->route_id(), provider_host->create_time(),
+-                   provider_host->client_uuid()),
++        base::Bind(&GetWindowClientInfoOnUI, provider_host->document_url(),
++                   provider_host->process_id(), provider_host->route_id(),
++                   provider_host->create_time(), provider_host->client_uuid()),
+         base::Bind(callback, SERVICE_WORKER_OK));
+     return;
+   }
+@@ -296,14 +298,14 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
+ 
+ void AddWindowClient(
+     ServiceWorkerProviderHost* host,
+-    std::vector<std::tuple<int, int, base::TimeTicks, std::string>>*
++    std::vector<std::tuple<GURL, int, int, base::TimeTicks, std::string>>*
+         client_info) {
+   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+   if (host->client_type() != blink::kWebServiceWorkerClientTypeWindow)
+     return;
+-  client_info->push_back(std::make_tuple(host->process_id(), host->frame_id(),
+-                                         host->create_time(),
+-                                         host->client_uuid()));
++  client_info->push_back(std::make_tuple(
++      host->document_url(), host->process_id(), host->frame_id(),
++      host->create_time(), host->client_uuid()));
+ }
+ 
+ void AddNonWindowClient(ServiceWorkerProviderHost* host,
+@@ -326,8 +328,9 @@ void AddNonWindowClient(ServiceWorkerProviderHost* host,
+ }
+ 
+ void OnGetWindowClientsOnUI(
+-    // The tuple contains process_id, frame_id, create_time, client_uuid.
+-    const std::vector<std::tuple<int, int, base::TimeTicks, std::string>>&
++    // The tuple contains document_url, process_id, frame_id, create_time,
++    // client_uuid.
++    const std::vector<std::tuple<GURL, int, int, base::TimeTicks, std::string>>&
+         clients_info,
+     const GURL& script_url,
+     const GetWindowClientsCallback& callback,
+@@ -336,7 +339,8 @@ void OnGetWindowClientsOnUI(
+ 
+   for (const auto& it : clients_info) {
+     ServiceWorkerClientInfo info = GetWindowClientInfoOnUI(
+-        std::get<0>(it), std::get<1>(it), std::get<2>(it), std::get<3>(it));
++        std::get<0>(it), std::get<1>(it), std::get<2>(it), std::get<3>(it),
++        std::get<4>(it));
+ 
+     // If the request to the provider_host returned an empty
+     // ServiceWorkerClientInfo, that means that it wasn't possible to associate
+@@ -427,7 +431,8 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
+   DCHECK(options.client_type == blink::kWebServiceWorkerClientTypeWindow ||
+          options.client_type == blink::kWebServiceWorkerClientTypeAll);
+ 
+-  std::vector<std::tuple<int, int, base::TimeTicks, std::string>> clients_info;
++  std::vector<std::tuple<GURL, int, int, base::TimeTicks, std::string>>
++      clients_info;
+   if (!options.include_uncontrolled) {
+     for (auto& controllee : controller->controllee_map())
+       AddWindowClient(controllee.second, &clients_info);
+@@ -461,9 +466,9 @@ void FocusWindowClient(ServiceWorkerProviderHost* provider_host,
+             provider_host->client_type());
+   BrowserThread::PostTaskAndReplyWithResult(
+       BrowserThread::UI, FROM_HERE,
+-      base::Bind(&FocusOnUI, provider_host->process_id(),
+-                 provider_host->frame_id(), provider_host->create_time(),
+-                 provider_host->client_uuid()),
++      base::Bind(&FocusOnUI, provider_host->document_url(),
++                 provider_host->process_id(), provider_host->frame_id(),
++                 provider_host->create_time(), provider_host->client_uuid()),
+       callback);
+ }
+ 
+@@ -509,9 +514,9 @@ void GetClient(ServiceWorkerProviderHost* provider_host,
+   if (client_type == blink::kWebServiceWorkerClientTypeWindow) {
+     BrowserThread::PostTaskAndReplyWithResult(
+         BrowserThread::UI, FROM_HERE,
+-        base::Bind(&GetWindowClientInfoOnUI, provider_host->process_id(),
+-                   provider_host->route_id(), provider_host->create_time(),
+-                   provider_host->client_uuid()),
++        base::Bind(&GetWindowClientInfoOnUI, provider_host->document_url(),
++                   provider_host->process_id(), provider_host->route_id(),
++                   provider_host->create_time(), provider_host->client_uuid()),
+         callback);
+     return;
+   }
+diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
+index 62d60ea92f56..9ecd97be8ced 100644
+--- a/third_party/WebKit/LayoutTests/TestExpectations
++++ b/third_party/WebKit/LayoutTests/TestExpectations
+@@ -2325,6 +2325,8 @@ crbug.com/675540 external/wpt/service-workers/service-worker/claim-with-redirect
+ crbug.com/675540 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/claim-with-redirect.https.html [ Skip ]
+ crbug.com/658997 external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html [ Skip ]
+ crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html [ Skip ]
++crbug.com/658997 external/wpt/service-workers/service-worker/clients-get-cross-origin.https.html [ Skip ]
++crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/clients-get-cross-origin.https.html [ Skip ]
+ crbug.com/658997 external/wpt/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ Skip ]
+ crbug.com/658997 virtual/off-main-thread-fetch/external/wpt/service-workers/service-worker/fetch-canvas-tainting-cache.https.html [ Skip ]
+ 
+diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https-expected.txt
+new file mode 100644
+index 000000000000..54af94b91aca
+--- /dev/null
++++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https-expected.txt
+@@ -0,0 +1,5 @@
++This is a testharness.js-based test.
++PASS Verify matchAll() with window client type 
++FAIL Verify matchAll() with {window, sharedworker, worker} client types assert_equals: expecting ,,https://web-platform.test:8444/service-workers/service-worker/resources/clients-matchall-client-types-dedicated-worker.js,worker,none: result count expected 1 but got 0
++Harness: the test ran to completion.
++
+diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html
+index 5bb50ec3db7f..6cd9ae3f68f9 100644
+--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html
++++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/clients-matchall-client-types.https.html
+@@ -38,7 +38,7 @@ function test_matchall(frame, expected, query_options) {
+       throw new Error(data);
+     }
+ 
+-    assert_equals(data.length, expected.length, 'result count');
++    assert_equals(data.length, expected.length, 'expecting ' + expected + ': result count');
+ 
+     for (var i = 0; i < data.length; ++i) {
+       assert_array_equals(data[i], expected[i]);
+-- 
+2.13.1.518.g3df882009-goog
+
diff --git a/third_party/WebKit/public/web/WebFrame.h b/third_party/WebKit/public/web/WebFrame.h
index 394d190b..54a433c7 100644
--- a/third_party/WebKit/public/web/WebFrame.h
+++ b/third_party/WebKit/public/web/WebFrame.h
@@ -210,19 +210,6 @@
   // TODO(clamy): Remove the reload, reloadWithOverrideURL, and loadRequest
   // functions once RenderFrame only calls WebLoadFrame::load.
 
-  // Reload the current document.
-  // Note: reload() and reloadWithOverrideURL() will be deprecated.
-  // Do not use these APIs any more, but use loadRequest() instead.
-  virtual void Reload(WebFrameLoadType) = 0;
-
-  // This is used for situations where we want to reload a different URL because
-  // of a redirect.
-  virtual void ReloadWithOverrideURL(const WebURL& override_url,
-                                     WebFrameLoadType) = 0;
-
-  // Load the given URL.
-  virtual void LoadRequest(const WebURLRequest&) = 0;
-
   // Stops any pending loads on the frame and its children.
   virtual void StopLoading() = 0;
 
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index ffaacf93..cc4d818 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -686,6 +686,19 @@
   // frame is attached to a document.
   virtual std::unique_ptr<WebURLLoader> CreateURLLoader() = 0;
 
+  // Reload the current document.
+  // Note: reload() and reloadWithOverrideURL() will be deprecated.
+  // Do not use these APIs any more, but use loadRequest() instead.
+  virtual void Reload(WebFrameLoadType) = 0;
+
+  // This is used for situations where we want to reload a different URL because
+  // of a redirect.
+  virtual void ReloadWithOverrideURL(const WebURL& override_url,
+                                     WebFrameLoadType) = 0;
+
+  // Load the given URL.
+  virtual void LoadRequest(const WebURLRequest&) = 0;
+
   // Geometry -----------------------------------------------------------------
 
   // If set to false, do not draw scrollbars on this frame's view.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 553e715..2de1cc0d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5654,6 +5654,7 @@
   <int value="31" label="Permission autoblocker data setting"/>
   <int value="32" label="Ads setting"/>
   <int value="33" label="Ads metadata"/>
+  <int value="34" label="Password protection setting"/>
 </enum>
 
 <enum name="ContentTypeParseableResult">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index bba1d6f..fb871b71 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -47276,7 +47276,8 @@
   <owner>dimich@chromium.org</owner>
   <summary>
     If the directory to store the SQLite database file does not exist, it is
-    created. This is recorded only if creation fails.
+    created. This is recorded every time the database is opened, even if the
+    directory already exists, in which case it's reported as FILE_OK.
   </summary>
 </histogram>
 
@@ -51813,8 +51814,8 @@
   </summary>
 </histogram>
 
-<histogram name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown"
-    units="count">
+<histogram base="true"
+    name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown" units="count">
   <owner>jialiul@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -93282,6 +93283,8 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="PasswordProtectionTrigger" separator=".">
+  <affected-histogram
+      name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown"/>
   <suffix name="PasswordFieldOnFocus"
       label="Password protection triggered by password field on focus event."/>
   <suffix name="ProtectedPasswordEntry"
diff --git a/ui/gfx/decorated_text.cc b/ui/gfx/decorated_text.cc
index 8c7a3299..f8b2fd1f 100644
--- a/ui/gfx/decorated_text.cc
+++ b/ui/gfx/decorated_text.cc
@@ -8,7 +8,7 @@
 
 DecoratedText::RangedAttribute::RangedAttribute(const gfx::Range& range,
                                                 const gfx::Font& font)
-    : range(range), font(font), strike(false), diagonal_strike(false) {}
+    : range(range), font(font), strike(false) {}
 
 DecoratedText::DecoratedText() {}
 
diff --git a/ui/gfx/decorated_text.h b/ui/gfx/decorated_text.h
index 2b80e54f..4904871 100644
--- a/ui/gfx/decorated_text.h
+++ b/ui/gfx/decorated_text.h
@@ -28,7 +28,6 @@
     Range range;
     Font font;
     bool strike;
-    bool diagonal_strike;
   };
 
   DecoratedText();
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 5cf7737..dfac164 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -60,8 +60,6 @@
 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
 // Fraction of the text size to use for a strike through or under-line.
 const SkScalar kLineThickness = (SK_Scalar1 / 18);
-// Fraction of the text size to use for a top margin of a diagonal strike.
-const SkScalar kDiagonalStrikeMarginOffset = (SK_Scalar1 / 4);
 
 // Invalid value of baseline.  Assigning this value to |baseline_| causes
 // re-calculation of baseline.
@@ -249,26 +247,15 @@
   canvas_skia_->drawPosText(&glyphs[0], byte_length, &pos[0], flags_);
 }
 
-void SkiaTextRenderer::DrawDecorations(int x, int y, int width, bool underline,
-                                       bool strike, bool diagonal_strike) {
+void SkiaTextRenderer::DrawDecorations(int x,
+                                       int y,
+                                       int width,
+                                       bool underline,
+                                       bool strike) {
   if (underline)
     DrawUnderline(x, y, width);
   if (strike)
     DrawStrike(x, y, width);
-  if (diagonal_strike) {
-    if (!diagonal_)
-      diagonal_.reset(new DiagonalStrike(canvas_, Point(x, y), flags_));
-    diagonal_->AddPiece(width, flags_.getColor());
-  } else if (diagonal_) {
-    EndDiagonalStrike();
-  }
-}
-
-void SkiaTextRenderer::EndDiagonalStrike() {
-  if (diagonal_) {
-    diagonal_->Draw();
-    diagonal_.reset();
-  }
 }
 
 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) {
@@ -294,51 +281,6 @@
   canvas_skia_->drawRect(r, flags_);
 }
 
-SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas,
-                                                 Point start,
-                                                 const cc::PaintFlags& flags)
-    : canvas_(canvas), start_(start), flags_(flags), total_length_(0) {}
-
-SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() {
-}
-
-void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) {
-  pieces_.push_back(Piece(length, color));
-  total_length_ += length;
-}
-
-void SkiaTextRenderer::DiagonalStrike::Draw() {
-  const SkScalar text_size = flags_.getTextSize();
-  const SkScalar offset = text_size * kDiagonalStrikeMarginOffset;
-  const int thickness = SkScalarCeilToInt(text_size * kLineThickness * 2);
-  const int height = SkScalarCeilToInt(text_size - offset);
-  const Point end = start_ + Vector2d(total_length_, -height);
-  const int clip_height = height + 2 * thickness;
-
-  flags_.setAntiAlias(true);
-  flags_.setStrokeWidth(SkIntToScalar(thickness));
-
-  const bool clipped = pieces_.size() > 1;
-  int x = start_.x();
-
-  for (size_t i = 0; i < pieces_.size(); ++i) {
-    flags_.setColor(pieces_[i].second);
-
-    if (clipped) {
-      canvas_->Save();
-      canvas_->ClipRect(
-          Rect(x, end.y() - thickness, pieces_[i].first, clip_height));
-    }
-
-    canvas_->DrawLine(start_, end, flags_);
-
-    if (clipped)
-      canvas_->Restore();
-
-    x += pieces_[i].first;
-  }
-}
-
 StyleIterator::StyleIterator(const BreakList<SkColor>& colors,
                              const BreakList<BaselineStyle>& baselines,
                              const BreakList<Font::Weight>& weights,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 5353be69..508f50ce 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -74,44 +74,22 @@
   // Draw underline and strike-through text decorations.
   // Based on |SkCanvas::DrawTextDecorations()| and constants from:
   //   third_party/skia/src/core/SkTextFormatParams.h
-  virtual void DrawDecorations(int x, int y, int width, bool underline,
-                               bool strike, bool diagonal_strike);
-  // Finishes any ongoing diagonal strike run.
-  void EndDiagonalStrike();
+  virtual void DrawDecorations(int x,
+                               int y,
+                               int width,
+                               bool underline,
+                               bool strike);
   void DrawUnderline(int x, int y, int width);
   void DrawStrike(int x, int y, int width) const;
 
  private:
   friend class test::RenderTextTestApi;
 
-  // Helper class to draw a diagonal line with multiple pieces of different
-  // lengths and colors; to support text selection appearances.
-  class DiagonalStrike {
-   public:
-    DiagonalStrike(Canvas* canvas, Point start, const cc::PaintFlags& flags);
-    ~DiagonalStrike();
-
-    void AddPiece(int length, SkColor color);
-    void Draw();
-
-   private:
-    typedef std::pair<int, SkColor> Piece;
-
-    Canvas* canvas_;
-    const Point start_;
-    cc::PaintFlags flags_;
-    int total_length_;
-    std::vector<Piece> pieces_;
-
-    DISALLOW_COPY_AND_ASSIGN(DiagonalStrike);
-  };
-
   Canvas* canvas_;
   cc::PaintCanvas* canvas_skia_;
   cc::PaintFlags flags_;
   SkScalar underline_thickness_;
   SkScalar underline_position_;
-  std::unique_ptr<DiagonalStrike> diagonal_;
 
   DISALLOW_COPY_AND_ASSIGN(SkiaTextRenderer);
 };
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index fe492c6..a51603a 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -654,7 +654,6 @@
       italic(false),
       weight(Font::Weight::NORMAL),
       strike(false),
-      diagonal_strike(false),
       underline(false) {}
 
 TextRunHarfBuzz::~TextRunHarfBuzz() {}
@@ -1322,15 +1321,12 @@
                    SkIntToScalar(origin.x()))
                 : positions[colored_glyphs.end() - glyphs_range.start()].x());
         renderer->DrawDecorations(start_x, origin.y(), end_x - start_x,
-                                  run.underline, run.strike,
-                                  run.diagonal_strike);
+                                  run.underline, run.strike);
       }
       preceding_segment_widths += SkFloatToScalar(segment.width());
     }
   }
 
-  renderer->EndDiagonalStrike();
-
   UndoCompositionAndSelectionStyles();
 }
 
@@ -1399,7 +1395,6 @@
     run->italic = style.style(ITALIC);
     run->baseline_type = style.baseline();
     run->strike = style.style(STRIKE);
-    run->diagonal_strike = style.style(DIAGONAL_STRIKE);
     run->underline = style.style(UNDERLINE);
     run->weight = style.weight();
     int32_t script_item_break = 0;
@@ -1726,7 +1721,6 @@
           run.font.Derive(0, style, run.weight));
 
       attribute.strike = run.strike;
-      attribute.diagonal_strike = run.diagonal_strike;
       decorated_text->attributes.push_back(attribute);
     }
   }
diff --git a/ui/gfx/render_text_harfbuzz.h b/ui/gfx/render_text_harfbuzz.h
index 3c31f51..f0b190f 100644
--- a/ui/gfx/render_text_harfbuzz.h
+++ b/ui/gfx/render_text_harfbuzz.h
@@ -86,7 +86,6 @@
   bool italic;
   Font::Weight weight;
   bool strike;
-  bool diagonal_strike;
   bool underline;
 
  private:
diff --git a/ui/gfx/render_text_mac.h b/ui/gfx/render_text_mac.h
index dc52f66..933592c 100644
--- a/ui/gfx/render_text_mac.h
+++ b/ui/gfx/render_text_mac.h
@@ -74,7 +74,6 @@
     SkColor foreground;
     bool underline;
     bool strike;
-    bool diagonal_strike;
 
     TextRun();
     TextRun(const TextRun& other) = delete;
diff --git a/ui/gfx/render_text_mac.mm b/ui/gfx/render_text_mac.mm
index eafd25a..6705817 100644
--- a/ui/gfx/render_text_mac.mm
+++ b/ui/gfx/render_text_mac.mm
@@ -260,10 +260,8 @@
     renderer->DrawPosText(&run.glyph_positions[0], &run.glyphs[0],
                           run.glyphs.size());
     renderer->DrawDecorations(run.origin.x(), run.origin.y(), run.width,
-                              run.underline, run.strike, run.diagonal_strike);
+                              run.underline, run.strike);
   }
-
-  renderer->EndDiagonalStrike();
 }
 
 RenderTextMac::TextRun::TextRun()
@@ -272,8 +270,7 @@
       width(0),
       foreground(SK_ColorBLACK),
       underline(false),
-      strike(false),
-      diagonal_strike(false) {}
+      strike(false) {}
 
 RenderTextMac::TextRun::TextRun(TextRun&& other) = default;
 
@@ -444,7 +441,7 @@
     }
 
     // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle
-    //                  this better. Also, support strike and diagonal_strike.
+    //                  this better. Also, support strike.
     CFDictionaryRef attributes = CTRunGetAttributes(ct_run);
     CTFontRef ct_font = base::mac::GetValueFromDictionary<CTFontRef>(
         attributes, kCTFontAttributeName);
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 2ec7e69..9317032 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -165,7 +165,6 @@
 enum {
   ITALIC_MASK = 1 << ITALIC,
   STRIKE_MASK = 1 << STRIKE,
-  DIAGONAL_STRIKE_MASK = 1 << DIAGONAL_STRIKE,
   UNDERLINE_MASK = 1 << UNDERLINE,
 };
 
@@ -251,7 +250,6 @@
   DecoratedText::RangedAttribute attributes(Range(index, index + 1),
                                             font_with_style);
   attributes.strike = style_mask & STRIKE_MASK;
-  attributes.diagonal_strike = style_mask & DIAGONAL_STRIKE_MASK;
   return attributes;
 }
 
@@ -280,7 +278,6 @@
     ASSERT_NE(actual.attributes.end(), actual_attr);
 
     EXPECT_EQ(expected_attr->strike, actual_attr->strike);
-    EXPECT_EQ(expected_attr->diagonal_strike, actual_attr->diagonal_strike);
     EXPECT_EQ(expected_attr->font.GetFontName(),
               actual_attr->font.GetFontName());
     EXPECT_EQ(expected_attr->font.GetFontSize(),
@@ -340,16 +337,13 @@
   };
 
   struct DecorationLog {
-    DecorationLog(int x, int y, int width, bool underline, bool strike,
-                  bool diagonal_strike)
-        : x(x), y(y), width(width), underline(underline), strike(strike),
-          diagonal_strike(diagonal_strike) {}
+    DecorationLog(int x, int y, int width, bool underline, bool strike)
+        : x(x), y(y), width(width), underline(underline), strike(strike) {}
     int x;
     int y;
     int width;
     bool underline;
     bool strike;
-    bool diagonal_strike;
   };
 
   explicit TestSkiaTextRenderer(Canvas* canvas)
@@ -387,12 +381,13 @@
     internal::SkiaTextRenderer::DrawPosText(pos, glyphs, glyph_count);
   }
 
-  void DrawDecorations(int x, int y, int width, bool underline, bool strike,
-                       bool diagonal_strike) override {
-    decoration_log_.push_back(
-        DecorationLog(x, y, width, underline, strike, diagonal_strike));
-    internal::SkiaTextRenderer::DrawDecorations(
-        x, y, width, underline, strike, diagonal_strike);
+  void DrawDecorations(int x,
+                       int y,
+                       int width,
+                       bool underline,
+                       bool strike) override {
+    decoration_log_.push_back(DecorationLog(x, y, width, underline, strike));
+    internal::SkiaTextRenderer::DrawDecorations(x, y, width, underline, strike);
   }
 
   std::vector<TextLog> text_log_;
@@ -1099,7 +1094,6 @@
   // slightly different width. This must be done after |SetText()|.
   render_text->ApplyWeight(Font::Weight::BOLD, Range(1, 20));
   render_text->ApplyStyle(ITALIC, true, Range(1, 20));
-  render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(1, 20));
   render_text->SetMultiline(true);
   render_text->SetElideBehavior(ELIDE_TAIL);
   render_text->SetMaxLines(3);
@@ -4201,7 +4195,6 @@
   render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(0, 3));
   render_text->ApplyStyle(UNDERLINE, true, Range(1, 5));
   render_text->ApplyStyle(ITALIC, true, Range(3, 8));
-  render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(5, 7));
   render_text->ApplyStyle(STRIKE, true, Range(1, 7));
   const int cursor_y = GetCursorYForTesting();
 
@@ -4225,9 +4218,9 @@
   DecoratedText expected_word_2;
   expected_word_2.text = ASCIIToUTF16("c");
   // Attributes for character 'c' at logical index |kWordTwoStartIndex|.
-  expected_word_2.attributes.push_back(CreateRangedAttribute(
-      font_spans, 0, kWordTwoStartIndex, Font::Weight::NORMAL,
-      ITALIC_MASK | DIAGONAL_STRIKE_MASK | STRIKE_MASK));
+  expected_word_2.attributes.push_back(
+      CreateRangedAttribute(font_spans, 0, kWordTwoStartIndex,
+                            Font::Weight::NORMAL, ITALIC_MASK | STRIKE_MASK));
   const Rect left_glyph_word_2 = render_text->GetCursorBounds(
       SelectionModel(kWordTwoStartIndex, CURSOR_FORWARD), false);
 
@@ -4286,7 +4279,6 @@
   render_text->ApplyWeight(Font::Weight::SEMIBOLD, Range(2, 3));
   render_text->ApplyStyle(UNDERLINE, true, Range(3, 6));
   render_text->ApplyStyle(ITALIC, true, Range(0, 3));
-  render_text->ApplyStyle(DIAGONAL_STRIKE, true, Range(0, 2));
   render_text->ApplyStyle(STRIKE, true, Range(2, 5));
   const int cursor_y = GetCursorYForTesting();
 
@@ -4298,8 +4290,7 @@
   expected_word_1.text = WideToUTF16(L"\x0634\x0632");
   // Attributes for characters at logical indices 1 and 2.
   expected_word_1.attributes.push_back(CreateRangedAttribute(
-      font_spans, 0, kWordOneStartIndex, Font::Weight::NORMAL,
-      ITALIC_MASK | DIAGONAL_STRIKE_MASK));
+      font_spans, 0, kWordOneStartIndex, Font::Weight::NORMAL, ITALIC_MASK));
   expected_word_1.attributes.push_back(
       CreateRangedAttribute(font_spans, 1, kWordOneStartIndex + 1,
                             Font::Weight::SEMIBOLD, ITALIC_MASK | STRIKE_MASK));
diff --git a/ui/gfx/text_constants.h b/ui/gfx/text_constants.h
index b63a05d..10c0340f 100644
--- a/ui/gfx/text_constants.h
+++ b/ui/gfx/text_constants.h
@@ -77,7 +77,6 @@
 enum TextStyle {
   ITALIC = 0,
   STRIKE,
-  DIAGONAL_STRIKE,
   UNDERLINE,
   NUM_TEXT_STYLES,
 };
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.cc b/ui/ozone/platform/drm/gpu/drm_buffer.cc
index 784549f..d511661b 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -107,10 +107,6 @@
   return fb_pixel_format_;
 }
 
-uint64_t DrmBuffer::GetFormatModifier() const {
-  return DRM_FORMAT_MOD_NONE;
-}
-
 uint32_t DrmBuffer::GetHandle() const {
   return handle_;
 }
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.h b/ui/ozone/platform/drm/gpu/drm_buffer.h
index dc6ed49..dd162198 100644
--- a/ui/ozone/platform/drm/gpu/drm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/drm_buffer.h
@@ -40,7 +40,6 @@
   uint32_t GetFramebufferPixelFormat() const override;
   uint32_t GetOpaqueFramebufferId() const override;
   uint32_t GetOpaqueFramebufferPixelFormat() const override;
-  uint64_t GetFormatModifier() const override;
   uint32_t GetHandle() const override;
   gfx::Size GetSize() const override;
   const DrmDevice* GetDrmDevice() const override;
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 6723874..dff2d96 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -83,6 +83,11 @@
   return planes_[index].size;
 }
 
+uint64_t GbmBuffer::GetFormatModifier(size_t index) const {
+  DCHECK_LT(index, planes_.size());
+  return planes_[index].modifier;
+}
+
 // TODO(reveman): This should not be needed once crbug.com/597932 is fixed,
 // as the size would be queried directly from the underlying bo.
 gfx::Size GbmBuffer::GetSize() const {
@@ -245,7 +250,7 @@
     }
     handle.planes.emplace_back(buffer_->GetStride(i), buffer_->GetOffset(i),
                                buffer_->GetSize(i),
-                               buffer_->GetFormatModifier());
+                               buffer_->GetFormatModifier(i));
   }
   return handle;
 }
@@ -278,7 +283,7 @@
 }
 
 uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const {
-  return buffer_->GetFormatModifier();
+  return buffer_->GetFormatModifier(plane);
 }
 
 gfx::BufferFormat GbmPixmap::GetBufferFormat() const {
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h
index da9b687..2823243 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -48,6 +48,7 @@
   int GetStride(size_t plane) const;
   int GetOffset(size_t plane) const;
   size_t GetSize(size_t plane) const;
+  uint64_t GetFormatModifier(size_t plane) const;
   gfx::Size GetSize() const override;
 
  private:
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
index 8af49a8d..7dac027 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
@@ -24,7 +24,6 @@
     framebuffer_pixel_format_ = format;
     opaque_framebuffer_pixel_format_ = GetFourCCFormatForOpaqueFramebuffer(
         GetBufferFormatFromFourCCFormat(format));
-    format_modifier_ = modifier;
 
     uint32_t handles[4] = {0};
     uint32_t strides[4] = {0};
@@ -87,11 +86,6 @@
   return opaque_framebuffer_pixel_format_;
 }
 
-uint64_t GbmBufferBase::GetFormatModifier() const {
-  DCHECK(framebuffer_);
-  return format_modifier_;
-}
-
 const DrmDevice* GbmBufferBase::GetDrmDevice() const {
   return drm_.get();
 }
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
index 48a15253..1aca1bb 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
@@ -32,7 +32,6 @@
   gfx::Size GetSize() const override;
   uint32_t GetFramebufferPixelFormat() const override;
   uint32_t GetOpaqueFramebufferPixelFormat() const override;
-  uint64_t GetFormatModifier() const override;
   const DrmDevice* GetDrmDevice() const override;
   bool RequiresGlFinish() const override;
 
@@ -55,7 +54,6 @@
   // otherwise it is set to 0.
   uint32_t opaque_framebuffer_ = 0;
   uint32_t opaque_framebuffer_pixel_format_ = 0;
-  uint64_t format_modifier_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(GbmBufferBase);
 };
diff --git a/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
index ec26ff8..409ac445 100644
--- a/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
@@ -18,7 +18,6 @@
     const std::vector<uint32_t>& crtcs,
     uint32_t planes_per_crtc) {
   const int kPlaneBaseId = 50;
-  const struct drm_format_modifier linear_modifier { 0x1, DRM_FORMAT_MOD_NONE };
   drm_ = drm;
   crtcs_ = crtcs;
   for (size_t crtc_idx = 0; crtc_idx < crtcs_.size(); crtc_idx++) {
@@ -26,7 +25,7 @@
       std::unique_ptr<HardwareDisplayPlane> plane(
           new HardwareDisplayPlane(kPlaneBaseId + i, 1 << crtc_idx));
       plane->Initialize(drm, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888),
-                        std::vector<drm_format_modifier>(1, linear_modifier),
+                        std::vector<drm_format_modifier>(),  // modifiers
                         false, true);
       planes_.push_back(std::move(plane));
     }
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
index fd15615..91c0082d 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
@@ -3,30 +3,16 @@
 // found in the LICENSE file.
 
 #include "ui/ozone/platform/drm/gpu/mock_scanout_buffer.h"
-#include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
 
 namespace ui {
 
-namespace {
-
-uint32_t g_current_framebuffer_id = 1;
-
-}  // namespace
-
-MockScanoutBuffer::MockScanoutBuffer(const gfx::Size& size,
-                                     uint32_t format,
-                                     uint64_t modifier,
-                                     const scoped_refptr<DrmDevice>& drm)
-    : size_(size),
-      format_(format),
-      modifier_(modifier),
-      id_(g_current_framebuffer_id++),
-      drm_(drm) {}
+MockScanoutBuffer::MockScanoutBuffer(const gfx::Size& size, uint32_t format)
+    : size_(size), format_(format) {}
 
 MockScanoutBuffer::~MockScanoutBuffer() {}
 
 uint32_t MockScanoutBuffer::GetFramebufferId() const {
-  return id_;
+  return 1;
 }
 
 uint32_t MockScanoutBuffer::GetOpaqueFramebufferId() const {
@@ -49,12 +35,8 @@
   return format_;
 }
 
-uint64_t MockScanoutBuffer::GetFormatModifier() const {
-  return modifier_;
-}
-
 const DrmDevice* MockScanoutBuffer::GetDrmDevice() const {
-  return drm_.get();
+  return nullptr;
 }
 
 bool MockScanoutBuffer::RequiresGlFinish() const {
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
index 33f5977..e2e9046 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
@@ -16,9 +16,7 @@
 class MockScanoutBuffer : public ScanoutBuffer {
  public:
   MockScanoutBuffer(const gfx::Size& size,
-                    uint32_t format = DRM_FORMAT_XRGB8888,
-                    uint64_t modifier = DRM_FORMAT_MOD_NONE,
-                    const scoped_refptr<DrmDevice>& drm = nullptr);
+                    uint32_t format = DRM_FORMAT_XRGB8888);
 
   // ScanoutBuffer:
   uint32_t GetFramebufferId() const override;
@@ -27,7 +25,6 @@
   gfx::Size GetSize() const override;
   uint32_t GetFramebufferPixelFormat() const override;
   uint32_t GetOpaqueFramebufferPixelFormat() const override;
-  uint64_t GetFormatModifier() const override;
   const DrmDevice* GetDrmDevice() const override;
   bool RequiresGlFinish() const override;
 
@@ -36,9 +33,6 @@
 
   gfx::Size size_;
   uint32_t format_;
-  uint64_t modifier_;
-  uint32_t id_;
-  scoped_refptr<DrmDevice> drm_;
 
   DISALLOW_COPY_AND_ASSIGN(MockScanoutBuffer);
 };
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc
index 08cd50a..ccf53a3 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc
@@ -17,19 +17,10 @@
     const scoped_refptr<DrmDevice>& drm,
     uint32_t format,
     const gfx::Size& size) {
-  return CreateWithModifier(drm, format, DRM_FORMAT_MOD_NONE, size);
-}
-
-scoped_refptr<ScanoutBuffer> MockScanoutBufferGenerator::CreateWithModifier(
-    const scoped_refptr<DrmDevice>& drm,
-    uint32_t format,
-    uint64_t modifier,
-    const gfx::Size& size) {
   if (allocation_failure_)
     return nullptr;
 
-  scoped_refptr<MockScanoutBuffer> buffer(
-      new MockScanoutBuffer(size, format, modifier, drm));
+  scoped_refptr<MockScanoutBuffer> buffer(new MockScanoutBuffer(size, format));
 
   return buffer;
 }
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h
index 2cb3161..fde77e3 100644
--- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h
+++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h
@@ -21,12 +21,6 @@
                                       uint32_t format,
                                       const gfx::Size& size) override;
 
-  scoped_refptr<ScanoutBuffer> CreateWithModifier(
-      const scoped_refptr<DrmDevice>& drm,
-      uint32_t format,
-      uint64_t modifier,
-      const gfx::Size& size);
-
   void set_allocation_failure(bool allocation_failure) {
     allocation_failure_ = allocation_failure;
   }
diff --git a/ui/ozone/platform/drm/gpu/scanout_buffer.h b/ui/ozone/platform/drm/gpu/scanout_buffer.h
index b6b58856..8a5cd13c 100644
--- a/ui/ozone/platform/drm/gpu/scanout_buffer.h
+++ b/ui/ozone/platform/drm/gpu/scanout_buffer.h
@@ -34,9 +34,6 @@
   // scanout when used as an opaque buffer.
   virtual uint32_t GetOpaqueFramebufferPixelFormat() const = 0;
 
-  // Returns format modifier for buffer.
-  virtual uint64_t GetFormatModifier() const = 0;
-
   // Handle for the buffer. This is received when allocating the buffer.
   virtual uint32_t GetHandle() const = 0;
 
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 899f0a5..5dd2666 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -348,30 +348,17 @@
     HardwareDisplayController* controller,
     const gfx::Rect& bounds) {
   DrmWindow* window = FindWindowAt(bounds);
-
-  gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
-  uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format);
-
   if (window) {
     const OverlayPlane* primary = window->GetLastModesetBuffer();
     const DrmDevice* drm = controller->GetAllocationDrmDevice().get();
     if (primary && primary->buffer->GetSize() == bounds.size() &&
-        primary->buffer->GetDrmDevice() == drm) {
-      // If the controller doesn't advertise modifiers, wont have a
-      // modifier either and we can reuse the buffer. Otherwise, check
-      // to see if the controller supports the buffers format
-      // modifier.
-      const auto& modifiers = controller->GetFormatModifiers(fourcc_format);
-      if (modifiers.empty())
-        return *primary;
-      for (const uint64_t modifier : modifiers) {
-        if (modifier == primary->buffer->GetFormatModifier())
-          return *primary;
-      }
-    }
+        primary->buffer->GetDrmDevice() == drm)
+      return *primary;
   }
 
+  gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
   scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice();
+  uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format);
   scoped_refptr<ScanoutBuffer> buffer =
       buffer_generator_->Create(drm, fourcc_format, bounds.size());
   if (!buffer) {
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index de0c717..c35b3808c 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -16,7 +16,7 @@
 #include "ui/ozone/platform/drm/gpu/drm_window.h"
 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
 #include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
-#include "ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h"
+#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h"
 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
 
 namespace {
@@ -51,10 +51,9 @@
   }
 
   void SetUp() override {
-    drm_ = new ui::MockDrmDevice(false, std::vector<uint32_t>(1, kPrimaryCrtc),
-                                 4 /* planes per crtc */);
+    drm_ = new ui::MockDrmDevice();
     device_manager_.reset(new ui::DrmDeviceManager(nullptr));
-    buffer_generator_.reset(new ui::MockScanoutBufferGenerator());
+    buffer_generator_.reset(new ui::MockDumbBufferGenerator());
     screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
   }
   void TearDown() override {
@@ -65,7 +64,7 @@
  protected:
   scoped_refptr<ui::MockDrmDevice> drm_;
   std::unique_ptr<ui::DrmDeviceManager> device_manager_;
-  std::unique_ptr<ui::MockScanoutBufferGenerator> buffer_generator_;
+  std::unique_ptr<ui::MockDumbBufferGenerator> buffer_generator_;
   std::unique_ptr<ui::ScreenManager> screen_manager_;
 
  private:
@@ -517,33 +516,3 @@
   window = screen_manager_->RemoveWindow(1);
   window->Shutdown();
 }
-
-TEST_F(ScreenManagerTest, RejectBufferWithIncompatibleModifiers) {
-  std::unique_ptr<ui::DrmWindow> window(
-      new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
-  window->Initialize(buffer_generator_.get());
-  window->SetBounds(GetPrimaryBounds());
-  scoped_refptr<ui::ScanoutBuffer> buffer =
-      buffer_generator_->CreateWithModifier(drm_, DRM_FORMAT_XRGB8888,
-                                            I915_FORMAT_MOD_X_TILED,
-                                            GetPrimaryBounds().size());
-
-  window->SchedulePageFlip(
-      std::vector<ui::OverlayPlane>(1, ui::OverlayPlane(buffer)),
-      base::Bind(&EmptySwapCallback));
-  screen_manager_->AddWindow(1, std::move(window));
-
-  screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
-  screen_manager_->ConfigureDisplayController(
-      drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
-      kDefaultMode);
-
-  // ScreenManager::GetModesetBuffer (called to get a buffer to
-  // modeset the new controller) should reject the buffer with
-  // I915_FORMAT_MOD_X_TILED modifier we created above and the two
-  // framebuffer IDs should be different.
-  EXPECT_NE(buffer->GetFramebufferId(), drm_->current_framebuffer());
-
-  window = screen_manager_->RemoveWindow(1);
-  window->Shutdown();
-}
diff --git a/ui/views/examples/multiline_example.cc b/ui/views/examples/multiline_example.cc
index 86be5fa..c92800f 100644
--- a/ui/views/examples/multiline_example.cc
+++ b/ui/views/examples/multiline_example.cc
@@ -97,8 +97,6 @@
     render_text_->SetText(new_contents);
     render_text_->SetColor(SK_ColorBLACK);
     render_text_->ApplyColor(0xFFFF0000, color_range);
-    render_text_->SetStyle(gfx::DIAGONAL_STRIKE, false);
-    render_text_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, color_range);
     render_text_->SetStyle(gfx::UNDERLINE, false);
     render_text_->ApplyStyle(gfx::UNDERLINE, true, color_range);
     render_text_->ApplyStyle(gfx::ITALIC, true, italic_range);
diff --git a/ui/views/examples/textfield_example.cc b/ui/views/examples/textfield_example.cc
index 98d8069..6f3c5f2 100644
--- a/ui/views/examples/textfield_example.cc
+++ b/ui/views/examples/textfield_example.cc
@@ -149,7 +149,6 @@
         const gfx::Range small_range(2 * fifth, 3 * fifth);
         name_->ApplyStyle(gfx::ITALIC, true, small_range);
         name_->ApplyStyle(gfx::UNDERLINE, false, small_range);
-        name_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, small_range);
         name_->ApplyColor(SK_ColorRED, small_range);
       }
     }