diff --git a/DEPS b/DEPS
index fa00e08..625ca46 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'efa9d34ccbdeb541a1fa77a678552df7a08531be',
+  'skia_revision': '65869fb64b56a4c59d74003c1fac5dffc8a8bf65',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'af5c10c843f4dcd6bf9d8aa9b41d45488b1946b1',
+  'v8_revision': '6cdbfc6d4134d4ae88b0c30b871789dac175916f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -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': 'da587fab57602e5e10c058e6e632df513fba0c93',
+  'pdfium_revision': '0fdeeb8175560ce6bbd8bbc14120cc75ea3a2d67',
   # 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': '2c95066149e88b00bea89ac25599cbd8f931de0d',
+  'catapult_revision': '7ca359550f9531a4c873dd071c73dcc7130eb537',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -408,7 +408,7 @@
 
     # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
     'src/third_party/chromite':
-      Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '0ab5a1cdaf3943aaa429ae74107aff1256c8899d',
+      Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bcd6eaeaf3259e990aa9382e2d4e225a2ce0c5f1',
 
     # Dependency of chromite.git and skia.
     'src/third_party/pyelftools':
diff --git a/WATCHLISTS b/WATCHLISTS
index 9639b0b..3e2f650 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -773,6 +773,7 @@
                   '|components/payments'\
                   '|third_party/WebKit/LayoutTests/payments/'\
                   '|third_party/WebKit/Source/modules/payments'\
+                  '|ios/chrome/browser/payments/'
     },
     'pepper_api': {
       'filepath': 'ppapi/api'\
diff --git a/ash/common/system/chromeos/session/logout_button_tray.cc b/ash/common/system/chromeos/session/logout_button_tray.cc
index 5a49bec..e3cfc2e 100644
--- a/ash/common/system/chromeos/session/logout_button_tray.cc
+++ b/ash/common/system/chromeos/session/logout_button_tray.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "ash/common/material_design/material_design_controller.h"
+#include "ash/common/shelf/wm_shelf_util.h"
 #include "ash/common/system/chromeos/session/logout_confirmation_controller.h"
 #include "ash/common/system/tray/system_tray_controller.h"
 #include "ash/common/system/tray/system_tray_notifier.h"
@@ -189,7 +190,7 @@
   const int button_size = MaterialDesignController::IsShelfMaterial()
                               ? kTrayItemSize
                               : GetTrayConstant(TRAY_ITEM_HEIGHT_LEGACY);
-  if (alignment == SHELF_ALIGNMENT_BOTTOM) {
+  if (IsHorizontalAlignment(alignment)) {
     button_->SetText(title);
     button_->SetImage(views::LabelButton::STATE_NORMAL, gfx::ImageSkia());
     button_->SetMinSize(gfx::Size(0, button_size));
diff --git a/ash/common/system/date/tray_date.cc b/ash/common/system/date/tray_date.cc
index 3b1a67e..48d0cd1 100644
--- a/ash/common/system/date/tray_date.cc
+++ b/ash/common/system/date/tray_date.cc
@@ -54,7 +54,7 @@
 views::View* TrayDate::CreateTrayView(LoginStatus status) {
   CHECK(time_tray_ == NULL);
   tray::TimeView::ClockLayout clock_layout =
-      system_tray()->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM
+      IsHorizontalAlignment(system_tray()->shelf_alignment())
           ? tray::TimeView::ClockLayout::HORIZONTAL_CLOCK
           : tray::TimeView::ClockLayout::VERTICAL_CLOCK;
   time_tray_ = new tray::TimeView(clock_layout);
diff --git a/ash/common/system/date/tray_system_info.cc b/ash/common/system/date/tray_system_info.cc
index 87e9c74..f4c7a97 100644
--- a/ash/common/system/date/tray_system_info.cc
+++ b/ash/common/system/date/tray_system_info.cc
@@ -48,7 +48,7 @@
 views::View* TraySystemInfo::CreateTrayView(LoginStatus status) {
   CHECK(tray_view_ == nullptr);
   tray::TimeView::ClockLayout clock_layout =
-      system_tray()->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM
+      IsHorizontalAlignment(system_tray()->shelf_alignment())
           ? tray::TimeView::ClockLayout::HORIZONTAL_CLOCK
           : tray::TimeView::ClockLayout::VERTICAL_CLOCK;
   tray_view_ = new tray::TimeView(clock_layout);
diff --git a/ash/common/system/web_notification/web_notification_tray.cc b/ash/common/system/web_notification/web_notification_tray.cc
index b681403..756f5fe 100644
--- a/ash/common/system/web_notification/web_notification_tray.cc
+++ b/ash/common/system/web_notification/web_notification_tray.cc
@@ -379,7 +379,7 @@
   // For vertical shelf alignments, anchor to the WebNotificationTray, but for
   // horizontal (i.e. bottom) shelves, anchor to the system tray.
   TrayBackgroundView* anchor_tray = this;
-  if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
+  if (IsHorizontalAlignment(shelf_alignment())) {
     anchor_tray = WmShelf::ForWindow(status_area_window_)
                       ->GetStatusAreaWidget()
                       ->system_tray();
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h
index 99cbef4..66b278f 100644
--- a/base/numerics/safe_conversions.h
+++ b/base/numerics/safe_conversions.h
@@ -110,35 +110,35 @@
 // that the specified numeric conversion will saturate by default rather than
 // overflow or underflow, and NaN assignment to an integral will return 0.
 // All boundary condition behaviors can be overriden with a custom handler.
-template <template <typename>
-          class SaturationHandler = SaturatedCastDefaultHandler,
-          typename Dst,
-          typename Src>
-constexpr Dst saturated_cast_impl(const Src value,
-                                  const RangeConstraint constraint) {
-  return constraint.IsValid()
-             ? static_cast<Dst>(value)
-             : (constraint.IsOverflow()
-                    ? SaturationHandler<Dst>::HandleOverflow()
-                    // Skip this check for integral Src, which cannot be NaN.
-                    : (std::is_integral<Src>::value || constraint.IsUnderflow()
-                           ? SaturationHandler<Dst>::HandleUnderflow()
-                           : SaturationHandler<Dst>::HandleNaN()));
-}
-
-// saturated_cast<> is analogous to static_cast<> for numeric types, except
-// that the specified numeric conversion will saturate by default rather than
-// overflow or underflow, and NaN assignment to an integral will return 0.
-// All boundary condition behaviors can be overriden with a custom handler.
 template <typename Dst,
           template <typename>
           class SaturationHandler = SaturatedCastDefaultHandler,
           typename Src>
 constexpr Dst saturated_cast(Src value) {
+  static_assert(
+      SaturationHandler<Dst>::lowest() < SaturationHandler<Dst>::max(), "");
+  // While this looks like a lot of code, it's all constexpr and all but
+  // one variable are compile-time constants (enforced by a static_assert).
+  // So, it should evaluate to the minimum number of comparisons required
+  // for the range check, which is 0-3, depending on the exact source and
+  // destination types, and whatever custom range is specified.
   using SrcType = typename UnderlyingType<Src>::type;
-  return saturated_cast_impl<SaturationHandler, Dst>(
-      static_cast<SrcType>(value),
-      DstRangeRelationToSrcRange<Dst, SaturationHandler, SrcType>(value));
+  return IsGreaterOrEqual<SrcType, Dst>::Test(
+             value, NarrowingRange<Dst, SrcType, SaturationHandler>::lowest())
+             ? (IsLessOrEqual<SrcType, Dst>::Test(
+                    value,
+                    NarrowingRange<Dst, SrcType, SaturationHandler>::max())
+                    ? static_cast<Dst>(value)
+                    : SaturationHandler<Dst>::HandleOverflow())
+             // This last branch is a little confusing. It's specifically to
+             // catch NaN when converting from float to integral.
+             : (std::is_integral<SrcType>::value ||
+                        std::is_floating_point<Dst>::value ||
+                        IsLessOrEqual<SrcType, Dst>::Test(
+                            value, NarrowingRange<Dst, SrcType,
+                                                  SaturationHandler>::max())
+                    ? SaturationHandler<Dst>::HandleUnderflow()
+                    : SaturationHandler<Dst>::HandleNaN());
 }
 
 // strict_cast<> is analogous to static_cast<> for numeric types, except that
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h
index fd0064dca..5ef3321 100644
--- a/base/numerics/safe_conversions_impl.h
+++ b/base/numerics/safe_conversions_impl.h
@@ -166,38 +166,29 @@
   static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
 };
 
-enum RangeConstraintEnum {
-  RANGE_VALID = 0x0,      // Value can be represented by the destination type.
-  RANGE_OVERFLOW = 0x1,   // Value would overflow.
-  RANGE_UNDERFLOW = 0x2,  // Value would underflow.
+enum RangeConstraint {
+  RANGE_VALID = 0x0,  // Value can be represented by the destination type.
+  RANGE_UNDERFLOW = 0x1,  // Value would overflow.
+  RANGE_OVERFLOW = 0x2,  // Value would underflow.
   RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW  // Invalid (i.e. NaN).
 };
 
-// This class wraps the range constraints as separate booleans so the compiler
-// can identify constants and eliminate unused code paths.
-class RangeConstraint {
- public:
-  constexpr RangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound)
-      : is_overflow_(!is_in_upper_bound), is_underflow_(!is_in_lower_bound) {}
-  constexpr RangeConstraint() : is_overflow_(0), is_underflow_(0) {}
-  constexpr bool IsValid() const { return !is_overflow_ && !is_underflow_; }
-  constexpr bool IsInvalid() const { return is_overflow_ && is_underflow_; }
-  constexpr bool IsOverflow() const { return is_overflow_ && !is_underflow_; }
-  constexpr bool IsUnderflow() const { return !is_overflow_ && is_underflow_; }
+// Helper function for coercing an int back to a RangeContraint.
+constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint) {
+  // TODO(jschuh): Once we get full C++14 support we want this
+  // assert(integer_range_constraint >= RANGE_VALID &&
+  //        integer_range_constraint <= RANGE_INVALID)
+  return static_cast<RangeConstraint>(integer_range_constraint);
+}
 
-  // These are some wrappers to make the tests a bit cleaner.
-  constexpr operator RangeConstraintEnum() const {
-    return static_cast<RangeConstraintEnum>(
-        static_cast<int>(is_overflow_) | static_cast<int>(is_underflow_) << 1);
-  }
-  constexpr bool operator==(const RangeConstraintEnum rhs) const {
-    return rhs == static_cast<RangeConstraintEnum>(*this);
-  }
-
- private:
-  const bool is_overflow_;
-  const bool is_underflow_;
-};
+// This function creates a RangeConstraint from an upper and lower bound
+// check by taking advantage of the fact that only NaN can be out of range in
+// both directions at once.
+constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound,
+                                                    bool is_in_lower_bound) {
+  return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
+                            (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
+}
 
 // The following helper template addresses a corner case in range checks for
 // conversion from a floating-point type to an integral type of smaller range
@@ -220,9 +211,11 @@
 // To fix this bug we manually truncate the maximum value when the destination
 // type is an integral of larger precision than the source floating-point type,
 // such that the resulting maximum is represented exactly as a floating point.
-template <typename Dst, typename Src, template <typename> class Bounds>
+template <typename Dst,
+          typename Src,
+          template <typename> class Bounds = std::numeric_limits>
 struct NarrowingRange {
-  using SrcLimits = std::numeric_limits<Src>;
+  using SrcLimits = typename std::numeric_limits<Src>;
   using DstLimits = typename std::numeric_limits<Dst>;
 
   // Computes the mask required to make an accurate comparison between types.
@@ -260,7 +253,6 @@
 
 template <typename Dst,
           typename Src,
-          template <typename> class Bounds,
           IntegerRepresentation DstSign = std::is_signed<Dst>::value
                                               ? INTEGER_REPRESENTATION_SIGNED
                                               : INTEGER_REPRESENTATION_UNSIGNED,
@@ -275,112 +267,83 @@
 // split it into checks based on signedness to avoid confusing casts and
 // compiler warnings on signed an unsigned comparisons.
 
-// Same sign narrowing: The range is contained for normal limits.
+// Dst range is statically determined to contain Src: Nothing to check.
 template <typename Dst,
           typename Src,
-          template <typename> class Bounds,
           IntegerRepresentation DstSign,
           IntegerRepresentation SrcSign>
 struct DstRangeRelationToSrcRangeImpl<Dst,
                                       Src,
-                                      Bounds,
                                       DstSign,
                                       SrcSign,
                                       NUMERIC_RANGE_CONTAINED> {
-  static constexpr RangeConstraint Check(Src value) {
-    using SrcLimits = std::numeric_limits<Src>;
-    using DstLimits = NarrowingRange<Dst, Src, Bounds>;
-    return RangeConstraint(
-        static_cast<Dst>(SrcLimits::max()) <= DstLimits::max() ||
-            static_cast<Dst>(value) <= DstLimits::max(),
-        static_cast<Dst>(SrcLimits::lowest()) >= DstLimits::lowest() ||
-            static_cast<Dst>(value) >= DstLimits::lowest());
-  }
+  static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; }
 };
 
 // Signed to signed narrowing: Both the upper and lower boundaries may be
-// exceeded for standard limits.
-template <typename Dst, typename Src, template <typename> class Bounds>
+// exceeded.
+template <typename Dst, typename Src>
 struct DstRangeRelationToSrcRangeImpl<Dst,
                                       Src,
-                                      Bounds,
                                       INTEGER_REPRESENTATION_SIGNED,
                                       INTEGER_REPRESENTATION_SIGNED,
                                       NUMERIC_RANGE_NOT_CONTAINED> {
   static constexpr RangeConstraint Check(Src value) {
-    using DstLimits = NarrowingRange<Dst, Src, Bounds>;
-    return RangeConstraint(value <= DstLimits::max(),
-                           value >= DstLimits::lowest());
+    return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
+                              (value >= NarrowingRange<Dst, Src>::lowest()));
   }
 };
 
-// Unsigned to unsigned narrowing: Only the upper bound can be exceeded for
-// standard limits.
-template <typename Dst, typename Src, template <typename> class Bounds>
+// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
+template <typename Dst, typename Src>
 struct DstRangeRelationToSrcRangeImpl<Dst,
                                       Src,
-                                      Bounds,
                                       INTEGER_REPRESENTATION_UNSIGNED,
                                       INTEGER_REPRESENTATION_UNSIGNED,
                                       NUMERIC_RANGE_NOT_CONTAINED> {
   static constexpr RangeConstraint Check(Src value) {
-    using DstLimits = NarrowingRange<Dst, Src, Bounds>;
-    return RangeConstraint(
-        value <= DstLimits::max(),
-        DstLimits::lowest() == Dst(0) || value >= DstLimits::lowest());
+    return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
   }
 };
 
-// Unsigned to signed: Only the upper bound can be exceeded for standard limits.
-template <typename Dst, typename Src, template <typename> class Bounds>
+// Unsigned to signed: The upper boundary may be exceeded.
+template <typename Dst, typename Src>
 struct DstRangeRelationToSrcRangeImpl<Dst,
                                       Src,
-                                      Bounds,
                                       INTEGER_REPRESENTATION_SIGNED,
                                       INTEGER_REPRESENTATION_UNSIGNED,
                                       NUMERIC_RANGE_NOT_CONTAINED> {
   static constexpr RangeConstraint Check(Src value) {
-    using DstLimits = NarrowingRange<Dst, Src, Bounds>;
-    using Promotion = decltype(Src() + Dst());
-    return RangeConstraint(static_cast<Promotion>(value) <=
-                               static_cast<Promotion>(DstLimits::max()),
-                           DstLimits::lowest() <= Dst(0) ||
-                               static_cast<Promotion>(value) >=
-                                   static_cast<Promotion>(DstLimits::lowest()));
+    return IntegerBitsPlusSign<Dst>::value > IntegerBitsPlusSign<Src>::value
+               ? RANGE_VALID
+               : GetRangeConstraint(
+                     value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+                     true);
   }
 };
 
 // Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
-// and any negative value exceeds the lower boundary for standard limits.
-template <typename Dst, typename Src, template <typename> class Bounds>
+// and any negative value exceeds the lower boundary.
+template <typename Dst, typename Src>
 struct DstRangeRelationToSrcRangeImpl<Dst,
                                       Src,
-                                      Bounds,
                                       INTEGER_REPRESENTATION_UNSIGNED,
                                       INTEGER_REPRESENTATION_SIGNED,
                                       NUMERIC_RANGE_NOT_CONTAINED> {
   static constexpr RangeConstraint Check(Src value) {
-    using SrcLimits = std::numeric_limits<Src>;
-    using DstLimits = NarrowingRange<Dst, Src, Bounds>;
-    using Promotion = decltype(Src() + Dst());
-    return RangeConstraint(
-        static_cast<Promotion>(SrcLimits::max()) <=
-                static_cast<Promotion>(DstLimits::max()) ||
-            static_cast<Promotion>(value) <=
-                static_cast<Promotion>(DstLimits::max()),
-        value >= Src(0) && (DstLimits::lowest() == 0 ||
-                            static_cast<Dst>(value) >= DstLimits::lowest()));
+    return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
+               ? GetRangeConstraint(true, value >= static_cast<Src>(0))
+               : GetRangeConstraint(
+                     value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+                     value >= static_cast<Src>(0));
   }
 };
 
-template <typename Dst,
-          template <typename> class Bounds = std::numeric_limits,
-          typename Src>
+template <typename Dst, typename Src>
 constexpr RangeConstraint DstRangeRelationToSrcRange(Src value) {
   static_assert(std::is_arithmetic<Src>::value, "Argument must be numeric.");
   static_assert(std::is_arithmetic<Dst>::value, "Result must be numeric.");
-  static_assert(Bounds<Dst>::lowest() < Bounds<Dst>::max(), "");
-  return DstRangeRelationToSrcRangeImpl<Dst, Src, Bounds>::Check(value);
+  return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
 }
 
 // Integer promotion templates used by the portable checked integer arithmetic.
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc
index 5304593..0e3d999b 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/numerics/safe_numerics_unittest.cc
@@ -671,14 +671,7 @@
     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
     TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
-
-    // Additional saturation tests.
-    EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
-    EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
-
     if (SrcLimits::is_iec559) {
-      EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
-
       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
       TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
       TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
@@ -721,10 +714,6 @@
     TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
     TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
     TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
-
-    // Additional saturation tests.
-    EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
-    EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
   }
 };
 
diff --git a/base/test/test_support_ios.mm b/base/test/test_support_ios.mm
index 2509fa0..d7e9990 100644
--- a/base/test/test_support_ios.mm
+++ b/base/test/test_support_ios.mm
@@ -32,7 +32,7 @@
 static char** g_argv;
 
 @interface UIApplication (Testing)
-- (void) _terminateWithStatus:(int)status;
+- (void)_terminateWithStatus:(int)status;
 @end
 
 #if TARGET_IPHONE_SIMULATOR
@@ -47,8 +47,7 @@
 #endif  // TARGET_IPHONE_SIMULATOR
 
 @interface ChromeUnitTestDelegate : NSObject {
- @private
-  base::scoped_nsobject<UIWindow> window_;
+  base::scoped_nsobject<UIWindow> _window;
 }
 - (void)runTests;
 @end
@@ -70,19 +69,19 @@
   CGRect bounds = [[UIScreen mainScreen] bounds];
 
   // Yes, this is leaked, it's just to make what's running visible.
-  window_.reset([[UIWindow alloc] initWithFrame:bounds]);
-  [window_ setBackgroundColor:[UIColor whiteColor]];
-  [window_ makeKeyAndVisible];
+  _window.reset([[UIWindow alloc] initWithFrame:bounds]);
+  [_window setBackgroundColor:[UIColor whiteColor]];
+  [_window makeKeyAndVisible];
 
   // Add a label with the app name.
   UILabel* label = [[[UILabel alloc] initWithFrame:bounds] autorelease];
   label.text = [[NSProcessInfo processInfo] processName];
   label.textAlignment = NSTextAlignmentCenter;
-  [window_ addSubview:label];
+  [_window addSubview:label];
 
   // An NSInternalInconsistencyException is thrown if the app doesn't have a
   // root view controller. Set an empty one here.
-  [window_ setRootViewController:[[[UIViewController alloc] init] autorelease]];
+  [_window setRootViewController:[[[UIViewController alloc] init] autorelease]];
 
   if ([self shouldRedirectOutputToFile])
     [self redirectOutput];
@@ -163,7 +162,7 @@
   // TODO(crbug.com/137010): Figure out how much time is actually needed, and
   // sleep only to make sure that much time has elapsed since launch.
   [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
-  window_.reset();
+  _window.reset();
 
   // Use the hidden selector to try and cleanly take down the app (otherwise
   // things can think the app crashed even on a zero exit status).
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 56bbb62..af22098ef 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -383,6 +383,12 @@
     CLEANUP_DONE,
   };
 
+  // Clears ScheduledTasks in |tasks_to_delete| while ensuring that
+  // |this_worker| has the desired task info context during ~ScheduledTask() to
+  // allow sequence-checking.
+  void DeleteWithoutLock(std::vector<SequencedTask>* tasks_to_delete,
+                         Worker* this_worker);
+
   // Helper used by PostTask() to complete the work when redirection is on.
   // Returns true if the task may run at some point in the future and false if
   // it will definitely not run.
@@ -420,7 +426,7 @@
   // See the implementation for a more detailed description.
   GetWorkStatus GetWork(SequencedTask* task,
                         TimeDelta* wait_time,
-                        std::vector<Closure>* delete_these_outside_lock);
+                        std::vector<SequencedTask>* delete_these_outside_lock);
 
   void HandleCleanup();
 
@@ -983,7 +989,7 @@
       // See GetWork for what delete_these_outside_lock is doing.
       SequencedTask task;
       TimeDelta wait_time;
-      std::vector<Closure> delete_these_outside_lock;
+      std::vector<SequencedTask> delete_these_outside_lock;
       GetWorkStatus status =
           GetWork(&task, &wait_time, &delete_these_outside_lock);
       if (status == GET_WORK_FOUND) {
@@ -1000,7 +1006,7 @@
           // already get a signal for each new task, but it doesn't
           // hurt.)
           SignalHasWork();
-          delete_these_outside_lock.clear();
+          DeleteWithoutLock(&delete_these_outside_lock, this_worker);
 
           // Complete thread creation outside the lock if necessary.
           if (new_thread_id)
@@ -1031,7 +1037,7 @@
         switch (status) {
           case GET_WORK_WAIT: {
               AutoUnlock unlock(lock_);
-              delete_these_outside_lock.clear();
+              DeleteWithoutLock(&delete_these_outside_lock, this_worker);
             }
             break;
           case GET_WORK_NOT_FOUND:
@@ -1053,7 +1059,7 @@
         // help this case.
         if (shutdown_called_ && blocking_shutdown_pending_task_count_ == 0) {
           AutoUnlock unlock(lock_);
-          delete_these_outside_lock.clear();
+          DeleteWithoutLock(&delete_these_outside_lock, this_worker);
           break;
         }
 
@@ -1061,7 +1067,7 @@
         // deletion must happen outside of the lock.
         if (delete_these_outside_lock.size()) {
           AutoUnlock unlock(lock_);
-          delete_these_outside_lock.clear();
+          DeleteWithoutLock(&delete_these_outside_lock, this_worker);
 
           // Since the lock has been released, |status| may no longer be
           // accurate. It might read GET_WORK_WAIT even if there are tasks
@@ -1084,6 +1090,9 @@
         }
         waiting_thread_count_--;
       }
+      // |delete_these_outside_lock| should have been cleared via
+      // DeleteWithoutLock() above already.
+      DCHECK(delete_these_outside_lock.empty());
     }
   }  // Release lock_.
 
@@ -1095,6 +1104,19 @@
   can_shutdown_cv_.Signal();
 }
 
+void SequencedWorkerPool::Inner::DeleteWithoutLock(
+    std::vector<SequencedTask>* tasks_to_delete,
+    Worker* this_worker) {
+  while (!tasks_to_delete->empty()) {
+    const SequencedTask& deleted_task = tasks_to_delete->back();
+    this_worker->set_running_task_info(
+        SequenceToken(deleted_task.sequence_token_id),
+        deleted_task.shutdown_behavior);
+    tasks_to_delete->pop_back();
+  }
+  this_worker->reset_running_task_info();
+}
+
 void SequencedWorkerPool::Inner::HandleCleanup() {
   DCHECK_EQ(AllPoolsState::USE_WORKER_POOL, g_all_pools_state);
 
@@ -1162,7 +1184,7 @@
 SequencedWorkerPool::Inner::GetWorkStatus SequencedWorkerPool::Inner::GetWork(
     SequencedTask* task,
     TimeDelta* wait_time,
-    std::vector<Closure>* delete_these_outside_lock) {
+    std::vector<SequencedTask>* delete_these_outside_lock) {
   DCHECK_EQ(AllPoolsState::USE_WORKER_POOL, g_all_pools_state);
 
   lock_.AssertAcquired();
@@ -1208,18 +1230,17 @@
       // shutdown. Delete it and get more work.
       //
       // Note that we do not want to delete unrunnable tasks. Deleting a task
-      // can have side effects (like freeing some objects) and deleting a
-      // task that's supposed to run after one that's currently running could
-      // cause an obscure crash.
+      // can have side effects (like freeing some objects) and deleting a task
+      // that's supposed to run after one that's currently running could cause
+      // an obscure crash.
       //
       // We really want to delete these tasks outside the lock in case the
-      // closures are holding refs to objects that want to post work from
-      // their destructorss (which would deadlock). The closures are
-      // internally refcounted, so we just need to keep a copy of them alive
-      // until the lock is exited. The calling code can just clear() the
-      // vector they passed to us once the lock is exited to make this
-      // happen.
-      delete_these_outside_lock->push_back(i->task);
+      // closures are holding refs to objects that want to post work from their
+      // destructors (which would deadlock). The closures are internally
+      // refcounted, so we just need to keep a copy of them alive until the lock
+      // is exited. The calling code can just clear() the vector they passed to
+      // us once the lock is exited to make this happen.
+      delete_these_outside_lock->push_back(*i);
       pending_tasks_.erase(i++);
       continue;
     }
@@ -1230,7 +1251,7 @@
       status = GET_WORK_WAIT;
       if (cleanup_state_ == CLEANUP_RUNNING) {
         // Deferred tasks are deleted when cleaning up, see Inner::ThreadLoop.
-        delete_these_outside_lock->push_back(i->task);
+        delete_these_outside_lock->push_back(*i);
         pending_tasks_.erase(i);
       }
       break;
diff --git a/build/android/devil_chromium.py b/build/android/devil_chromium.py
index 0e085d8..af2141a 100644
--- a/build/android/devil_chromium.py
+++ b/build/android/devil_chromium.py
@@ -18,82 +18,89 @@
     os.path.join(os.path.dirname(__file__), 'devil_chromium.json'))
 
 _DEVIL_BUILD_PRODUCT_DEPS = {
+  'chromium_commands': [
+    {
+      'platform': 'linux2',
+      'arch': 'x86_64',
+      'path_components': ['lib.java', 'chromium_commands.dex.jar'],
+    }
+  ],
   'forwarder_device': [
     {
       'platform': 'android',
       'arch': 'armeabi-v7a',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
     {
       'platform': 'android',
       'arch': 'arm64-v8a',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
     {
       'platform': 'android',
       'arch': 'mips',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
     {
       'platform': 'android',
       'arch': 'mips64',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
     {
       'platform': 'android',
       'arch': 'x86',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
     {
       'platform': 'android',
       'arch': 'x86_64',
-      'name': 'forwarder_dist',
+      'path_components': ['forwarder_dist'],
     },
   ],
   'forwarder_host': [
     {
       'platform': 'linux2',
       'arch': 'x86_64',
-      'name': 'host_forwarder',
+      'path_components': ['host_forwarder'],
     },
   ],
   'md5sum_device': [
     {
       'platform': 'android',
       'arch': 'armeabi-v7a',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
     {
       'platform': 'android',
       'arch': 'arm64-v8a',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
     {
       'platform': 'android',
       'arch': 'mips',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
     {
       'platform': 'android',
       'arch': 'mips64',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
     {
       'platform': 'android',
       'arch': 'x86',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
     {
       'platform': 'android',
       'arch': 'x86_64',
-      'name': 'md5sum_dist',
+      'path_components': ['md5sum_dist'],
     },
   ],
   'md5sum_host': [
     {
       'platform': 'linux2',
       'arch': 'x86_64',
-      'name': 'md5sum_bin_host',
+      'path_components': ['md5sum_bin_host'],
     },
   ],
 }
@@ -137,7 +144,7 @@
         'file_info': {
           '%s_%s' % (dep_config['platform'], dep_config['arch']): {
             'local_paths': [
-              os.path.join(output_directory, dep_config['name']),
+              os.path.join(output_directory, *dep_config['path_components']),
             ],
           }
           for dep_config in dep_configs
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index b7053e7..d964493 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -155,10 +155,15 @@
 prebuilt_instrumented_libraries_available =
     is_msan && (msan_track_origins == 0 || msan_track_origins == 2)
 
-if (use_libfuzzer && is_asan && is_linux) {
-  # We do leak checking with libFuzzer on Linux. Set is_lsan for code that
-  # relies on LEAK_SANITIZER define to avoid false positives.
-  is_lsan = true
+if (use_libfuzzer && is_linux) {
+  if (is_asan) {
+    # We do leak checking with libFuzzer on Linux. Set is_lsan for code that
+    # relies on LEAK_SANITIZER define to avoid false positives.
+    is_lsan = true
+  }
+  if (is_msan) {
+    use_prebuilt_instrumented_libraries = true
+  }
 }
 
 # MSan only links Chrome properly in release builds (brettw -- 9/1/2015). The
diff --git a/cc/quads/draw_polygon.cc b/cc/quads/draw_polygon.cc
index 59ecbef0..e202fed 100644
--- a/cc/quads/draw_polygon.cc
+++ b/cc/quads/draw_polygon.cc
@@ -43,9 +43,12 @@
   for (size_t i = 0; i < in_points.size(); i++) {
     points_.push_back(in_points[i]);
   }
+#if DCHECK_IS_ON()
   normal_ = normal;
-  DCHECK_LE((ConstructNormal(), (normal_ - normal).Length()),
-            normalized_threshold);
+  ConstructNormal();
+  DCHECK_LE((normal_ - normal).Length(), normalized_threshold);
+#endif
+  normal_ = normal;
 }
 
 // This takes the original DrawQuad that this polygon should be based on,
diff --git a/cc/quads/draw_polygon_unittest.cc b/cc/quads/draw_polygon_unittest.cc
index 6938b88f..f795787ec 100644
--- a/cc/quads/draw_polygon_unittest.cc
+++ b/cc/quads/draw_polygon_unittest.cc
@@ -525,7 +525,9 @@
   vertices_c.push_back(gfx::Point3F(10.0f, 0.05f, 9.0f));
 
   CREATE_NEW_DRAW_POLYGON_PTR(polygon_c, vertices_c,
-                              gfx::Vector3dF(0.0055f, -0.999f, 0.0055f), 0);
+                              gfx::Vector3dF(0.005555f, -0.99997f, 0.005555f),
+                              0);
+  polygon_c->RecomputeNormalForTesting();
 
   std::unique_ptr<DrawPolygon> second_front_polygon;
   std::unique_ptr<DrawPolygon> second_back_polygon;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java
index 312dd77..4bbbb4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java
@@ -24,7 +24,7 @@
 /**
  * The {@link BackgroundSyncLauncher} singleton is created and owned by the C++ browser. It
  * registers interest in waking up the browser the next time the device goes online after the
- * browser closes via the {@link #setLaunchWhenNextOnline} method.
+ * browser closes via the {@link #launchBrowserIfStopped} method.
  *
  * Thread model: This class is to be run on the UI thread only.
  */
@@ -50,6 +50,9 @@
      */
     private static boolean sGCMEnabled = true;
 
+    @VisibleForTesting
+    protected AsyncTask<Void, Void, Void> mLaunchBrowserIfStoppedTask;
+
     /**
      * Create a BackgroundSyncLauncher object, which is owned by C++.
      * @param context The app context.
@@ -79,18 +82,21 @@
      * Callback for {@link #shouldLaunchBrowserIfStopped}. The run method is invoked on the UI
      * thread.
      */
-    public static interface ShouldLaunchCallback { public void run(Boolean shouldLaunch); }
+    public interface ShouldLaunchCallback { void run(Boolean shouldLaunch); }
 
     /**
      * Returns whether the browser should be launched when the device next goes online.
      * This is set by C++ and reset to false each time {@link BackgroundSyncLauncher}'s singleton is
      * created (the native browser is started). This call is asynchronous and will run the callback
      * on the UI thread when complete.
-     * @param context The application context.
-     * @param sharedPreferences The shared preferences.
+     *
+     * {@link AsyncTask} is necessary as the browser process will not have warmed up the
+     * {@link SharedPreferences} before it is used here. This is likely the first usage of
+     * {@link ContextUtils#getAppSharedPreferences}.
+     *
+     * @param callback The callback after fetching prefs.
      */
-    protected static void shouldLaunchBrowserIfStopped(
-            final Context context, final ShouldLaunchCallback callback) {
+    protected static void shouldLaunchBrowserIfStopped(final ShouldLaunchCallback callback) {
         new AsyncTask<Void, Void, Boolean>() {
             @Override
             protected Boolean doInBackground(Void... params) {
@@ -101,7 +107,7 @@
             protected void onPostExecute(Boolean shouldLaunch) {
                 callback.run(shouldLaunch);
             }
-        }.execute();
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     /**
@@ -110,15 +116,16 @@
      * This method is called by C++ as background sync registrations are added and removed. When the
      * {@link BackgroundSyncLauncher} singleton is created (on browser start), this is called to
      * remove any pre-existing scheduled tasks.
-     * @param context The application context.
+     *
+     * See {@link #shouldLaunchBrowserIfStopped} for {@link AsyncTask}.
+     *
      * @param shouldLaunch Whether or not to launch the browser in the background.
      * @param minDelayMs The minimum time to wait before checking on the browser process.
      */
     @VisibleForTesting
     @CalledByNative
-    protected void launchBrowserIfStopped(
-            final Context context, final boolean shouldLaunch, final long minDelayMs) {
-        new AsyncTask<Void, Void, Void>() {
+    protected void launchBrowserIfStopped(final boolean shouldLaunch, final long minDelayMs) {
+        mLaunchBrowserIfStoppedTask = new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
                 SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
@@ -133,7 +140,7 @@
                     if (shouldLaunch) {
                         RecordHistogram.recordBooleanHistogram(
                                 "BackgroundSync.LaunchTask.ScheduleSuccess",
-                                scheduleLaunchTask(context, mScheduler, minDelayMs));
+                                scheduleLaunchTask(mScheduler, minDelayMs));
                     } else {
                         RecordHistogram.recordBooleanHistogram(
                                 "BackgroundSync.LaunchTask.CancelSuccess",
@@ -141,7 +148,7 @@
                     }
                 }
             }
-        }.execute();
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     /**
@@ -154,7 +161,7 @@
 
     protected BackgroundSyncLauncher(Context context) {
         mScheduler = GcmNetworkManager.getInstance(context);
-        launchBrowserIfStopped(context, false, 0);
+        launchBrowserIfStopped(false, 0);
     }
 
     private static boolean canUseGooglePlayServices(Context context) {
@@ -188,8 +195,7 @@
         return !sGCMEnabled;
     }
 
-    private static boolean scheduleLaunchTask(
-            Context context, GcmNetworkManager scheduler, long minDelayMs) {
+    private static boolean scheduleLaunchTask(GcmNetworkManager scheduler, long minDelayMs) {
         // Google Play Services may not be up to date, if the application was not installed through
         // the Play Store. In this case, scheduling the task will fail silently.
         final long minDelaySecs = minDelayMs / 1000;
@@ -252,11 +258,11 @@
                             // without delay and let the browser reschedule if necessary.
                             // TODO(iclelland): If this fails, report the failure via UMA (not now,
                             // since the browser is not running, but on next startup.)
-                            scheduleLaunchTask(context, scheduler, 0);
+                            scheduleLaunchTask(scheduler, 0);
                         }
                     }
                 };
-        BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(context, callback);
+        BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(callback);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java
new file mode 100644
index 0000000..3746766
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java
@@ -0,0 +1,96 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import org.chromium.base.ContextUtils;
+
+/**
+ * Intent handler that is specific for the situation when the screen is unlocked from pin, pattern,
+ * or password.
+ * This class handles exactly one intent unlock + dispatch at a time. It could be reused by calling
+ * updateDeferredIntent with a new intent.
+ */
+public class DelayedScreenLockIntentHandler extends BroadcastReceiver {
+    private static final int VALID_DEFERRED_PERIOD_MS = 10000;
+
+    private final Handler mTaskHandler;
+    private final Runnable mUnregisterTask;
+
+    private Intent mDeferredIntent;
+    private long mDeferredIntentCreatedTime;
+    private boolean mReceiverRegistered;
+
+    public DelayedScreenLockIntentHandler() {
+        mTaskHandler = new Handler();
+        mUnregisterTask = new Runnable() {
+            @Override
+            public void run() {
+                updateDeferredIntent(null);
+            }
+        };
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        assert Intent.ACTION_USER_PRESENT.equals(intent.getAction());
+
+        if (Intent.ACTION_USER_PRESENT.equals(intent.getAction()) && mDeferredIntent != null) {
+            context.startActivity(mDeferredIntent);
+            // Prevent the broadcast receiver from firing intent unexpectedly.
+            updateDeferredIntent(null);
+        }
+    }
+
+    /**
+     * Update the deferred intent with the target intent, also reset the deferred intent's lifecycle
+     * @param intent Target intent
+     */
+    public void updateDeferredIntent(final Intent intent) {
+        mTaskHandler.removeCallbacks(mUnregisterTask);
+
+        if (intent == null) {
+            unregisterReceiver();
+            mDeferredIntent = null;
+            return;
+        }
+
+        mDeferredIntent = intent;
+        mDeferredIntentCreatedTime = SystemClock.elapsedRealtime();
+        registerReceiver();
+        mTaskHandler.postDelayed(mUnregisterTask, VALID_DEFERRED_PERIOD_MS);
+    }
+
+    /**
+     * Register to receive ACTION_USER_PRESENT when the screen is unlocked.
+     * The ACTION_USER_PRESENT is sent by platform to indicates when user is present.
+     */
+    private void registerReceiver() {
+        if (mReceiverRegistered) return;
+
+        ContextUtils.getApplicationContext()
+                .registerReceiver(this, new IntentFilter(Intent.ACTION_USER_PRESENT));
+        mReceiverRegistered = true;
+    }
+
+    /**
+     * Unregister the receiver in one of the following situations
+     * - When the deferred intent expires
+     * - When updateDeferredIntent(null) called
+     * - When the deferred intent has been fired
+     */
+    private void unregisterReceiver() {
+        if (!mReceiverRegistered) return;
+
+        ContextUtils.getApplicationContext().unregisterReceiver(this);
+        mReceiverRegistered = false;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 31834e4..c05dd117 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -226,6 +226,11 @@
     private final String mPackageName;
     private KeyguardManager mKeyguardManager;
 
+    /**
+     * Receiver for screen unlock broadcast.
+     */
+    private DelayedScreenLockIntentHandler mDelayedScreenIntentHandler;
+
     public static enum TabOpenType {
         OPEN_NEW_TAB,
         // Tab is reused only if the URLs perfectly match.
@@ -331,13 +336,26 @@
         }
     }
 
+    private void updateDeferredIntent(Intent intent) {
+        if (mDelayedScreenIntentHandler == null && intent != null) {
+            mDelayedScreenIntentHandler = new DelayedScreenLockIntentHandler();
+        }
+
+        if (mDelayedScreenIntentHandler != null) {
+            mDelayedScreenIntentHandler.updateDeferredIntent(intent);
+        }
+    }
+
     /**
      * Handles an Intent after the ChromeTabbedActivity decides that it shouldn't ignore the
      * Intent.
-     *
+     * @param context Android Context.
+     * @param intent Target intent.
      * @return Whether the Intent was successfully handled.
      */
     boolean onNewIntent(Context context, Intent intent) {
+        updateDeferredIntent(null);
+
         assert intentHasValidUrl(intent);
         String url = getUrlFromIntent(intent);
         boolean hasUserGesture =
@@ -688,7 +706,11 @@
             // We must check for screen state at this point.
             // These might be slow.
             boolean internalOrVisible = isInternal || isIntentUserVisible(context);
-            return !internalOrVisible;
+            if (!internalOrVisible) {
+                updateDeferredIntent(intent);
+                return true;
+            }
+            return false;
         } catch (Throwable t) {
             return true;
         }
@@ -761,7 +783,8 @@
         return false;
     }
 
-    private boolean isIntentUserVisible(Context context) {
+    @VisibleForTesting
+    boolean isIntentUserVisible(Context context) {
         // Only process Intents if the screen is on and the device is unlocked;
         // i.e. the user will see what is going on.
         if (mKeyguardManager == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index e7230bb..6c81ee0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -1567,7 +1567,7 @@
     @Override
     public void broadcastDownloadAction(DownloadItem downloadItem, String action) {
         Intent intent = DownloadNotificationService.buildActionIntent(mContext, action,
-                downloadItem.getId(), downloadItem.getDownloadInfo().getFileName());
+                downloadItem.getId(), downloadItem.getDownloadInfo().isOffTheRecord(), false);
         mContext.sendBroadcast(intent);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index 59d530e..23f08c89 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -55,6 +55,10 @@
     static final String EXTRA_DOWNLOAD_FILE_PATH = "DownloadFilePath";
     static final String EXTRA_NOTIFICATION_DISMISSED = "NotificationDismissed";
     static final String EXTRA_IS_SUPPORTED_MIME_TYPE = "IsSupportedMimeType";
+    static final String EXTRA_IS_OFF_THE_RECORD =
+            "org.chromium.chrome.browser.download.IS_OFF_THE_RECORD";
+    static final String EXTRA_IS_OFFLINE_PAGE =
+            "org.chromium.chrome.browser.download.IS_OFFLINE_PAGE";
 
     public static final String ACTION_DOWNLOAD_CANCEL =
             "org.chromium.chrome.browser.download.DOWNLOAD_CANCEL";
@@ -296,20 +300,20 @@
         if (startTime > 0) builder.setWhen(startTime);
 
         // Clicking on an in-progress download sends the user to see all their downloads.
-        Intent downloadHomeIntent = buildActionIntent(
-                mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, null);
+        Intent downloadHomeIntent = buildActionIntent(mContext,
+                DownloadManager.ACTION_NOTIFICATION_CLICKED, null, isOffTheRecord, isOfflinePage);
         builder.setContentIntent(PendingIntent.getBroadcast(
                 mContext, notificationId, downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
         builder.setAutoCancel(false);
 
         Intent pauseIntent = buildActionIntent(
-                mContext, ACTION_DOWNLOAD_PAUSE, downloadGuid, fileName);
+                mContext, ACTION_DOWNLOAD_PAUSE, downloadGuid, isOffTheRecord, isOfflinePage);
         builder.addAction(R.drawable.ic_media_control_pause,
                 mContext.getResources().getString(R.string.download_notification_pause_button),
                 buildPendingIntent(pauseIntent, notificationId));
 
         Intent cancelIntent = buildActionIntent(
-                mContext, ACTION_DOWNLOAD_CANCEL, downloadGuid, fileName);
+                mContext, ACTION_DOWNLOAD_CANCEL, downloadGuid, isOffTheRecord, isOfflinePage);
         builder.addAction(R.drawable.btn_close_white,
                 mContext.getResources().getString(R.string.download_notification_cancel_button),
                 buildPendingIntent(cancelIntent, notificationId));
@@ -378,19 +382,19 @@
 
         // Clicking on an in-progress download sends the user to see all their downloads.
         Intent downloadHomeIntent = buildActionIntent(
-                mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, null);
+                mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, false, false);
         builder.setContentIntent(PendingIntent.getBroadcast(mContext, entry.notificationId,
                 downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
         builder.setAutoCancel(false);
 
         Intent resumeIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_RESUME,
-                entry.downloadGuid, entry.fileName);
+                entry.downloadGuid, entry.isOffTheRecord, entry.isOfflinePage());
         builder.addAction(R.drawable.ic_get_app_white_24dp,
                 mContext.getResources().getString(R.string.download_notification_resume_button),
                 buildPendingIntent(resumeIntent, entry.notificationId));
 
         Intent cancelIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_CANCEL,
-                entry.downloadGuid, entry.fileName);
+                entry.downloadGuid, entry.isOffTheRecord, entry.isOfflinePage());
         builder.addAction(R.drawable.btn_close_white,
                 mContext.getResources().getString(R.string.download_notification_cancel_button),
                 buildPendingIntent(cancelIntent, entry.notificationId));
@@ -429,8 +433,7 @@
                 mContext.getPackageName(), DownloadBroadcastReceiver.class.getName());
         Intent intent;
         if (isOfflinePage) {
-            intent = buildActionIntent(
-                    mContext, ACTION_DOWNLOAD_OPEN, downloadGuid, fileName);
+            intent = buildActionIntent(mContext, ACTION_DOWNLOAD_OPEN, downloadGuid, false, true);
         } else {
             intent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
             long[] idArray = {systemDownloadId};
@@ -514,15 +517,18 @@
      * @param context {@link Context} to pull resources from.
      * @param action Download action to perform.
      * @param downloadGuid GUID of the download.
-     * @param fileName Name of the download file.
+     * @param isOffTheRecord Whether the download is incognito.
+     * @param isOfflinePage Whether the download represents an Offline Page.
      */
     static Intent buildActionIntent(Context context, String action, String downloadGuid,
-            String fileName) {
+            boolean isOffTheRecord, boolean isOfflinePage) {
         ComponentName component = new ComponentName(
                 context.getPackageName(), DownloadBroadcastReceiver.class.getName());
         Intent intent = new Intent(action);
         intent.setComponent(component);
         intent.putExtra(EXTRA_DOWNLOAD_GUID, downloadGuid);
+        intent.putExtra(EXTRA_IS_OFF_THE_RECORD, isOffTheRecord);
+        intent.putExtra(EXTRA_IS_OFFLINE_PAGE, isOfflinePage);
         return intent;
     }
 
@@ -587,7 +593,11 @@
      */
     private void handleDownloadOperation(final Intent intent) {
         final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(intent);
-        if (entry == null) return;
+        if (entry == null) {
+            handleDownloadOperationForMissingNotification(intent);
+            return;
+        }
+
         if (intent.getAction() == ACTION_DOWNLOAD_PAUSE) {
             // If browser process already goes away, the download should have already paused. Do
             // nothing in that case.
@@ -675,6 +685,38 @@
     }
 
     /**
+     * Handles operations for downloads that the DownloadNotificationService is unaware of.
+     *
+     * This can happen because the DownloadNotificationService learn about downloads later than
+     * Download Home does, and may not yet have a DownloadSharedPreferenceEntry for the item.
+     *
+     * TODO(qinmin): Talk with dfalcantara@ about whether this is the best path forward.
+     */
+    private void handleDownloadOperationForMissingNotification(Intent intent) {
+        String action = intent.getAction();
+        String downloadGuid = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_GUID);
+        boolean isOffTheRecord =
+                IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OFF_THE_RECORD, false);
+        int itemType = IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OFFLINE_PAGE, false)
+                ? DownloadSharedPreferenceEntry.ITEM_TYPE_OFFLINE_PAGE
+                : DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD;
+        if (itemType != DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD) return;
+
+        // Pass information directly to the DownloadManagerService.
+        if (TextUtils.equals(action, ACTION_DOWNLOAD_CANCEL)) {
+            getServiceDelegate(itemType).cancelDownload(downloadGuid, isOffTheRecord, false);
+        } else if (TextUtils.equals(action, ACTION_DOWNLOAD_PAUSE)) {
+            getServiceDelegate(itemType).pauseDownload(downloadGuid, isOffTheRecord);
+        } else if (TextUtils.equals(action, ACTION_DOWNLOAD_RESUME)) {
+            DownloadInfo info = new DownloadInfo.Builder()
+                                        .setDownloadGuid(downloadGuid)
+                                        .setIsOffTheRecord(isOffTheRecord)
+                                        .build();
+            getServiceDelegate(itemType).resumeDownload(new DownloadItem(false, info), true);
+        }
+    }
+
+    /**
      * Gets appropriate download delegate that can handle interactions with download item referred
      * to by the entry.
      * @param forOfflinePage Whether the service should deal with offline pages or downloads.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
index 2e61b311..8ffecbf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
@@ -7,14 +7,12 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
-import android.text.TextUtils;
 
-import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.components.variations.VariationsAssociatedData;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.DeviceFormFactor;
 
@@ -22,8 +20,6 @@
  * Utility methods for the browsing history manager.
  */
 public class HistoryManagerUtils {
-    private static final String FIELD_TRIAL_NAME = "AndroidHistoryManager";
-    private static final String ENABLE_HISTORY_SWTICH = "enable_android_history_manager";
     private static final Object NATIVE_HISTORY_ENABLED_LOCK = new Object();
     private static Boolean sNativeHistoryEnabled;
 
@@ -33,13 +29,7 @@
     public static boolean isAndroidHistoryManagerEnabled() {
         synchronized (NATIVE_HISTORY_ENABLED_LOCK) {
             if (sNativeHistoryEnabled == null) {
-                if (CommandLine.getInstance().hasSwitch(ENABLE_HISTORY_SWTICH)) {
-                    sNativeHistoryEnabled = true;
-                } else {
-                    sNativeHistoryEnabled = TextUtils.equals("true",
-                            VariationsAssociatedData.getVariationParamValue(FIELD_TRIAL_NAME,
-                                    ENABLE_HISTORY_SWTICH));
-                }
+                sNativeHistoryEnabled = ChromeFeatureList.isEnabled("AndroidHistoryManager");
             }
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 27ed0621..65b3c2de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -369,6 +369,13 @@
             }
 
             @Override
+            public void onToggleFullscreenMode(Tab tab, boolean enable) {
+                if (mFindToolbarManager != null && enable) {
+                    mFindToolbarManager.hideToolbar();
+                }
+            }
+
+            @Override
             public void onContentChanged(Tab tab) {
                 mToolbar.onTabContentViewChanged();
                 if (shouldShowCusrsorInLocationBar()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java
index b363eff..4e36958 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrCoreVersionCheckerImpl.java
@@ -31,7 +31,7 @@
             }
             return true;
         } catch (VrCoreNotAvailableException e) {
-            Log.e(TAG, "Unable to find a compatible VrCore", e);
+            Log.i(TAG, "Unable to find a compatible VrCore.");
             return false;
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
index 1de6c0e..de8a7c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbar.java
@@ -235,7 +235,6 @@
                 if (mFindInPageBridge == null) return;
 
                 mAccessibilityDidActivateResult = false;
-                setPrevNextEnabled(s.length() > 0);
 
                 if (mSettingFindTextProgrammatically) return;
 
@@ -430,6 +429,8 @@
                 result.numberOfMatches);
         setStatus(text, result.numberOfMatches == 0);
 
+        setPrevNextEnabled(result.numberOfMatches > 0);
+
         // The accessible version will be something like "Result 1 of 9".
         String accessibleText = getAccessibleStatusText(
                 Math.max(result.activeMatchOrdinal, 0),
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 2151a03..56f6c73 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -42,6 +42,7 @@
   "java/src/org/chromium/chrome/browser/JavaExceptionReporter.java",
   "java/src/org/chromium/chrome/browser/JavascriptAppModalDialog.java",
   "java/src/org/chromium/chrome/browser/KeyboardShortcuts.java",
+  "java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java",
   "java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java",
   "java/src/org/chromium/chrome/browser/LoginPrompt.java",
   "java/src/org/chromium/chrome/browser/LollipopTtsPlatformImpl.java",
@@ -1476,6 +1477,7 @@
   "junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java",
   "junit/src/org/chromium/chrome/browser/ChromeBackgroundServiceWaiterTest.java",
   "junit/src/org/chromium/chrome/browser/EnableFeatures.java",
+  "junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java",
   "junit/src/org/chromium/chrome/browser/ShortcutHelperTest.java",
   "junit/src/org/chromium/chrome/browser/SSLClientCertificateRequestTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java
index f26d62d..d54d646 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java
@@ -13,6 +13,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Semaphore;
 
 /**
@@ -29,6 +30,8 @@
         BackgroundSyncLauncher.setGCMEnabled(false);
         RecordHistogram.disableForTests();
         mLauncher = BackgroundSyncLauncher.create(mContext);
+        // Ensure that the initial task is given enough time to complete.
+        waitForLaunchBrowserTask();
     }
 
     private void deleteLauncherInstance() {
@@ -51,7 +54,7 @@
                     }
                 };
 
-        BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(mContext, callback);
+        BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(callback);
         try {
             // Wait on the callback to be called.
             semaphore.acquire();
@@ -61,6 +64,16 @@
         return mShouldLaunchResult;
     }
 
+    private void waitForLaunchBrowserTask() {
+        try {
+            mLauncher.mLaunchBrowserIfStoppedTask.get();
+        } catch (InterruptedException e) {
+            fail("Launch task was interrupted");
+        } catch (ExecutionException e) {
+            fail("Launch task had execution exception");
+        }
+    }
+
     @SmallTest
     @Feature({"BackgroundSync"})
     @RetryOnFailure
@@ -81,9 +94,11 @@
     @RetryOnFailure
     public void testSetLaunchWhenNextOnline() {
         assertFalse(shouldLaunchBrowserIfStoppedSync());
-        mLauncher.launchBrowserIfStopped(mContext, true, 0);
+        mLauncher.launchBrowserIfStopped(true, 0);
+        waitForLaunchBrowserTask();
         assertTrue(shouldLaunchBrowserIfStoppedSync());
-        mLauncher.launchBrowserIfStopped(mContext, false, 0);
+        mLauncher.launchBrowserIfStopped(false, 0);
+        waitForLaunchBrowserTask();
         assertFalse(shouldLaunchBrowserIfStoppedSync());
     }
 
@@ -91,12 +106,14 @@
     @Feature({"BackgroundSync"})
     @RetryOnFailure
     public void testNewLauncherDisablesNextOnline() {
-        mLauncher.launchBrowserIfStopped(mContext, true, 0);
+        mLauncher.launchBrowserIfStopped(true, 0);
+        waitForLaunchBrowserTask();
         assertTrue(shouldLaunchBrowserIfStoppedSync());
 
         // Simulate restarting the browser by deleting the launcher and creating a new one.
         deleteLauncherInstance();
         mLauncher = BackgroundSyncLauncher.create(mContext);
+        waitForLaunchBrowserTask();
         assertFalse(shouldLaunchBrowserIfStoppedSync());
     }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java
new file mode 100644
index 0000000..8f0b919
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java
@@ -0,0 +1,100 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+/**
+ * Unit tests for the DelayedScreenLockIntentHandlerTest class.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class DelayedScreenLockIntentHandlerTest {
+    @Mock private Context mContextMock;
+
+    private DelayedScreenLockIntentHandler mIntentHandler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mIntentHandler = new DelayedScreenLockIntentHandler();
+        ContextUtils.initApplicationContextForTests(mContextMock);
+    }
+
+    @Test
+    public void testReceiveBroadcast() {
+        final Intent deferredIntent = new Intent();
+        final Intent intent = new Intent(Intent.ACTION_USER_PRESENT);
+
+        mIntentHandler.updateDeferredIntent(deferredIntent);
+        mIntentHandler.onReceive(mContextMock, intent);
+
+        verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class));
+        verify(mContextMock).startActivity(deferredIntent);
+        verify(mContextMock).unregisterReceiver(mIntentHandler);
+    }
+
+    @Test
+    public void testReceiveBroadcastTwice() {
+        final Intent deferredIntent = new Intent();
+        final Intent intent = new Intent(Intent.ACTION_USER_PRESENT);
+
+        mIntentHandler.updateDeferredIntent(deferredIntent);
+        mIntentHandler.onReceive(mContextMock, intent);
+        mIntentHandler.onReceive(mContextMock, intent);
+
+        verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class));
+        verify(mContextMock).startActivity(deferredIntent);
+        verify(mContextMock).unregisterReceiver(mIntentHandler);
+    }
+
+    @Test
+    public void testSecondDeferredIntentAction() {
+        final Intent deferredIntent1 = new Intent();
+        final Intent deferredIntent2 = new Intent();
+        final Intent intent = new Intent(Intent.ACTION_USER_PRESENT);
+
+        mIntentHandler.updateDeferredIntent(deferredIntent1);
+        mIntentHandler.updateDeferredIntent(deferredIntent2);
+        mIntentHandler.onReceive(mContextMock, intent);
+
+        verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class));
+        verify(mContextMock).startActivity(deferredIntent2);
+        verify(mContextMock).unregisterReceiver(mIntentHandler);
+    }
+
+    @Test
+    public void testNonExpectedIntentAction() {
+        mIntentHandler.updateDeferredIntent(new Intent());
+        try {
+            mIntentHandler.onReceive(mContextMock, new Intent());
+        } catch (AssertionError assertError) {
+            // Ignore AssertErrors
+        }
+
+        verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class));
+        verify(mContextMock, never()).startActivity(any(Intent.class));
+        verify(mContextMock, never()).unregisterReceiver(mIntentHandler);
+    }
+}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 89cfc5a..3e585809 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -15620,6 +15620,16 @@
      <message name="IDS_FLAGS_FASTER_LOCATION_RELOAD_DESCRIPTION" desc="Description for the flag to enable faster location.reload()" translateable="false">
       Enable faster location.reload() to use a reload mode that revalidates only main resource forcibly.
     </message>
+
+    <!-- Native Android History chrome://flags strings -->
+    <if expr="is_android">
+      <message name="IDS_NATIVE_ANDROID_HISTORY_MANAGER" desc="Name of the flag that enables the native Android history UI." translateable="false">
+        Native Android History
+      </message>
+      <message name="IDS_NATIVE_ANDROID_HISTORY_MANAGER_DESCRIPTION" desc="Description of the flag that enables the native Android history UI." translateable="false">
+        Show the native Android UI for browsing history.
+      </message>
+    </if>
   </messages>
  </release>
 </grit>
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 58d0db3..275111d 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -98,6 +98,7 @@
   "+third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h",
   "+third_party/WebKit/public/platform/WebGestureEvent.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
+  "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
   "+third_party/WebKit/public/platform/WebSecurityStyle.h",
   "+third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3d684d6..ec10a42 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2142,6 +2142,9 @@
          autofill::kAutofillCreditCardPopupLayout,
          kAutofillCreditCardPopupLayoutFeatureVariations,
          "AutofillCreditCardPopupLayout")},
+     {"native-android-history-manager", IDS_NATIVE_ANDROID_HISTORY_MANAGER,
+      IDS_NATIVE_ANDROID_HISTORY_MANAGER_DESCRIPTION, kOsAndroid,
+      FEATURE_VALUE_TYPE(chrome::android::kNativeAndroidHistoryManager)},
 #endif  // OS_ANDROID
     {"enable-faster-location-reload", IDS_FLAGS_FASTER_LOCATION_RELOAD_NAME,
      IDS_FLAGS_FASTER_LOCATION_RELOAD_DESCRIPTION, kOsAll,
diff --git a/chrome/browser/android/background_sync_launcher_android.cc b/chrome/browser/android/background_sync_launcher_android.cc
index 0b13a14..bac2de6 100644
--- a/chrome/browser/android/background_sync_launcher_android.cc
+++ b/chrome/browser/android/background_sync_launcher_android.cc
@@ -44,8 +44,7 @@
 
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_BackgroundSyncLauncher_launchBrowserIfStopped(
-      env, java_launcher_, base::android::GetApplicationContext(),
-      launch_when_next_online, min_delay_ms);
+      env, java_launcher_, launch_when_next_online, min_delay_ms);
 }
 
 // static
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 1e37f80..a04b5f4 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -47,6 +47,7 @@
     &kDownloadsUiFeature,
     &kImportantSitesInCBD,
     &kImprovedA2HS,
+    &kNativeAndroidHistoryManager,
     &kNoCreditCardAbort,
     &kNTPFakeOmniboxTextFeature,
     &kNTPOfflinePagesFeature,
@@ -100,6 +101,9 @@
 const base::Feature kImprovedA2HS{"ImprovedA2HS",
                                   base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kNativeAndroidHistoryManager{
+  "AndroidHistoryManager", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kNoCreditCardAbort{"NoCreditCardAbort",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index c9d623c..4a18820 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -22,6 +22,7 @@
 extern const base::Feature kDownloadsUiFeature;
 extern const base::Feature kImportantSitesInCBD;
 extern const base::Feature kImprovedA2HS;
+extern const base::Feature kNativeAndroidHistoryManager;
 extern const base::Feature kNoCreditCardAbort;
 extern const base::Feature kNTPFakeOmniboxTextFeature;
 extern const base::Feature kNTPOfflinePagesFeature;
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 842d9308..fdd1961 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/files/file_util.h"
 #include "base/guid.h"
 #include "base/location.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
@@ -885,6 +886,18 @@
     NOTREACHED();
   }
 
+  void SetDiscardUploadsForTesting(bool discard_uploads) override {
+    NOTREACHED();
+  }
+
+  void AddContextForTesting(
+      std::unique_ptr<const domain_reliability::DomainReliabilityConfig> config)
+      override {
+    NOTREACHED();
+  }
+
+  void ForceUploadsForTesting() override { NOTREACHED(); }
+
   int clear_count() const { return clear_count_; }
 
   DomainReliabilityClearMode last_clear_mode() const {
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index 3634168..03dc966 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -23,6 +23,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/browser_watcher/features.h"
+#include "components/browser_watcher/stability_debugging.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/common/content_switches.h"
 #include "media/media_features.h"
@@ -30,7 +31,6 @@
 #if defined(OS_WIN)
 #include "chrome/install_static/install_util.h"
 #include "components/browser_watcher/stability_data_names.h"
-#include "components/browser_watcher/stability_debugging_win.h"
 #endif
 
 namespace chrome {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 46e0df9..d4e7a1c 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3370,6 +3370,11 @@
       MaybePerformBrowserTaskSchedulerRedirection();
 }
 
+bool ChromeContentBrowserClient::ShouldRedirectDOMStorageTaskRunner() {
+  return variations::GetVariationParamValue(
+             "BrowserScheduler", "RedirectDOMStorageTaskRunner") == "true";
+}
+
 bool ChromeContentBrowserClient::
     RedirectNonUINonIOBrowserThreadsToTaskScheduler() {
   return variations::GetVariationParamValue(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 6c01bb6..84551bf 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -325,6 +325,7 @@
       base::TaskScheduler::WorkerPoolIndexForTraitsCallback*
           index_to_traits_callback) override;
   void PerformExperimentalTaskSchedulerRedirections() override;
+  bool ShouldRedirectDOMStorageTaskRunner() override;
   bool RedirectNonUINonIOBrowserThreadsToTaskScheduler() override;
 
  private:
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc
index 218497c0..3440767 100644
--- a/chrome/browser/chromeos/arc/arc_auth_service.cc
+++ b/chrome/browser/chromeos/arc/arc_auth_service.cc
@@ -233,6 +233,9 @@
         ArcSessionManager::Get()->profile(),
         ArcSessionManager::Get()->auth_context());
   } else {
+    // Report that silent auth code is not activated. All other states are
+    // reported in ArcBackgroundAuthCodeFetcher.
+    UpdateSilentAuthCodeUMA(OptInSilentAuthCode::DISABLED);
     // Otherwise, show LSO page and let user click "Sign in" button.
     // Here, support_host should be available always. The case support_host is
     // not created is when 1) IsOptInVerificationDisabled() is true or 2)
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.cc b/chrome/browser/chromeos/arc/arc_optin_uma.cc
index f350e09..f2ff20a 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.cc
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.cc
@@ -49,4 +49,9 @@
       ->AddTime(elapsed_time);
 }
 
+void UpdateSilentAuthCodeUMA(OptInSilentAuthCode state) {
+  UMA_HISTOGRAM_ENUMERATION("Arc.OptInSilentAuthCode", static_cast<int>(state),
+                            static_cast<int>(OptInSilentAuthCode::SIZE));
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/arc_optin_uma.h b/chrome/browser/chromeos/arc/arc_optin_uma.h
index bc8983d..c6cd240 100644
--- a/chrome/browser/chromeos/arc/arc_optin_uma.h
+++ b/chrome/browser/chromeos/arc/arc_optin_uma.h
@@ -35,6 +35,29 @@
   SIZE,                             // The size of this enum; keep last.
 };
 
+enum class OptInSilentAuthCode {
+  // Silent auth code feature is disabled.
+  DISABLED = 0,
+  // Silent auth code fetched normally.
+  SUCCESS = 1,
+  // HTTP Context cannot be prepared.
+  CONTEXT_NOT_READY = 2,
+  // No LST token is available.
+  NO_LST_TOKEN = 3,
+  // Silent auth code failed due sever HTTP error 5XX.
+  HTTP_SERVER_FAILURE = 4,
+  // Silent auth code failed due client HTTP error 4XX.
+  HTTP_CLIENT_FAILURE = 5,
+  // Silent auth code failed due unknown HTTP error.
+  HTTP_UNKNOWN_FAILURE = 6,
+  // Cannot parse HTTP response.
+  RESPONSE_PARSE_FAILURE = 7,
+  // No Auth code in response.
+  NO_AUTH_CODE_IN_RESPONSE = 8,
+  // The size of this enum, keep last.
+  SIZE,
+};
+
 // The values should be listed in ascending order for SIZE a last, for safety.
 // For detailed meaning, please see also to auth.mojom.
 enum class ProvisioningResult : int {
@@ -95,6 +118,7 @@
 void UpdateProvisioningTiming(const base::TimeDelta& elapsed_time,
                               bool success,
                               bool managed);
+void UpdateSilentAuthCodeUMA(OptInSilentAuthCode state);
 
 }  // namespace arc
 
diff --git a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
index d21207d7..62973cf 100644
--- a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.cc
@@ -68,7 +68,7 @@
 void ArcBackgroundAuthCodeFetcher::OnPrepared(
     net::URLRequestContextGetter* request_context_getter) {
   if (!request_context_getter) {
-    base::ResetAndReturn(&callback_).Run(std::string());
+    ReportResult(std::string(), OptInSilentAuthCode::CONTEXT_NOT_READY);
     return;
   }
 
@@ -119,7 +119,7 @@
     const GoogleServiceAuthError& error) {
   VLOG(2) << "Failed to get LST " << error.ToString() << ".";
   ResetFetchers();
-  base::ResetAndReturn(&callback_).Run(std::string());
+  ReportResult(std::string(), OptInSilentAuthCode::NO_LST_TOKEN);
 }
 
 void ArcBackgroundAuthCodeFetcher::OnURLFetchComplete(
@@ -132,7 +132,14 @@
 
   if (response_code != net::HTTP_OK) {
     VLOG(2) << "Server returned wrong response code: " << response_code << ".";
-    base::ResetAndReturn(&callback_).Run(std::string());
+    OptInSilentAuthCode uma_status;
+    if (response_code >= 400 && response_code < 500)
+      uma_status = OptInSilentAuthCode::HTTP_CLIENT_FAILURE;
+    if (response_code >= 500 && response_code < 600)
+      uma_status = OptInSilentAuthCode::HTTP_SERVER_FAILURE;
+    else
+      uma_status = OptInSilentAuthCode::HTTP_UNKNOWN_FAILURE;
+    ReportResult(std::string(), uma_status);
     return;
   }
 
@@ -143,7 +150,7 @@
   if (!auth_code_info) {
     VLOG(2) << "Unable to deserialize auth code json data: " << error_msg
             << ".";
-    base::ResetAndReturn(&callback_).Run(std::string());
+    ReportResult(std::string(), OptInSilentAuthCode::RESPONSE_PARSE_FAILURE);
     return;
   }
 
@@ -151,7 +158,7 @@
       base::DictionaryValue::From(std::move(auth_code_info));
   if (!auth_code_dictionary) {
     NOTREACHED();
-    base::ResetAndReturn(&callback_).Run(std::string());
+    ReportResult(std::string(), OptInSilentAuthCode::RESPONSE_PARSE_FAILURE);
     return;
   }
 
@@ -159,11 +166,11 @@
   if (!auth_code_dictionary->GetString(kToken, &auth_code) ||
       auth_code.empty()) {
     VLOG(2) << "Response does not contain auth code.";
-    base::ResetAndReturn(&callback_).Run(std::string());
+    ReportResult(std::string(), OptInSilentAuthCode::NO_AUTH_CODE_IN_RESPONSE);
     return;
   }
 
-  base::ResetAndReturn(&callback_).Run(auth_code);
+  ReportResult(auth_code, OptInSilentAuthCode::SUCCESS);
 }
 
 void ArcBackgroundAuthCodeFetcher::ResetFetchers() {
@@ -171,4 +178,11 @@
   auth_code_fetcher_.reset();
 }
 
+void ArcBackgroundAuthCodeFetcher::ReportResult(
+    const std::string& auth_code,
+    OptInSilentAuthCode uma_status) {
+  UpdateSilentAuthCodeUMA(uma_status);
+  base::ResetAndReturn(&callback_).Run(auth_code);
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
index b7d41a8..0463868 100644
--- a/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
+++ b/chrome/browser/chromeos/arc/auth/arc_background_auth_code_fetcher.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/arc/arc_auth_context.h"
+#include "chrome/browser/chromeos/arc/arc_optin_uma.h"
 #include "chrome/browser/chromeos/arc/auth/arc_auth_code_fetcher.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -51,6 +52,9 @@
   // net::URLFetcherDelegate:
   void OnURLFetchComplete(const net::URLFetcher* source) override;
 
+  void ReportResult(const std::string& auth_code,
+                    OptInSilentAuthCode uma_status);
+
   // Unowned pointers.
   Profile* const profile_;
   ArcAuthContext* const context_;
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 4b3e12bf..236bc10 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -489,6 +489,7 @@
 
   media::SoundsManager::Create();
 
+  // |arc_service_launcher_| must be initialized before NoteTakingHelper.
   NoteTakingHelper::Initialize();
 
   AccessibilityManager::Initialize();
@@ -797,6 +798,9 @@
 
   BootTimesRecorder::Get()->AddLogoutTimeMarker("UIMessageLoopEnded", true);
 
+  // This must be shut down before |arc_service_launcher_|.
+  NoteTakingHelper::Shutdown();
+
   arc_service_launcher_->Shutdown();
 
   // Unregister CrosSettings observers before CrosSettings is destroyed.
@@ -858,8 +862,6 @@
   if (!chrome::IsRunningInMash())
     MagnificationManager::Shutdown();
 
-  NoteTakingHelper::Shutdown();
-
   media::SoundsManager::Shutdown();
 
   system::StatisticsProvider::GetInstance()->Shutdown();
diff --git a/chrome/browser/chromeos/note_taking_helper.cc b/chrome/browser/chromeos/note_taking_helper.cc
index 653e55c..cfba53e1 100644
--- a/chrome/browser/chromeos/note_taking_helper.cc
+++ b/chrome/browser/chromeos/note_taking_helper.cc
@@ -15,9 +15,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string_split.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_switches.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/common/intent_helper.mojom.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_registry.h"
@@ -40,6 +43,35 @@
     NoteTakingHelper::kProdKeepExtensionId,
 };
 
+// Returns true if |app_id|, a value from prefs::kNoteTakingAppId, looks like
+// it's probably an Android package name rather than a Chrome extension ID.
+bool LooksLikeAndroidPackageName(const std::string& app_id) {
+  // Android package names are required to contain at least one period (see
+  // validateName() in PackageParser.java), while Chrome extension IDs contain
+  // only characters in [a-p].
+  return app_id.find(".") != std::string::npos;
+}
+
+// Returns the helper used for intent-related communication with Android, or
+// null if it's unavailable.
+arc::mojom::IntentHelperInstance* GetIntentHelper(const std::string& method,
+                                                  uint32_t min_version) {
+  return arc::ArcServiceManager::Get()
+      ->arc_bridge_service()
+      ->intent_helper()
+      ->GetInstanceForMethod(method, min_version);
+}
+
+// Creates a new Mojo IntentInfo struct for launching an Android note-taking app
+// with an optional ClipData URI.
+arc::mojom::IntentInfoPtr CreateIntentInfo(const GURL& clip_data_uri) {
+  arc::mojom::IntentInfoPtr intent = arc::mojom::IntentInfo::New();
+  intent->action = NoteTakingHelper::kIntentAction;
+  if (!clip_data_uri.is_empty())
+    intent->clip_data_uri = clip_data_uri.spec();
+  return intent;
+}
+
 // Returns all installed and enabled whitelisted Chrome note-taking apps.
 std::vector<const extensions::Extension*> GetChromeApps(Profile* profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -73,6 +105,8 @@
 
 }  // namespace
 
+const char NoteTakingHelper::kIntentAction[] =
+    "org.chromium.arc.intent.action.CREATE_NOTE";
 const char NoteTakingHelper::kDevKeepExtensionId[] =
     "ogfjaccbdfhecploibfbhighmebiffla";
 const char NoteTakingHelper::kProdKeepExtensionId[] =
@@ -97,6 +131,18 @@
   return g_helper;
 }
 
+void NoteTakingHelper::AddObserver(Observer* observer) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(observer);
+  observers_.AddObserver(observer);
+}
+
+void NoteTakingHelper::RemoveObserver(Observer* observer) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(observer);
+  observers_.RemoveObserver(observer);
+}
+
 NoteTakingAppInfos NoteTakingHelper::GetAvailableApps(Profile* profile) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   NoteTakingAppInfos infos;
@@ -106,6 +152,9 @@
   for (const auto& app : chrome_apps)
     infos.push_back(NoteTakingAppInfo{app->name(), app->id(), false});
 
+  if (arc::ArcSessionManager::Get()->IsAllowedForProfile(profile))
+    infos.insert(infos.end(), android_apps_.begin(), android_apps_.end());
+
   // Determine which app, if any, is preferred.
   const std::string pref_app_id =
       profile->GetPrefs()->GetString(prefs::kNoteTakingAppId);
@@ -149,14 +198,85 @@
     LaunchAppInternal(profile, infos[0].app_id, path);
 }
 
+void NoteTakingHelper::OnArcShutdown() {}
+
+void NoteTakingHelper::OnIntentFiltersUpdated() {
+  if (android_enabled_)
+    UpdateAndroidApps();
+}
+
+void NoteTakingHelper::OnArcOptInChanged(bool enabled) {
+  android_enabled_ = enabled;
+  if (!enabled) {
+    android_apps_.clear();
+    android_apps_received_ = false;
+  }
+  for (auto& observer : observers_)
+    observer.OnAvailableNoteTakingAppsUpdated();
+}
+
 NoteTakingHelper::NoteTakingHelper()
     : launch_chrome_app_callback_(
-          base::Bind(&apps::LaunchPlatformAppWithAction)) {
+          base::Bind(&apps::LaunchPlatformAppWithAction)),
+      weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // Check if the primary profile has already enabled ARC and watch for changes.
+  auto session_manager = arc::ArcSessionManager::Get();
+  session_manager->AddObserver(this);
+  android_enabled_ = session_manager->IsArcEnabled();
+
+  // ArcServiceManager will notify us about changes to the list of available
+  // Android apps.
+  auto service_manager = arc::ArcServiceManager::Get();
+  service_manager->AddObserver(this);
+
+  // If the ARC intent helper is ready, get the Android apps. Otherwise,
+  // UpdateAndroidApps() will be called when ArcServiceManager calls
+  // OnIntentFiltersUpdated().
+  if (android_enabled_ &&
+      arc::ArcServiceManager::Get()
+          ->arc_bridge_service()
+          ->intent_helper()
+          ->has_instance())
+    UpdateAndroidApps();
 }
 
 NoteTakingHelper::~NoteTakingHelper() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // ArcSessionManagerTest shuts down ARC before NoteTakingHelper.
+  if (arc::ArcServiceManager::Get())
+    arc::ArcServiceManager::Get()->RemoveObserver(this);
+  if (arc::ArcSessionManager::Get())
+    arc::ArcSessionManager::Get()->RemoveObserver(this);
+}
+
+void NoteTakingHelper::UpdateAndroidApps() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  auto* helper = GetIntentHelper("RequestIntentHandlerList", 12);
+  if (!helper)
+    return;
+  helper->RequestIntentHandlerList(
+      CreateIntentInfo(GURL()), base::Bind(&NoteTakingHelper::OnGotAndroidApps,
+                                           weak_ptr_factory_.GetWeakPtr()));
+}
+
+void NoteTakingHelper::OnGotAndroidApps(
+    std::vector<arc::mojom::IntentHandlerInfoPtr> handlers) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!android_enabled_)
+    return;
+
+  android_apps_.clear();
+  android_apps_.reserve(handlers.size());
+  for (const auto& it : handlers) {
+    android_apps_.emplace_back(
+        NoteTakingAppInfo{it->name, it->package_name, false});
+  }
+  android_apps_received_ = true;
+
+  for (auto& observer : observers_)
+    observer.OnAvailableNoteTakingAppsUpdated();
 }
 
 bool NoteTakingHelper::LaunchAppInternal(Profile* profile,
@@ -164,17 +284,45 @@
                                          const base::FilePath& path) {
   DCHECK(profile);
 
-  const extensions::ExtensionRegistry* extension_registry =
-      extensions::ExtensionRegistry::Get(profile);
-  const extensions::Extension* app = extension_registry->GetExtensionById(
-      app_id, extensions::ExtensionRegistry::ENABLED);
-  if (!app) {
-    LOG(WARNING) << "Failed to find Chrome note-taking app " << app_id;
-    return false;
+  if (LooksLikeAndroidPackageName(app_id)) {
+    // Android app.
+    if (!arc::ArcSessionManager::Get()->IsAllowedForProfile(profile)) {
+      LOG(WARNING) << "Can't launch Android app " << app_id << " for profile";
+      return false;
+    }
+    auto* helper = GetIntentHelper("HandleIntent", 10);
+    if (!helper)
+      return false;
+
+    GURL clip_data_uri;
+    if (!path.empty()) {
+      if (!file_manager::util::ConvertPathToArcUrl(path, &clip_data_uri) ||
+          !clip_data_uri.is_valid()) {
+        LOG(WARNING) << "Failed to convert " << path.value() << " to ARC URI";
+        return false;
+      }
+    }
+
+    // Only set the package name: leaving the activity name unset enables the
+    // app to rename its activities.
+    arc::mojom::ActivityNamePtr activity = arc::mojom::ActivityName::New();
+    activity->package_name = app_id;
+
+    helper->HandleIntent(CreateIntentInfo(clip_data_uri), std::move(activity));
+  } else {
+    // Chrome app.
+    const extensions::ExtensionRegistry* extension_registry =
+        extensions::ExtensionRegistry::Get(profile);
+    const extensions::Extension* app = extension_registry->GetExtensionById(
+        app_id, extensions::ExtensionRegistry::ENABLED);
+    if (!app) {
+      LOG(WARNING) << "Failed to find Chrome note-taking app " << app_id;
+      return false;
+    }
+    auto action_data = base::MakeUnique<app_runtime::ActionData>();
+    action_data->action_type = app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
+    launch_chrome_app_callback_.Run(profile, app, std::move(action_data), path);
   }
-  auto action_data = base::MakeUnique<app_runtime::ActionData>();
-  action_data->action_type = app_runtime::ActionType::ACTION_TYPE_NEW_NOTE;
-  launch_chrome_app_callback_.Run(profile, app, std::move(action_data), path);
 
   return true;
 }
diff --git a/chrome/browser/chromeos/note_taking_helper.h b/chrome/browser/chromeos/note_taking_helper.h
index 7275e3b..c90b410 100644
--- a/chrome/browser/chromeos/note_taking_helper.h
+++ b/chrome/browser/chromeos/note_taking_helper.h
@@ -8,8 +8,11 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chrome/browser/chromeos/arc/arc_session_manager.h"
+#include "components/arc/arc_service_manager.h"
 
 class Profile;
 
@@ -44,8 +47,19 @@
 using NoteTakingAppInfos = std::vector<NoteTakingAppInfo>;
 
 // Singleton class used to launch a note-taking app.
-class NoteTakingHelper {
+class NoteTakingHelper : public arc::ArcServiceManager::Observer,
+                         public arc::ArcSessionManager::Observer {
  public:
+  // Interface for observing changes to the list of available apps.
+  class Observer {
+   public:
+    virtual ~Observer() = default;
+
+    // Called when the list of available apps that will be returned by
+    // GetAvailableApps() changes or when |android_enabled_| changes state.
+    virtual void OnAvailableNoteTakingAppsUpdated() = 0;
+  };
+
   // Callback used to launch a Chrome app.
   using LaunchChromeAppCallback = base::Callback<void(
       Profile*,
@@ -53,6 +67,9 @@
       std::unique_ptr<extensions::api::app_runtime::ActionData>,
       const base::FilePath&)>;
 
+  // Intent action used to launch Android apps.
+  static const char kIntentAction[];
+
   // Extension IDs for the development and released versions of the Google Keep
   // Chrome app.
   static const char kDevKeepExtensionId[];
@@ -62,11 +79,18 @@
   static void Shutdown();
   static NoteTakingHelper* Get();
 
+  bool android_enabled() const { return android_enabled_; }
+  bool android_apps_received() const { return android_apps_received_; }
+
   void set_launch_chrome_app_callback_for_test(
       const LaunchChromeAppCallback& callback) {
     launch_chrome_app_callback_ = callback;
   }
 
+  // Adds or removes an observer.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
   // Returns a list of available note-taking apps.
   std::vector<NoteTakingAppInfo> GetAvailableApps(Profile* profile);
 
@@ -83,9 +107,22 @@
   // first.
   void LaunchAppForNewNote(Profile* profile, const base::FilePath& path);
 
+  // arc::ArcServiceManager::Observer:
+  void OnArcShutdown() override;
+  void OnIntentFiltersUpdated() override;
+
+  // arc::ArcSessionManager::Observer:
+  void OnArcOptInChanged(bool enabled) override;
+
  private:
   NoteTakingHelper();
-  ~NoteTakingHelper();
+  ~NoteTakingHelper() override;
+
+  // Requests a list of Android note-taking apps from ARC.
+  void UpdateAndroidApps();
+
+  // Handles ARC's response to an earlier UpdateAndroidApps() call.
+  void OnGotAndroidApps(std::vector<arc::mojom::IntentHandlerInfoPtr> handlers);
 
   // Helper method that launches |app_id| (either an Android package name or a
   // Chrome extension ID) to create a new note with an optional attached file at
@@ -94,9 +131,25 @@
                          const std::string& app_id,
                          const base::FilePath& path);
 
+  // True iff ARC is enabled (i.e. per the checkbox on the settings page). Note
+  // that ARC may not be fully started yet when this is true, but it is expected
+  // to start eventually. Similarly, ARC may not be fully shut down yet when
+  // this is false, but will be eventually.
+  bool android_enabled_ = false;
+
+  // This is set to true after |android_apps_| is updated.
+  bool android_apps_received_ = false;
+
   // Callback used to launch Chrome apps. Can be overridden for tests.
   LaunchChromeAppCallback launch_chrome_app_callback_;
 
+  // Cached information about available Android note-taking apps.
+  NoteTakingAppInfos android_apps_;
+
+  base::ObserverList<Observer> observers_;
+
+  base::WeakPtrFactory<NoteTakingHelper> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(NoteTakingHelper);
 };
 
diff --git a/chrome/browser/chromeos/note_taking_helper_unittest.cc b/chrome/browser/chromeos/note_taking_helper_unittest.cc
index c04a2a9e..b631851 100644
--- a/chrome/browser/chromeos/note_taking_helper_unittest.cc
+++ b/chrome/browser/chromeos/note_taking_helper_unittest.cc
@@ -11,21 +11,37 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
+#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/common/intent_helper.mojom.h"
+#include "components/arc/test/fake_intent_helper_instance.h"
 #include "extensions/common/api/app_runtime.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_id.h"
 #include "extensions/common/value_builder.h"
+#include "url/gurl.h"
 
 namespace app_runtime = extensions::api::app_runtime;
 
+using arc::mojom::IntentHandlerInfo;
+using arc::mojom::IntentHandlerInfoPtr;
+using HandledIntent = arc::FakeIntentHelperInstance::HandledIntent;
+
 namespace chromeos {
 namespace {
 
-// Helper functions returning strings that can be used for comparison.
+// Helper functions returning strings that can be used to compare information
+// about available note-taking apps.
 std::string GetAppString(const std::string& id,
                          const std::string& name,
                          bool preferred) {
@@ -35,6 +51,55 @@
   return GetAppString(info.app_id, info.name, info.preferred);
 }
 
+// Helper functions returning strings that can be used to compare launched
+// intents.
+std::string GetIntentString(const std::string& package,
+                            const std::string& clip_data_uri) {
+  return base::StringPrintf(
+      "%s %s", package.c_str(),
+      clip_data_uri.empty() ? "[unset]" : clip_data_uri.c_str());
+}
+std::string GetIntentString(const HandledIntent& intent) {
+  EXPECT_EQ(NoteTakingHelper::kIntentAction, intent.intent->action);
+  return GetIntentString(
+      intent.activity->package_name,
+      (intent.intent->clip_data_uri ? *intent.intent->clip_data_uri : ""));
+}
+
+// Creates an ARC IntentHandlerInfo object.
+IntentHandlerInfoPtr CreateIntentHandlerInfo(const std::string& name,
+                                             const std::string& package) {
+  IntentHandlerInfoPtr handler = IntentHandlerInfo::New();
+  handler->name = name;
+  handler->package_name = package;
+  return handler;
+}
+
+// Converts a filesystem path to an ARC URL.
+std::string GetArcUrl(const base::FilePath& path) {
+  GURL url;
+  EXPECT_TRUE(file_manager::util::ConvertPathToArcUrl(path, &url));
+  return url.spec();
+}
+
+// Implementation of NoteTakingHelper::Observer for testing.
+class TestObserver : public NoteTakingHelper::Observer {
+ public:
+  TestObserver() { NoteTakingHelper::Get()->AddObserver(this); }
+  ~TestObserver() override { NoteTakingHelper::Get()->RemoveObserver(this); }
+
+  int num_updates() const { return num_updates_; }
+
+ private:
+  // NoteTakingHelper::Observer:
+  void OnAvailableNoteTakingAppsUpdated() override { num_updates_++; }
+
+  // Number of times that OnAvailableNoteTakingAppsUpdated() has been called.
+  int num_updates_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
 }  // namespace
 
 class NoteTakingHelperTest : public BrowserWithTestWindowTest {
@@ -43,6 +108,15 @@
   ~NoteTakingHelperTest() override = default;
 
   void SetUp() override {
+    // This is needed to avoid log spam due to ArcSessionManager's
+    // RemoveArcData() calls failing.
+    if (DBusThreadManager::IsInitialized())
+      DBusThreadManager::Shutdown();
+    session_manager_client_ = new FakeSessionManagerClient();
+    session_manager_client_->set_arc_available(true);
+    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
+        std::unique_ptr<SessionManagerClient>(session_manager_client_));
+
     BrowserWithTestWindowTest::SetUp();
 
     extensions::TestExtensionSystem* extension_system =
@@ -57,9 +131,11 @@
   void TearDown() override {
     if (initialized_) {
       NoteTakingHelper::Shutdown();
+      arc_test_.TearDown();
     }
     extensions::ExtensionSystem::Get(profile())->Shutdown();
     BrowserWithTestWindowTest::TearDown();
+    DBusThreadManager::Shutdown();
   }
 
  protected:
@@ -69,18 +145,34 @@
     base::FilePath path;
   };
 
+  // Options that can be passed to Init().
+  enum InitFlags {
+    ENABLE_ARC = 1 << 0,
+    ENABLE_PALETTE = 1 << 1,
+  };
+
   static NoteTakingHelper* helper() { return NoteTakingHelper::Get(); }
 
-  // Initializes NoteTakingHelper.
-  void Init() {
+  // Initializes ARC and NoteTakingHelper. |flags| contains OR-ed together
+  // InitFlags values.
+  void Init(uint32_t flags) {
     ASSERT_FALSE(initialized_);
     initialized_ = true;
 
-    if (palette_enabled_) {
+    profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, flags & ENABLE_ARC);
+    arc_test_.SetUp(profile());
+    arc::ArcServiceManager::Get()
+        ->arc_bridge_service()
+        ->intent_helper()
+        ->SetInstance(&intent_helper_);
+
+    if (flags & ENABLE_PALETTE) {
       base::CommandLine::ForCurrentProcess()->AppendSwitch(
           ash::switches::kAshEnablePalette);
     }
 
+    // TODO(derat): Sigh, something in ArcAppTest appears to be re-enabling ARC.
+    profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, flags & ENABLE_ARC);
     NoteTakingHelper::Initialize();
     NoteTakingHelper::Get()->set_launch_chrome_app_callback_for_test(base::Bind(
         &NoteTakingHelperTest::LaunchChromeApp, base::Unretained(this)));
@@ -124,12 +216,11 @@
                           extensions::UnloadedExtensionInfo::REASON_UNINSTALL);
   }
 
-  // Should Init() enable the palette feature?
-  bool palette_enabled_ = true;
-
   // Info about launched Chrome apps, in the order they were launched.
   std::vector<ChromeAppLaunchInfo> launched_chrome_apps_;
 
+  arc::FakeIntentHelperInstance intent_helper_;
+
  private:
   // Callback registered with the helper to record Chrome app launch requests.
   void LaunchChromeApp(Profile* passed_profile,
@@ -145,13 +236,16 @@
   // Has Init() been called?
   bool initialized_ = false;
 
+  FakeSessionManagerClient* session_manager_client_ = nullptr;  // Not owned.
+
+  ArcAppTest arc_test_;
+
   DISALLOW_COPY_AND_ASSIGN(NoteTakingHelperTest);
 };
 
 TEST_F(NoteTakingHelperTest, PaletteNotEnabled) {
   // Without the palette enabled, IsAppAvailable() should return false.
-  palette_enabled_ = false;
-  Init();
+  Init(0);
   auto extension =
       CreateExtension(NoteTakingHelper::kProdKeepExtensionId, "Keep");
   InstallExtension(extension.get());
@@ -159,12 +253,11 @@
 }
 
 TEST_F(NoteTakingHelperTest, ListChromeApps) {
-  Init();
+  Init(ENABLE_PALETTE);
 
   // Start out without any note-taking apps installed.
   EXPECT_FALSE(helper()->IsAppAvailable(profile()));
-  std::vector<NoteTakingAppInfo> apps = helper()->GetAvailableApps(profile());
-  EXPECT_TRUE(apps.empty());
+  EXPECT_TRUE(helper()->GetAvailableApps(profile()).empty());
 
   // If only the prod version of the app is installed, it should be returned.
   const std::string kProdName = "Google Keep [prod]";
@@ -172,7 +265,7 @@
       CreateExtension(NoteTakingHelper::kProdKeepExtensionId, kProdName);
   InstallExtension(prod_extension.get());
   EXPECT_TRUE(helper()->IsAppAvailable(profile()));
-  apps = helper()->GetAvailableApps(profile());
+  std::vector<NoteTakingAppInfo> apps = helper()->GetAvailableApps(profile());
   ASSERT_EQ(1u, apps.size());
   EXPECT_EQ(
       GetAppString(NoteTakingHelper::kProdKeepExtensionId, kProdName, false),
@@ -220,7 +313,7 @@
 }
 
 TEST_F(NoteTakingHelperTest, LaunchChromeApp) {
-  Init();
+  Init(ENABLE_PALETTE);
   auto extension =
       CreateExtension(NoteTakingHelper::kProdKeepExtensionId, "Keep");
   InstallExtension(extension.get());
@@ -235,7 +328,7 @@
 }
 
 TEST_F(NoteTakingHelperTest, FallBackIfPreferredAppUnavailable) {
-  Init();
+  Init(ENABLE_PALETTE);
   auto prod_extension =
       CreateExtension(NoteTakingHelper::kProdKeepExtensionId, "prod");
   InstallExtension(prod_extension.get());
@@ -258,4 +351,154 @@
   EXPECT_EQ(NoteTakingHelper::kDevKeepExtensionId, launched_chrome_apps_[0].id);
 }
 
+TEST_F(NoteTakingHelperTest, ArcInitiallyDisabled) {
+  Init(ENABLE_PALETTE);
+  EXPECT_FALSE(helper()->android_enabled());
+  EXPECT_FALSE(helper()->android_apps_received());
+
+  // When ARC is enabled, the helper's members should be updated accordingly.
+  profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true);
+  EXPECT_TRUE(helper()->android_enabled());
+  EXPECT_FALSE(helper()->android_apps_received());
+
+  // After the callback to receive intent handlers has run, the "apps received"
+  // member should be updated (even if there aren't any apps).
+  helper()->OnIntentFiltersUpdated();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(helper()->android_enabled());
+  EXPECT_TRUE(helper()->android_apps_received());
+}
+
+TEST_F(NoteTakingHelperTest, ListAndroidApps) {
+  // Add two Android apps.
+  std::vector<IntentHandlerInfoPtr> handlers;
+  const std::string kName1 = "App 1";
+  const std::string kPackage1 = "org.chromium.package1";
+  handlers.emplace_back(CreateIntentHandlerInfo(kName1, kPackage1));
+  const std::string kName2 = "App 2";
+  const std::string kPackage2 = "org.chromium.package2";
+  handlers.emplace_back(CreateIntentHandlerInfo(kName2, kPackage2));
+  intent_helper_.SetIntentHandlers(NoteTakingHelper::kIntentAction,
+                                   std::move(handlers));
+
+  // NoteTakingHelper should make an async request for Android apps when
+  // constructed.
+  Init(ENABLE_PALETTE | ENABLE_ARC);
+  EXPECT_TRUE(helper()->android_enabled());
+  EXPECT_FALSE(helper()->android_apps_received());
+  EXPECT_TRUE(helper()->GetAvailableApps(profile()).empty());
+
+  // The apps should be listed after the callback has had a chance to run.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(helper()->android_enabled());
+  EXPECT_TRUE(helper()->android_apps_received());
+  EXPECT_TRUE(helper()->IsAppAvailable(profile()));
+  std::vector<NoteTakingAppInfo> apps = helper()->GetAvailableApps(profile());
+  ASSERT_EQ(2u, apps.size());
+  EXPECT_EQ(GetAppString(kPackage1, kName1, false), GetAppString(apps[0]));
+  EXPECT_EQ(GetAppString(kPackage2, kName2, false), GetAppString(apps[1]));
+
+  // Disable ARC and check that the apps are no longer returned.
+  profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
+  EXPECT_FALSE(helper()->android_enabled());
+  EXPECT_FALSE(helper()->android_apps_received());
+  EXPECT_FALSE(helper()->IsAppAvailable(profile()));
+  EXPECT_TRUE(helper()->GetAvailableApps(profile()).empty());
+}
+
+TEST_F(NoteTakingHelperTest, LaunchAndroidApp) {
+  const std::string kPackage1 = "org.chromium.package1";
+  std::vector<IntentHandlerInfoPtr> handlers;
+  handlers.emplace_back(CreateIntentHandlerInfo("App 1", kPackage1));
+  intent_helper_.SetIntentHandlers(NoteTakingHelper::kIntentAction,
+                                   std::move(handlers));
+
+  Init(ENABLE_PALETTE | ENABLE_ARC);
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(helper()->IsAppAvailable(profile()));
+
+  // The installed app should be launched.
+  helper()->LaunchAppForNewNote(profile(), base::FilePath());
+  ASSERT_EQ(1u, intent_helper_.handled_intents().size());
+  EXPECT_EQ(GetIntentString(kPackage1, ""),
+            GetIntentString(intent_helper_.handled_intents()[0]));
+
+  // Install a second app and set it as the preferred app.
+  const std::string kPackage2 = "org.chromium.package2";
+  handlers.emplace_back(CreateIntentHandlerInfo("App 1", kPackage1));
+  handlers.emplace_back(CreateIntentHandlerInfo("App 2", kPackage2));
+  intent_helper_.SetIntentHandlers(NoteTakingHelper::kIntentAction,
+                                   std::move(handlers));
+  helper()->OnIntentFiltersUpdated();
+  base::RunLoop().RunUntilIdle();
+  helper()->SetPreferredApp(profile(), kPackage2);
+
+  // The second app should be launched now.
+  intent_helper_.clear_handled_intents();
+  helper()->LaunchAppForNewNote(profile(), base::FilePath());
+  ASSERT_EQ(1u, intent_helper_.handled_intents().size());
+  EXPECT_EQ(GetIntentString(kPackage2, ""),
+            GetIntentString(intent_helper_.handled_intents()[0]));
+}
+
+TEST_F(NoteTakingHelperTest, LaunchAndroidAppWithPath) {
+  const std::string kPackage = "org.chromium.package";
+  std::vector<IntentHandlerInfoPtr> handlers;
+  handlers.emplace_back(CreateIntentHandlerInfo("App", kPackage));
+  intent_helper_.SetIntentHandlers(NoteTakingHelper::kIntentAction,
+                                   std::move(handlers));
+
+  Init(ENABLE_PALETTE | ENABLE_ARC);
+  base::RunLoop().RunUntilIdle();
+  ASSERT_TRUE(helper()->IsAppAvailable(profile()));
+
+  const base::FilePath kDownloadedPath(
+      file_manager::util::GetDownloadsFolderForProfile(profile()).Append(
+          "image.jpg"));
+  helper()->LaunchAppForNewNote(profile(), kDownloadedPath);
+  ASSERT_EQ(1u, intent_helper_.handled_intents().size());
+  EXPECT_EQ(GetIntentString(kPackage, GetArcUrl(kDownloadedPath)),
+            GetIntentString(intent_helper_.handled_intents()[0]));
+
+  const base::FilePath kRemovablePath =
+      base::FilePath(file_manager::util::kRemovableMediaPath)
+          .Append("image.jpg");
+  intent_helper_.clear_handled_intents();
+  helper()->LaunchAppForNewNote(profile(), kRemovablePath);
+  ASSERT_EQ(1u, intent_helper_.handled_intents().size());
+  EXPECT_EQ(GetIntentString(kPackage, GetArcUrl(kRemovablePath)),
+            GetIntentString(intent_helper_.handled_intents()[0]));
+
+  // When a path that isn't accessible to ARC is passed, the request should be
+  // dropped.
+  intent_helper_.clear_handled_intents();
+  helper()->LaunchAppForNewNote(profile(), base::FilePath("/bad/path.jpg"));
+  EXPECT_TRUE(intent_helper_.handled_intents().empty());
+}
+
+TEST_F(NoteTakingHelperTest, NotifyObserver) {
+  Init(ENABLE_PALETTE | ENABLE_ARC);
+  TestObserver observer;
+
+  // Let the app-fetching callback run and check that the observer is notified.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, observer.num_updates());
+
+  // Disabling and enabling ARC should also notify the observer (and enabling
+  // should request apps again).
+  profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, false);
+  EXPECT_EQ(2, observer.num_updates());
+  profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true);
+  EXPECT_EQ(3, observer.num_updates());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(4, observer.num_updates());
+
+  // Update intent filters and check that the observer is notified again after
+  // apps are received.
+  helper()->OnIntentFiltersUpdated();
+  EXPECT_EQ(4, observer.num_updates());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(5, observer.num_updates());
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/domain_reliability/browsertest.cc b/chrome/browser/domain_reliability/browsertest.cc
new file mode 100644
index 0000000..1954b78c
--- /dev/null
+++ b/chrome/browser/domain_reliability/browsertest.cc
@@ -0,0 +1,101 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/domain_reliability/service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/domain_reliability/service.h"
+#include "net/base/net_errors.h"
+#include "net/test/url_request/url_request_failed_job.h"
+#include "url/gurl.h"
+
+namespace domain_reliability {
+
+class DomainReliabilityBrowserTest : public InProcessBrowserTest {
+ public:
+  DomainReliabilityBrowserTest() {
+    net::URLRequestFailedJob::AddUrlHandler();
+  }
+
+  ~DomainReliabilityBrowserTest() override {}
+
+  // Note: In an ideal world, instead of appending the command-line switch and
+  // manually setting discard_uploads to false, Domain Reliability would
+  // continuously monitor the metrics reporting pref, and the test could just
+  // set the pref.
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kEnableDomainReliability);
+  }
+
+  void SetUpOnMainThread() override {
+    InProcessBrowserTest::SetUpOnMainThread();
+
+    DomainReliabilityService* service = GetService();
+    if (service)
+      service->SetDiscardUploadsForTesting(false);
+  }
+
+  DomainReliabilityService* GetService() {
+    return DomainReliabilityServiceFactory::GetForBrowserContext(
+        browser()->profile());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DomainReliabilityBrowserTest);
+};
+
+class DomainReliabilityDisabledBrowserTest
+    : public DomainReliabilityBrowserTest {
+ protected:
+  DomainReliabilityDisabledBrowserTest() {}
+
+  ~DomainReliabilityDisabledBrowserTest() override {}
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kDisableDomainReliability);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DomainReliabilityDisabledBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DomainReliabilityDisabledBrowserTest,
+                       ServiceNotCreated) {
+  EXPECT_FALSE(GetService());
+}
+
+IN_PROC_BROWSER_TEST_F(DomainReliabilityBrowserTest, ServiceCreated) {
+  EXPECT_TRUE(GetService());
+}
+
+IN_PROC_BROWSER_TEST_F(DomainReliabilityBrowserTest, UploadAtShutdown) {
+  DomainReliabilityService* service = GetService();
+
+  auto config = base::MakeUnique<DomainReliabilityConfig>();
+  config->origin = GURL("https://localhost/");
+  config->include_subdomains = false;
+  config->collectors.push_back(new GURL(
+      net::URLRequestFailedJob::GetMockHttpsUrl(net::ERR_IO_PENDING)));
+  config->success_sample_rate = 1.0;
+  config->failure_sample_rate = 1.0;
+  service->AddContextForTesting(std::move(config));
+
+  ui_test_utils::NavigateToURL(browser(), GURL("https://localhost/"));
+
+  service->ForceUploadsForTesting();
+
+  // At this point, there is an upload pending. If everything goes well, the
+  // test will finish, destroy the profile, and Domain Reliability will shut
+  // down properly. If things go awry, it may crash as terminating the pending
+  // upload calls into already-destroyed parts of the component.
+}
+
+}  // namespace domain_reliability
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc
index 7b5301f..ba385dce 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -12,7 +12,6 @@
 #include "base/containers/small_map.h"
 #include "base/guid.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/media/router/create_presentation_connection_request.h"
 #include "chrome/browser/media/router/media_route.h"
@@ -58,14 +57,10 @@
 
 // Gets the last committed URL for the render frame specified by
 // |render_frame_host_id|.
-GURL GetLastCommittedURLForFrame(RenderFrameHostId render_frame_host_id,
-                                 content::WebContents* web_contents) {
+GURL GetLastCommittedURLForFrame(RenderFrameHostId render_frame_host_id) {
   RenderFrameHost* render_frame_host = RenderFrameHost::FromID(
       render_frame_host_id.first, render_frame_host_id.second);
-  // crbug.com/663740: The RFH may not be associated with the frame tree; in
-  // that case, GetLastCommittedOrigin() may crash.
-  if (!render_frame_host ||
-      !base::ContainsValue(web_contents->GetAllFrames(), render_frame_host))
+  if (!render_frame_host)
     return GURL();
 
   // TODO(crbug.com/632623): Use url::Origin in place of GURL for origins
@@ -241,8 +236,7 @@
 
   sinks_observer.reset(new PresentationMediaSinksObserver(
       router_, listener, source,
-      GetLastCommittedURLForFrame(render_frame_host_id_, web_contents_)
-          .GetOrigin()));
+      GetLastCommittedURLForFrame(render_frame_host_id_).GetOrigin()));
 
   if (!sinks_observer->Init()) {
     url_to_sinks_observer_.erase(source.id());
@@ -566,8 +560,7 @@
     ClearDefaultPresentationRequest();
   } else {
     DCHECK(!callback.is_null());
-    GURL frame_url(
-        GetLastCommittedURLForFrame(render_frame_host_id, web_contents_));
+    GURL frame_url(GetLastCommittedURLForFrame(render_frame_host_id));
     PresentationRequest request(render_frame_host_id, default_presentation_urls,
                                 frame_url);
     default_presentation_started_callback_ = callback;
@@ -808,7 +801,7 @@
   std::unique_ptr<CreatePresentationConnectionRequest> request(
       new CreatePresentationConnectionRequest(
           render_frame_host_id, presentation_urls,
-          GetLastCommittedURLForFrame(render_frame_host_id, web_contents_),
+          GetLastCommittedURLForFrame(render_frame_host_id),
           base::Bind(&PresentationServiceDelegateImpl::OnStartSessionSucceeded,
                      weak_factory_.GetWeakPtr(), render_process_id,
                      render_frame_id, success_cb),
@@ -839,7 +832,7 @@
   }
 
   const url::Origin& origin = url::Origin(GetLastCommittedURLForFrame(
-      RenderFrameHostId(render_process_id, render_frame_id), web_contents_));
+      RenderFrameHostId(render_process_id, render_frame_id)));
 
 #if !defined(OS_ANDROID)
   if (IsAutoJoinPresentationId(presentation_id) &&
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 98a9764..8cfc600 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -44,6 +44,7 @@
 #include "chrome/common/features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/installer/util/util_constants.h"
+#include "components/browser_watcher/stability_debugging.h"
 #include "components/metrics/call_stack_profile_metrics_provider.h"
 #include "components/metrics/drive_metrics_provider.h"
 #include "components/metrics/file_metrics_provider.h"
@@ -105,7 +106,6 @@
 #include "chrome/common/metrics_constants_util_win.h"
 #include "chrome/install_static/install_util.h"
 #include "chrome/installer/util/browser_distribution.h"
-#include "components/browser_watcher/stability_debugging_win.h"
 #include "components/browser_watcher/watcher_metrics_provider_win.h"
 #endif
 
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 19a65c5..6bc5cf0e 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -151,8 +151,7 @@
       force_google_safe_search_(nullptr),
       force_youtube_restrict_(nullptr),
       allowed_domains_for_apps_(nullptr),
-      url_blacklist_manager_(nullptr),
-      domain_reliability_monitor_(nullptr),
+      url_blacklist_manager_(NULL),
       experimental_web_platform_features_enabled_(
           base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kEnableExperimentalWebPlatformFeatures)),
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h
index de4cb05..241cf2c 100644
--- a/chrome/browser/net/chrome_network_delegate.h
+++ b/chrome/browser/net/chrome_network_delegate.h
@@ -17,6 +17,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/net/safe_search_util.h"
+#include "components/domain_reliability/monitor.h"
 #include "components/prefs/pref_member.h"
 #include "net/base/network_delegate_impl.h"
 
@@ -109,8 +110,8 @@
   }
 
   void set_domain_reliability_monitor(
-      domain_reliability::DomainReliabilityMonitor* monitor) {
-    domain_reliability_monitor_ = monitor;
+      std::unique_ptr<domain_reliability::DomainReliabilityMonitor> monitor) {
+    domain_reliability_monitor_ = std::move(monitor);
   }
 
   void set_data_use_aggregator(
@@ -203,7 +204,8 @@
 
   // Weak, owned by our owner.
   const policy::URLBlacklistManager* url_blacklist_manager_;
-  domain_reliability::DomainReliabilityMonitor* domain_reliability_monitor_;
+  std::unique_ptr<domain_reliability::DomainReliabilityMonitor>
+      domain_reliability_monitor_;
 
   // When true, allow access to all file:// URLs.
   static bool g_allow_file_access_;
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
index 0ebcc93..d0aada1 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
@@ -39,10 +39,18 @@
                                                       : it->second;
 }
 
-// Returns true if persistent caching has been enabled in the field trial.
-bool persistent_caching_enabled() {
+// Returns true if writing to the persistent cache has been enabled via field
+// trial.
+bool persistent_cache_writing_enabled() {
   return GetStringValueForVariationParamWithDefaultValue(
-             "persistent_caching_enabled", "false") == "true";
+             "persistent_cache_writing_enabled", "false") == "true";
+}
+
+// Returns true if reading from the persistent cache has been enabled via field
+// trial.
+bool persistent_cache_reading_enabled() {
+  return GetStringValueForVariationParamWithDefaultValue(
+             "persistent_cache_reading_enabled", "false") == "true";
 }
 
 // PrefDelegateImpl writes the provided dictionary value to the network quality
@@ -59,17 +67,19 @@
 
   void SetDictionaryValue(const base::DictionaryValue& value) override {
     DCHECK(thread_checker_.CalledOnValidThread());
-    if (!persistent_caching_enabled())
+    if (!persistent_cache_writing_enabled())
       return;
 
     pref_service_->Set(path_, value);
     UMA_HISTOGRAM_COUNTS_1000("NQE.Prefs.WriteCount", 1);
   }
 
-  const base::DictionaryValue& GetDictionaryValue() override {
+  std::unique_ptr<base::DictionaryValue> GetDictionaryValue() override {
     DCHECK(thread_checker_.CalledOnValidThread());
+    if (!persistent_cache_reading_enabled())
+      return base::WrapUnique(new base::DictionaryValue());
     UMA_HISTOGRAM_COUNTS_1000("NQE.Prefs.ReadCount", 1);
-    return *pref_service_->GetDictionary(path_);
+    return pref_service_->GetDictionary(path_)->CreateDeepCopy();
   }
 
  private:
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service_browsertest.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service_browsertest.cc
index 4a433ce9..571e4f6 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service_browsertest.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service_browsertest.cc
@@ -57,19 +57,21 @@
  public:
   UINetworkQualityEstimatorServiceBrowserTest() {}
 
-  // Enables persistent caching if |persistent_caching_enabled| is true.
-  // Verifies that the network quality prefs are written correctly, and that
-  // they are written only if the persistent caching was enabled.
-  void VerifyWritingReadingPrefs(bool persistent_caching_enabled) {
-    if (persistent_caching_enabled) {
-      std::map<std::string, std::string> variation_params;
-      variation_params["persistent_caching_enabled"] = "true";
+  // Verifies that the network quality prefs are written amd read correctly.
+  void VerifyWritingReadingPrefs(bool persistent_cache_writing_enabled,
+                                 bool persistent_cache_reading_enabled) {
+    std::map<std::string, std::string> variation_params;
 
-      variations::AssociateVariationParams("NetworkQualityEstimator", "Enabled",
-                                           variation_params);
-      base::FieldTrialList::CreateFieldTrial("NetworkQualityEstimator",
-                                             "Enabled");
-    }
+    if (persistent_cache_writing_enabled)
+      variation_params["persistent_cache_writing_enabled"] = "true";
+
+    if (persistent_cache_reading_enabled)
+      variation_params["persistent_cache_reading_enabled"] = "true";
+
+    variations::AssociateVariationParams("NetworkQualityEstimator", "Enabled",
+                                         variation_params);
+    base::FieldTrialList::CreateFieldTrial("NetworkQualityEstimator",
+                                           "Enabled");
 
     // Verifies that NQE notifying EffectiveConnectionTypeObservers causes the
     // UINetworkQualityEstimatorService to receive an updated
@@ -101,7 +103,7 @@
 
       // Prefs are written only if the network id was available, and persistent
       // caching was enabled.
-      EXPECT_NE(network_id_available && persistent_caching_enabled,
+      EXPECT_NE(network_id_available && persistent_cache_writing_enabled,
                 histogram_tester.GetAllSamples("NQE.Prefs.WriteCount").empty());
       histogram_tester.ExpectTotalCount("NQE.Prefs.ReadCount", 0);
 
@@ -119,7 +121,7 @@
 
       // Prefs are written only if the network id was available, and persistent
       // caching was enabled.
-      EXPECT_NE(network_id_available && persistent_caching_enabled,
+      EXPECT_NE(network_id_available && persistent_cache_writing_enabled,
                 histogram_tester.GetAllSamples("NQE.Prefs.WriteCount").empty());
       histogram_tester.ExpectTotalCount("NQE.Prefs.ReadCount", 0);
 
@@ -131,9 +133,13 @@
     std::map<net::nqe::internal::NetworkID,
              net::nqe::internal::CachedNetworkQuality>
         read_prefs = nqe_service->ForceReadPrefsForTesting();
-    EXPECT_EQ(network_id_available && persistent_caching_enabled ? 1u : 0u,
+    EXPECT_EQ(network_id_available && persistent_cache_writing_enabled &&
+                      persistent_cache_reading_enabled
+                  ? 1u
+                  : 0u,
               read_prefs.size());
-    if (network_id_available && persistent_caching_enabled) {
+    if (network_id_available && persistent_cache_writing_enabled &&
+        persistent_cache_reading_enabled) {
       // Verify that the cached network quality was written correctly.
       EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
                 read_prefs.begin()->second.effective_connection_type());
@@ -214,12 +220,18 @@
 // via field trial.
 IN_PROC_BROWSER_TEST_F(UINetworkQualityEstimatorServiceBrowserTest,
                        WritingToPrefsDisabled) {
-  VerifyWritingReadingPrefs(false);
+  VerifyWritingReadingPrefs(false, true);
 }
 
-// Verify that prefs are writen when writing of the prefs is enabled via field
-// trial.
+// Verify that prefs are not read when reading of the prefs is not enabled
+// via field trial.
 IN_PROC_BROWSER_TEST_F(UINetworkQualityEstimatorServiceBrowserTest,
-                       WritingToPrefsEnabled) {
-  VerifyWritingReadingPrefs(true);
+                       ReadingFromPrefsDisabled) {
+  VerifyWritingReadingPrefs(true, false);
+}
+
+// Verify that prefs are writen and read correctly.
+IN_PROC_BROWSER_TEST_F(UINetworkQualityEstimatorServiceBrowserTest,
+                       WritingReadingToPrefsEnabled) {
+  VerifyWritingReadingPrefs(true, true);
 }
diff --git a/chrome/browser/notifications/notification_permission_context_unittest.cc b/chrome/browser/notifications/notification_permission_context_unittest.cc
index 1c878d9..d6239a6 100644
--- a/chrome/browser/notifications/notification_permission_context_unittest.cc
+++ b/chrome/browser/notifications/notification_permission_context_unittest.cc
@@ -5,9 +5,8 @@
 #include "chrome/browser/notifications/notification_permission_context.h"
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/time/time.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
@@ -81,24 +80,19 @@
 class NotificationPermissionContextTest
     : public ChromeRenderViewHostTestHarness {
  public:
-  scoped_refptr<base::TestMockTimeTaskRunner> SwitchToMockTime() {
-    old_task_runner_ = base::ThreadTaskRunnerHandle::Get();
-    scoped_refptr<base::TestMockTimeTaskRunner> task_runner(
-        new base::TestMockTimeTaskRunner(base::Time::Now(),
-                                         base::TimeTicks::Now()));
-    base::MessageLoop::current()->SetTaskRunner(task_runner);
-    return task_runner;
-  }
-
   void TearDown() override {
-    if (old_task_runner_) {
-      base::MessageLoop::current()->SetTaskRunner(old_task_runner_);
-      old_task_runner_ = nullptr;
-    }
+    mock_time_task_runner_.reset();
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
  protected:
+  base::TestMockTimeTaskRunner* SwitchToMockTime() {
+    EXPECT_FALSE(mock_time_task_runner_);
+    mock_time_task_runner_ =
+        base::MakeUnique<base::ScopedMockTimeMessageLoopTaskRunner>();
+    return mock_time_task_runner_->task_runner();
+  }
+
   void UpdateContentSetting(NotificationPermissionContext* context,
                             const GURL& requesting_origin,
                             const GURL& embedding_origin,
@@ -107,7 +101,8 @@
   }
 
  private:
-  scoped_refptr<base::SingleThreadTaskRunner> old_task_runner_;
+  std::unique_ptr<base::ScopedMockTimeMessageLoopTaskRunner>
+      mock_time_task_runner_;
 };
 
 // Web Notification permission requests will completely ignore the embedder
@@ -215,7 +210,7 @@
                                web_contents()->GetMainFrame()->GetRoutingID(),
                                -1);
 
-  scoped_refptr<base::TestMockTimeTaskRunner> task_runner(SwitchToMockTime());
+  base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
   ASSERT_EQ(0, permission_context.permission_set_count());
   ASSERT_FALSE(permission_context.last_permission_set_persisted());
@@ -281,7 +276,7 @@
                                web_contents()->GetMainFrame()->GetRoutingID(),
                                -1);
 
-  scoped_refptr<base::TestMockTimeTaskRunner> task_runner(SwitchToMockTime());
+  base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
   content::PermissionManager* permission_manager =
       PermissionManagerFactory::GetForProfile(
@@ -318,7 +313,7 @@
                                 web_contents()->GetMainFrame()->GetRoutingID(),
                                 1);
 
-  scoped_refptr<base::TestMockTimeTaskRunner> task_runner(SwitchToMockTime());
+  base::TestMockTimeTaskRunner* task_runner = SwitchToMockTime();
 
   ASSERT_EQ(0, permission_context.permission_set_count());
   ASSERT_FALSE(permission_context.last_permission_set_persisted());
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 87e8b89..95dd07c 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -171,6 +171,8 @@
   lazy_params->extensions_cookie_path = extensions_cookie_path;
   lazy_params->session_cookie_mode = session_cookie_mode;
   lazy_params->special_storage_policy = special_storage_policy;
+  lazy_params->domain_reliability_monitor =
+      std::move(domain_reliability_monitor);
 
   PrefService* pref_service = profile_->GetPrefs();
   lazy_params->http_server_properties_manager.reset(
@@ -188,11 +190,10 @@
   io_data_->app_media_cache_max_size_ = media_cache_max_size;
 
   io_data_->predictor_.reset(predictor);
-  io_data_->domain_reliability_monitor_ = std::move(domain_reliability_monitor);
 
   io_data_->InitializeMetricsEnabledStateOnUIThread();
-  if (io_data_->domain_reliability_monitor_)
-    io_data_->domain_reliability_monitor_->MoveToNetworkThread();
+  if (io_data_->lazy_params_->domain_reliability_monitor)
+    io_data_->lazy_params_->domain_reliability_monitor->MoveToNetworkThread();
 
   io_data_->previews_io_data_ = base::MakeUnique<previews::PreviewsIOData>(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
@@ -426,11 +427,15 @@
 ProfileImplIOData::ProfileImplIOData()
     : ProfileIOData(Profile::REGULAR_PROFILE),
       http_server_properties_manager_(NULL),
+      domain_reliability_monitor_(nullptr),
       app_cache_max_size_(0),
       app_media_cache_max_size_(0) {
 }
 
 ProfileImplIOData::~ProfileImplIOData() {
+  if (domain_reliability_monitor_)
+    domain_reliability_monitor_->Shutdown();
+
   DestroyResourceContext();
 
   if (media_request_context_)
@@ -459,13 +464,18 @@
   IOThread* const io_thread = profile_params->io_thread;
   IOThread::Globals* const io_thread_globals = io_thread->globals();
 
-  if (domain_reliability_monitor_) {
-    domain_reliability::DomainReliabilityMonitor* monitor =
-        domain_reliability_monitor_.get();
-    monitor->InitURLRequestContext(main_context);
-    monitor->AddBakedInConfigs();
-    monitor->SetDiscardUploads(!GetMetricsEnabledStateOnIOThread());
-    chrome_network_delegate->set_domain_reliability_monitor(monitor);
+  if (lazy_params_->domain_reliability_monitor) {
+    // Hold on to a raw pointer to call Shutdown() in ~ProfileImplIOData.
+    domain_reliability_monitor_ =
+        lazy_params_->domain_reliability_monitor.get();
+
+    domain_reliability_monitor_->InitURLRequestContext(main_context);
+    domain_reliability_monitor_->AddBakedInConfigs();
+    domain_reliability_monitor_->SetDiscardUploads(
+        !GetMetricsEnabledStateOnIOThread());
+
+    chrome_network_delegate->set_domain_reliability_monitor(
+        std::move(lazy_params_->domain_reliability_monitor));
   }
 
   ApplyProfileParamsToContext(main_context);
diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h
index dedb29afb..0a46ea7 100644
--- a/chrome/browser/profiles/profile_impl_io_data.h
+++ b/chrome/browser/profiles/profile_impl_io_data.h
@@ -156,6 +156,8 @@
     scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy;
     std::unique_ptr<net::HttpServerPropertiesManager>
         http_server_properties_manager;
+    std::unique_ptr<domain_reliability::DomainReliabilityMonitor>
+        domain_reliability_monitor;
   };
 
   ProfileImplIOData();
@@ -219,7 +221,8 @@
 
   mutable std::unique_ptr<net::URLRequestJobFactory> extensions_job_factory_;
 
-  mutable std::unique_ptr<domain_reliability::DomainReliabilityMonitor>
+  // Owned by ChromeNetworkDelegate (which is owned by |network_delegate_|).
+  mutable domain_reliability::DomainReliabilityMonitor*
       domain_reliability_monitor_;
 
   mutable std::unique_ptr<net::SdchOwner> sdch_policy_;
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
index b9a63a6..674410d 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
@@ -11,6 +11,7 @@
 #import "chrome/browser/ui/cocoa/history_overlay_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace {
 // The horizontal distance required to cause the browser to perform a history
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
index d35732d..1ce08a6 100644
--- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
+++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
@@ -9,6 +9,7 @@
 #import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/ocmock_extensions.h"
 
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
index cd555d2b..3460a36 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_dialog.html
@@ -26,7 +26,7 @@
       }
 
       paper-spinner {
-        @apply(--cr-icon-size);
+        @apply(--cr-icon-height-width);
         margin: 0 10px;
       }
 
diff --git a/chrome/browser/resources/settings/controls/extension_controlled_indicator.html b/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
index bd477d7..cb96ae2 100644
--- a/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
+++ b/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
@@ -16,9 +16,8 @@
       }
 
       img {
+        @apply(--cr-icon-height-width);
         -webkit-margin-end: 16px;
-        height: var(--settings-icon-size);
-        width: var(--settings-icon-size);
       }
 
       span {
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html
index 2c1314c..ce5d71d 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.html
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -16,7 +16,7 @@
   <template>
     <style include="settings-shared">
       paper-spinner {
-        @apply(--cr-icon-size);
+        @apply(--cr-icon-height-width);
         margin: 0 var(--settings-box-row-padding);
       }
 
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js
index f32e0151..144968d 100644
--- a/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -75,10 +75,6 @@
     },
   },
 
-  keyBindings: {
-    'enter': 'onDetailsTap_',
-  },
-
   /** @private */
   expandedChanged_: function() {
     var type = this.deviceState ? this.deviceState.Type : '';
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index d7b6814..a6dc4d5 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -11,17 +11,6 @@
         display: none !important;
       }
 
-      button[is='paper-icon-button-light'] {
-        -webkit-margin-end: -8px;  /* Allow ripple to overlap the end. */
-        -webkit-margin-start: 16px;
-        background-position: center;
-        background-repeat: no-repeat;
-        background-size: var(--settings-icon-size);
-        flex-shrink: 0;
-        height: var(--settings-icon-ripple-size);
-        width: var(--settings-icon-ripple-size);
-      }
-
       :host-context([dir=rtl]) button[is='paper-icon-button-light'] {
         transform: scaleX(-1);  /* Flip on the X axis (aka mirror). */
       }
diff --git a/chrome/browser/resources/settings/settings_vars_css.html b/chrome/browser/resources/settings/settings_vars_css.html
index 9bbc6a8..b3cbbf96 100644
--- a/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -20,10 +20,6 @@
     --settings-disabled-opacity: .65;
     --settings-error-color: var(--paper-red-700);
 
-    /* The inner icon is 20px in size. paper-icon-button has 8px padding. */
-    --settings-icon-ripple-size: 36px;
-    --settings-icon-size: 20px;
-
     --settings-list-frame-padding: {
       -webkit-padding-end: var(--settings-box-row-padding);
       -webkit-padding-start: calc(
@@ -73,13 +69,13 @@
     --checkbox-size: 16px;
     --checkbox-spacing: 18px;
     --iron-icon-fill-color: var(--paper-grey-600);
-    --iron-icon-height: var(--settings-icon-size);
-    --iron-icon-width: var(--settings-icon-size);
+    --iron-icon-height: var(--cr-icon-size);
+    --iron-icon-width: var(--cr-icon-size);
     --paper-checkbox-label-color: inherit;
     --paper-dialog-color: inherit;
     --paper-icon-button: {
-      height: var(--settings-icon-ripple-size);
-      width: var(--settings-icon-ripple-size);
+      height: var(--cr-icon-ripple-size);
+      width: var(--cr-icon-ripple-size);
     };
     --paper-input-container-focus-color: var(--google-blue-500);
     --paper-input-container-input: {
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
index 804f789..8296494c 100644
--- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
+++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -24,8 +24,8 @@
 #include "chrome/browser/signin/easy_unlock_metrics.h"
 #include "chromeos/login/auth/user_context.h"
 #include "chromeos/tpm/tpm_token_loader.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
-#include "components/proximity_auth/remote_device.h"
 #include "components/proximity_auth/switches.h"
 
 namespace {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index dc147dc..880c26a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1357,6 +1357,7 @@
       "../browser/dom_distiller/distillable_page_utils_browsertest.cc",
       "../browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc",
       "../browser/dom_distiller/tab_utils_browsertest.cc",
+      "../browser/domain_reliability/browsertest.cc",
       "../browser/download/download_browsertest.cc",
       "../browser/download/download_browsertest.h",
       "../browser/download/download_danger_prompt_browsertest.cc",
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn
index e490528..f171bde 100644
--- a/chromeos/components/tether/BUILD.gn
+++ b/chromeos/components/tether/BUILD.gn
@@ -6,6 +6,8 @@
 
 static_library("tether") {
   sources = [
+    "ble_advertisement_device_queue.cc",
+    "ble_advertisement_device_queue.h",
     "host_scan_scheduler.cc",
     "host_scan_scheduler.h",
     "host_scanner.cc",
@@ -45,6 +47,7 @@
   testonly = true
 
   sources = [
+    "ble_advertisement_device_queue_unittest.cc",
     "host_scan_scheduler_unittest.cc",
   ]
 
@@ -54,6 +57,7 @@
     "//base/test:test_support",
     "//chromeos",
     "//components/cryptauth",
+    "//components/cryptauth:test_support",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/chromeos/components/tether/ble_advertisement_device_queue.cc b/chromeos/components/tether/ble_advertisement_device_queue.cc
new file mode 100644
index 0000000..4f53fcf
--- /dev/null
+++ b/chromeos/components/tether/ble_advertisement_device_queue.cc
@@ -0,0 +1,118 @@
+// Copyright 2016 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 "chromeos/components/tether/ble_advertisement_device_queue.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/logging.h"
+#include "components/proximity_auth/logging/logging.h"
+
+namespace chromeos {
+
+namespace tether {
+
+const int BleAdvertisementDeviceQueue::kMaxConcurrentAdvertisements = 2;
+
+BleAdvertisementDeviceQueue::BleAdvertisementDeviceQueue() {}
+
+BleAdvertisementDeviceQueue::~BleAdvertisementDeviceQueue() {}
+
+bool BleAdvertisementDeviceQueue::SetDevices(
+    std::vector<cryptauth::RemoteDevice> devices) {
+  // Determine which devices exist in |devices| but not in |device_queue_|, then
+  // add them to |device_queue_|.
+  std::vector<cryptauth::RemoteDevice> missing_from_queue;
+  for (auto& device : devices) {
+    if (std::find(device_queue_.begin(), device_queue_.end(), device) ==
+        device_queue_.end()) {
+      missing_from_queue.push_back(device);
+    }
+  }
+  if (!missing_from_queue.empty()) {
+    std::string log_message = "Adding device IDs: [";
+    for (auto& device : missing_from_queue) {
+      device_queue_.push_back(device);
+      log_message += device.GetTruncatedDeviceIdForLogs() + ",";
+    }
+    log_message.replace(log_message.length() - 1, log_message.length(), "]");
+    PA_LOG(INFO) << log_message;
+  }
+
+  // Determine which devices do not exist in |devices| but do exist in
+  // |device_queue_|, then remove them from |device_queue_|.
+  std::vector<cryptauth::RemoteDevice> to_remove_from_queue;
+  for (auto& device : device_queue_) {
+    if (std::find(devices.begin(), devices.end(), device) == devices.end()) {
+      to_remove_from_queue.push_back(device);
+    }
+  }
+  if (!to_remove_from_queue.empty()) {
+    std::string log_message = "Removing device IDs: [";
+    for (auto& device : to_remove_from_queue) {
+      device_queue_.erase(
+          std::find(device_queue_.begin(), device_queue_.end(), device));
+      log_message += device.GetTruncatedDeviceIdForLogs() + ",";
+    }
+    log_message.replace(log_message.length() - 1, log_message.length(), "]");
+    PA_LOG(INFO) << log_message;
+  }
+
+  return !missing_from_queue.empty() || !to_remove_from_queue.empty();
+}
+
+void BleAdvertisementDeviceQueue::MoveDeviceToEnd(std::string device_id) {
+  if (device_id.empty()) {
+    return;
+  }
+
+  int index = -1;
+  for (size_t i = 0; i < device_queue_.size(); i++) {
+    if (device_id == device_queue_[i].GetDeviceId()) {
+      index = i;
+      break;
+    }
+  }
+
+  if (index >= 0) {
+    cryptauth::RemoteDevice to_move = device_queue_[index];
+    device_queue_.erase(device_queue_.begin() + index);
+    device_queue_.push_back(to_move);
+  }
+}
+
+std::vector<cryptauth::RemoteDevice>
+BleAdvertisementDeviceQueue::GetDevicesToWhichToAdvertise() const {
+  std::vector<cryptauth::RemoteDevice> to_advertise;
+
+  if (device_queue_.empty()) {
+    PA_LOG(INFO) << "No devices to which to advertise.";
+    return to_advertise;
+  }
+
+  std::string log_message = "Should advertise to the following device IDs: [";
+  for (auto& device : device_queue_) {
+    to_advertise.push_back(device);
+    log_message += device.GetTruncatedDeviceIdForLogs() + ",";
+
+    if (to_advertise.size() ==
+        static_cast<size_t>(kMaxConcurrentAdvertisements)) {
+      break;
+    }
+  }
+
+  log_message.replace(log_message.length() - 1, log_message.length(), "]");
+  PA_LOG(INFO) << log_message;
+
+  return to_advertise;
+}
+
+size_t BleAdvertisementDeviceQueue::GetSize() const {
+  return device_queue_.size();
+}
+
+}  // namespace tether
+
+}  // namespace chromeos
diff --git a/chromeos/components/tether/ble_advertisement_device_queue.h b/chromeos/components/tether/ble_advertisement_device_queue.h
new file mode 100644
index 0000000..84cff21
--- /dev/null
+++ b/chromeos/components/tether/ble_advertisement_device_queue.h
@@ -0,0 +1,64 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_COMPONENTS_TETHER_BLE_ADVERTISEMENT_DEVICE_QUEUE_H_
+#define CHROMEOS_COMPONENTS_TETHER_BLE_ADVERTISEMENT_DEVICE_QUEUE_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "components/cryptauth/remote_device.h"
+
+namespace chromeos {
+
+namespace tether {
+
+// Queue of devices to which to advertise. Because only
+// |kMaxConcurrentAdvertisements| devices can be advertised to concurrently,
+// this queue maintains the order of devices to ensure that each device gets its
+// fair share of time spent contacting it.
+class BleAdvertisementDeviceQueue {
+ public:
+  // The maximum number of devices to which to advertise concurrently. If more
+  // than this number of devices are registered, some advertisement must be
+  // stopped before new ones can be added.
+  //
+  // Note that this upper limit on concurrent advertisements is imposed due to a
+  // hardware limit of advertisements.
+  static const int kMaxConcurrentAdvertisements;
+
+  BleAdvertisementDeviceQueue();
+  virtual ~BleAdvertisementDeviceQueue();
+
+  // Updates the queue with the given |devices|. Devices which are already in
+  // the queue and are not in |devices| are removed from the queue, and all
+  // devices which are not in the queue but are in |devices| are added to the
+  // end of the queue. Note devices that are already in the queue will not
+  // change order as a result of this function being called to ensure that the
+  // queue remains in order. Returns whether the device list has changed due to
+  // the function call.
+  bool SetDevices(std::vector<cryptauth::RemoteDevice> devices);
+
+  // Moves the given device to the end of the queue. If the device was not in
+  // the queue to begin with, do nothing.
+  void MoveDeviceToEnd(std::string device_id);
+
+  // Returns a list of devices to which to advertise. The devices returned are
+  // the first |kMaxConcurrentAdvertisements| devices in the front of the queue,
+  // or fewer if the number of devices in the queue is less than that value.
+  std::vector<cryptauth::RemoteDevice> GetDevicesToWhichToAdvertise() const;
+
+  size_t GetSize() const;
+
+ private:
+  std::vector<cryptauth::RemoteDevice> device_queue_;
+
+  DISALLOW_COPY_AND_ASSIGN(BleAdvertisementDeviceQueue);
+};
+
+}  // namespace tether
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_TETHER_BLE_ADVERTISEMENT_DEVICE_QUEUE_H_
diff --git a/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc b/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc
new file mode 100644
index 0000000..6ba67b8
--- /dev/null
+++ b/chromeos/components/tether/ble_advertisement_device_queue_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2016 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 "chromeos/components/tether/ble_advertisement_device_queue.h"
+
+#include <memory>
+
+#include "components/cryptauth/remote_device_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::ElementsAre;
+
+namespace chromeos {
+
+namespace tether {
+
+class BleAdvertisementDeviceQueueTest : public testing::Test {
+ protected:
+  BleAdvertisementDeviceQueueTest() : device_queue_(nullptr) {}
+
+  void SetUp() override {
+    device_queue_.reset(new BleAdvertisementDeviceQueue());
+  }
+
+  std::unique_ptr<BleAdvertisementDeviceQueue> device_queue_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BleAdvertisementDeviceQueueTest);
+};
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestEmptyQueue) {
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_EQ(static_cast<size_t>(0), device_queue_->GetSize());
+  EXPECT_TRUE(to_advertise.empty());
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestSingleDevice) {
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(1);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_EQ(static_cast<size_t>(1), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestSingleDevice_MoveToEnd) {
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(1);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_EQ(static_cast<size_t>(1), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0]));
+
+  device_queue_->MoveDeviceToEnd(devices[0].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestTwoDevices) {
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(2);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_EQ(static_cast<size_t>(2), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0], devices[1]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestTwoDevices_MoveToEnd) {
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(2);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_EQ(static_cast<size_t>(2), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0], devices[1]));
+
+  device_queue_->MoveDeviceToEnd(devices[0].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[1], devices[0]));
+
+  device_queue_->MoveDeviceToEnd(devices[1].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0], devices[1]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestThreeDevices) {
+  // Note: These tests need to be rewritten if MAX_CONCURRENT_ADVERTISEMENTS is
+  // ever changed.
+  ASSERT_GT(3, BleAdvertisementDeviceQueue::kMaxConcurrentAdvertisements);
+
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(3);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_EQ(static_cast<size_t>(3), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0], devices[1]));
+
+  device_queue_->MoveDeviceToEnd(devices[0].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[1], devices[2]));
+
+  device_queue_->MoveDeviceToEnd(devices[1].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[2], devices[0]));
+
+  device_queue_->MoveDeviceToEnd(devices[2].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(devices[0], devices[1]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestAddingDevices) {
+  // Note: These tests need to be rewritten if MAX_CONCURRENT_ADVERTISEMENTS is
+  // ever changed.
+  ASSERT_GT(3, BleAdvertisementDeviceQueue::kMaxConcurrentAdvertisements);
+
+  std::vector<cryptauth::RemoteDevice> all_devices =
+      cryptauth::GenerateTestRemoteDevices(5);
+  std::vector<cryptauth::RemoteDevice> initial_devices = {all_devices[0],
+                                                          all_devices[1]};
+  std::vector<cryptauth::RemoteDevice> updated_devices_list = {
+      all_devices[1], all_devices[2], all_devices[3], all_devices[4]};
+
+  EXPECT_TRUE(device_queue_->SetDevices(initial_devices));
+  EXPECT_EQ(static_cast<size_t>(2), device_queue_->GetSize());
+
+  std::vector<cryptauth::RemoteDevice> to_advertise =
+      device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(all_devices[0], all_devices[1]));
+
+  device_queue_->MoveDeviceToEnd(all_devices[0].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(all_devices[1], all_devices[0]));
+
+  // Device #1 has been unregistered; Devices #3 and #4 have been registered.
+  EXPECT_TRUE(device_queue_->SetDevices(updated_devices_list));
+  EXPECT_EQ(static_cast<size_t>(4), device_queue_->GetSize());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(all_devices[1], all_devices[2]));
+
+  device_queue_->MoveDeviceToEnd(all_devices[2].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(all_devices[1], all_devices[3]));
+
+  device_queue_->MoveDeviceToEnd(all_devices[1].GetDeviceId());
+  to_advertise = device_queue_->GetDevicesToWhichToAdvertise();
+  EXPECT_THAT(to_advertise, ElementsAre(all_devices[3], all_devices[4]));
+}
+
+TEST_F(BleAdvertisementDeviceQueueTest, TestSettingSameDevices) {
+  std::vector<cryptauth::RemoteDevice> devices =
+      cryptauth::GenerateTestRemoteDevices(2);
+  EXPECT_TRUE(device_queue_->SetDevices(devices));
+  EXPECT_FALSE(device_queue_->SetDevices(devices));
+  EXPECT_FALSE(device_queue_->SetDevices(devices));
+  EXPECT_TRUE(
+      device_queue_->SetDevices(cryptauth::GenerateTestRemoteDevices(3)));
+}
+
+}  // namespace tether
+
+}  // namespace cryptauth
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index e655f7fe..bbceb4f 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -814,6 +814,10 @@
     Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE);
   }
 
+  if (has_logged_suggestions_shown_) {
+    Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE);
+  }
+
   base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm"));
 }
 
@@ -837,6 +841,10 @@
   } else {
     Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE);
   }
+
+  if (has_logged_suggestions_shown_) {
+    Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE);
+  }
 }
 
 void AutofillMetrics::FormEventLogger::Log(FormEvent event) const {
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index b8e569b..974f39d 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -383,6 +383,13 @@
     FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE,
     FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE,
     FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+    // A dropdown with suggestions was shown and a form was submitted after
+    // that.
+    FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE,
+    // A dropdown with suggestions was shown and a form is about to be
+    // submitted. If the submission is not interrupted by JavaScript, the "form
+    // submitted" event above will also be logged.
+    FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE,
 
     NUM_FORM_EVENTS,
   };
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 459e871..83fd062 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -2413,6 +2413,24 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
+    // Simulating submission with suggestion shown.
+    base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+    autofill_manager_->SubmitForm(form, TimeTicks::Now());
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+  }
+
+  // Reset the autofill manager state.
+  autofill_manager_->Reset();
+  autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+  {
     // Simulating submission with filled local data.
     base::HistogramTester histogram_tester;
     autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -2496,6 +2514,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
@@ -2510,6 +2531,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
@@ -2526,27 +2550,45 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
-    // Simulating submission without previous interaction.
+    // Simulating submission with suggestion shown but without previous
+    // interaction.
     base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
     autofill_manager_->SubmitForm(form, TimeTicks::Now());
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
-    histogram_tester.ExpectBucketCount(
-        "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
-    histogram_tester.ExpectBucketCount(
-        "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+        AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+        0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+        0);
   }
 }
 
@@ -2600,6 +2642,24 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
+    // Simulating submission with suggestion shown.
+    base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+    autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+  }
+
+  // Reset the autofill manager state.
+  autofill_manager_->Reset();
+  autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+  {
     // Simulating submission with filled local data.
     base::HistogramTester histogram_tester;
     autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -2683,6 +2743,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
@@ -2697,6 +2760,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
@@ -2713,27 +2779,45 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
-    // Simulating submission without previous interaction.
+    // Simulating submission with suggestion shown but without previous
+    // interaction.
     base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
     autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
-    histogram_tester.ExpectBucketCount(
-        "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
-    histogram_tester.ExpectBucketCount(
-        "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
-        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+        AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.CreditCard",
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+        0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.CreditCard",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+        0);
   }
 }
 
@@ -2991,6 +3075,24 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
+    // Simulating submission with suggestion shown.
+    base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+    autofill_manager_->SubmitForm(form, TimeTicks::Now());
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
+  }
+
+  // Reset the autofill manager state.
+  autofill_manager_->Reset();
+  autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+  {
     // Simulating submission with filled local data.
     base::HistogramTester histogram_tester;
     autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3043,6 +3145,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3052,6 +3157,9 @@
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3063,11 +3171,16 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
-    // Simulating submission without previous interaction.
+    // Simulating submission with suggestion show but without previous
+    // interaction.
     base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
     autofill_manager_->SubmitForm(form, TimeTicks::Now());
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3077,6 +3190,14 @@
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+        0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3084,6 +3205,11 @@
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+        0);
   }
 }
 
@@ -3135,6 +3261,24 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
+    // Simulating submission with suggestion shown.
+    base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+    autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+    autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+  }
+
+  // Reset the autofill manager state.
+  autofill_manager_->Reset();
+  autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+  {
     // Simulating submission with filled local data.
     base::HistogramTester histogram_tester;
     autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3184,9 +3328,26 @@
     autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+        0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3194,6 +3355,11 @@
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+        0);
   }
 
   // Reset the autofill manager state.
@@ -3201,11 +3367,16 @@
   autofill_manager_->AddSeenForm(form, field_types, field_types);
 
   {
-    // Simulating submission without previous interaction.
+    // Simulating submission with suggestion shown but without previous
+    // interaction.
     base::HistogramTester histogram_tester;
+    autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
     autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3215,6 +3386,14 @@
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE,
+        0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0);
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
@@ -3222,6 +3401,11 @@
     histogram_tester.ExpectBucketCount(
         "Autofill.FormEvents.Address",
         AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
+    histogram_tester.ExpectBucketCount(
+        "Autofill.FormEvents.Address",
+        AutofillMetrics::
+            FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE,
+        0);
   }
 }
 
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 4bb90e1..dfc2821 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -804,11 +804,6 @@
 void ProfileSyncService::StopImpl(SyncStopDataFate data_fate) {
   switch (data_fate) {
     case KEEP_DATA:
-      // TODO(maxbogue): Investigate whether this logic can/should be moved
-      // into ShutdownImpl or the sync engine itself.
-      if (HasSyncingEngine()) {
-        engine_->UnregisterInvalidationIds();
-      }
       ShutdownImpl(syncer::STOP_SYNC);
       break;
     case CLEAR_DATA:
diff --git a/components/browser_watcher/BUILD.gn b/components/browser_watcher/BUILD.gn
index 5d64eed..95b431e 100644
--- a/components/browser_watcher/BUILD.gn
+++ b/components/browser_watcher/BUILD.gn
@@ -4,79 +4,81 @@
 
 import("//third_party/protobuf/proto_library.gni")
 
-proto_library("stability_report_proto") {
-  sources = [
-    "stability_report.proto",
-  ]
-}
+if (is_win) {
+  proto_library("stability_report_proto") {
+    sources = [
+      "stability_report.proto",
+    ]
+  }
 
-static_library("browser_watcher") {
-  # This is a separate lib to minimize the dependencies for its
-  # hosting binary "chrome_watcher.dll".
-  sources = [
-    "endsession_watcher_window_win.cc",
-    "endsession_watcher_window_win.h",
-    "exit_code_watcher_win.cc",
-    "exit_code_watcher_win.h",
-    "window_hang_monitor_win.cc",
-    "window_hang_monitor_win.h",
-  ]
-  deps = [
-    "//base",
-  ]
-}
+  static_library("browser_watcher") {
+    # This is a separate lib to minimize the dependencies for its
+    # hosting binary "chrome_watcher.dll".
+    sources = [
+      "endsession_watcher_window_win.cc",
+      "endsession_watcher_window_win.h",
+      "exit_code_watcher_win.cc",
+      "exit_code_watcher_win.h",
+      "window_hang_monitor_win.cc",
+      "window_hang_monitor_win.h",
+    ]
+    deps = [
+      "//base",
+    ]
+  }
 
-static_library("browser_watcher_client") {
-  sources = [
-    "watcher_client_win.cc",
-    "watcher_client_win.h",
-    "watcher_metrics_provider_win.cc",
-    "watcher_metrics_provider_win.h",
-  ]
-  deps = [
-    ":postmortem_report_collector",
-    ":stability",
-    "//base",
-    "//components/metrics",
-    "//third_party/crashpad/crashpad/client",
-  ]
-}
+  static_library("browser_watcher_client") {
+    sources = [
+      "watcher_client_win.cc",
+      "watcher_client_win.h",
+      "watcher_metrics_provider_win.cc",
+      "watcher_metrics_provider_win.h",
+    ]
+    deps = [
+      ":postmortem_report_collector",
+      ":stability",
+      "//base",
+      "//components/metrics",
+      "//third_party/crashpad/crashpad/client",
+    ]
+  }
 
-static_library("postmortem_minidump_writer") {
-  # TODO(manzagop): remove this lib once Crashpad writes the minidumps.
-  sources = [
-    "postmortem_minidump_writer.h",
-    "postmortem_minidump_writer_win.cc",
-  ]
-  deps = [
-    ":stability_report_proto",
-    "//base",
-    "//third_party/crashpad/crashpad/client",
-    "//third_party/crashpad/crashpad/minidump",
-    "//third_party/crashpad/crashpad/util",
-  ]
-}
+  static_library("postmortem_minidump_writer") {
+    # TODO(manzagop): remove this lib once Crashpad writes the minidumps.
+    sources = [
+      "postmortem_minidump_writer.h",
+      "postmortem_minidump_writer_win.cc",
+    ]
+    deps = [
+      ":stability_report_proto",
+      "//base",
+      "//third_party/crashpad/crashpad/client",
+      "//third_party/crashpad/crashpad/minidump",
+      "//third_party/crashpad/crashpad/util",
+    ]
+  }
 
-static_library("postmortem_report_collector") {
-  sources = [
-    "postmortem_report_collector.cc",
-    "postmortem_report_collector.h",
-  ]
-  deps = [
-    ":postmortem_minidump_writer",
-    ":stability_report_proto",
-    "//base",
-    "//third_party/crashpad/crashpad/client",
-    "//third_party/crashpad/crashpad/util",
-  ]
+  static_library("postmortem_report_collector") {
+    sources = [
+      "postmortem_report_collector.cc",
+      "postmortem_report_collector.h",
+    ]
+    deps = [
+      ":postmortem_minidump_writer",
+      ":stability_report_proto",
+      "//base",
+      "//third_party/crashpad/crashpad/client",
+      "//third_party/crashpad/crashpad/util",
+    ]
+  }
 }
 
 static_library("stability") {
   sources = [
     "features.cc",
     "features.h",
-    "stability_debugging_win.cc",
-    "stability_debugging_win.h",
+    "stability_debugging.cc",
+    "stability_debugging.h",
   ]
   deps = [
     "//base",
@@ -90,44 +92,46 @@
   ]
 }
 
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "endsession_watcher_window_win_unittest.cc",
-    "exit_code_watcher_win_unittest.cc",
-    "postmortem_minidump_writer_win_unittest.cc",
-    "postmortem_report_collector_unittest.cc",
-    "watcher_client_win_unittest.cc",
-    "watcher_metrics_provider_win_unittest.cc",
-    "window_hang_monitor_win_unittest.cc",
-  ]
-  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-  deps = [
-    ":browser_watcher",
-    ":browser_watcher_client",
-    ":postmortem_minidump_writer",
-    ":postmortem_report_collector",
-    ":stability_report_proto",
-    "//base",
-    "//base/test:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//third_party/crashpad/crashpad/client",
+if (is_win) {
+  source_set("unit_tests") {
+    testonly = true
+    sources = [
+      "endsession_watcher_window_win_unittest.cc",
+      "exit_code_watcher_win_unittest.cc",
+      "postmortem_minidump_writer_win_unittest.cc",
+      "postmortem_report_collector_unittest.cc",
+      "watcher_client_win_unittest.cc",
+      "watcher_metrics_provider_win_unittest.cc",
+      "window_hang_monitor_win_unittest.cc",
+    ]
+    configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+    deps = [
+      ":browser_watcher",
+      ":browser_watcher_client",
+      ":postmortem_minidump_writer",
+      ":postmortem_report_collector",
+      ":stability_report_proto",
+      "//base",
+      "//base/test:test_support",
+      "//testing/gmock",
+      "//testing/gtest",
+      "//third_party/crashpad/crashpad/client",
 
-    # TODO(manzagop): remove this lib once Crashpad writes the minidumps.
-    "//third_party/crashpad/crashpad/compat",
-    "//third_party/crashpad/crashpad/minidump",
-    "//third_party/crashpad/crashpad/snapshot",
-    "//third_party/crashpad/crashpad/util",
-  ]
-}
+      # TODO(manzagop): remove this lib once Crashpad writes the minidumps.
+      "//third_party/crashpad/crashpad/compat",
+      "//third_party/crashpad/crashpad/minidump",
+      "//third_party/crashpad/crashpad/snapshot",
+      "//third_party/crashpad/crashpad/util",
+    ]
+  }
 
-executable("dump_postmortem") {
-  sources = [
-    "dump_postmortem_minidump_main_win.cc",
-  ]
-  deps = [
-    ":stability_report_proto",
-    "//base",
-  ]
+  executable("dump_postmortem") {
+    sources = [
+      "dump_postmortem_minidump_main_win.cc",
+    ]
+    deps = [
+      ":stability_report_proto",
+      "//base",
+    ]
+  }
 }
diff --git a/components/browser_watcher/stability_data_names.cc b/components/browser_watcher/stability_data_names.cc
index b227065..27be25b 100644
--- a/components/browser_watcher/stability_data_names.cc
+++ b/components/browser_watcher/stability_data_names.cc
@@ -7,6 +7,7 @@
 namespace browser_watcher {
 
 const char kStabilityChannel[] = "channel";
+const char kStabilityExecutionPhase[] = "stability-execution-phase";
 const char kStabilityPlatform[] = "platform";
 const char kStabilityProduct[] = "product";
 const char kStabilitySpecialBuild[] = "special-build";
diff --git a/components/browser_watcher/stability_data_names.h b/components/browser_watcher/stability_data_names.h
index 9c7cfc15..9143811 100644
--- a/components/browser_watcher/stability_data_names.h
+++ b/components/browser_watcher/stability_data_names.h
@@ -9,6 +9,7 @@
 
 // Alphabetical list of stability data names.
 extern const char kStabilityChannel[];
+extern const char kStabilityExecutionPhase[];
 extern const char kStabilityPlatform[];
 extern const char kStabilityProduct[];
 extern const char kStabilitySpecialBuild[];
diff --git a/components/browser_watcher/stability_debugging_win.cc b/components/browser_watcher/stability_debugging.cc
similarity index 84%
rename from components/browser_watcher/stability_debugging_win.cc
rename to components/browser_watcher/stability_debugging.cc
index 3eb4e47..4341ffe 100644
--- a/components/browser_watcher/stability_debugging_win.cc
+++ b/components/browser_watcher/stability_debugging.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/browser_watcher/stability_debugging_win.h"
+#include "components/browser_watcher/stability_debugging.h"
 
 #include <string>
 
+#include "base/debug/activity_tracker.h"
 #include "base/feature_list.h"
 #include "base/files/file.h"
 #include "base/metrics/persistent_memory_allocator.h"
@@ -19,6 +20,7 @@
 
 namespace {
 
+#if defined(OS_WIN)
 bool GetCreationTime(const base::Process& process, base::Time* time) {
   DCHECK(time);
 
@@ -33,9 +35,12 @@
   *time = base::Time::FromFileTime(creation_time);
   return true;
 }
+#endif  // defined(OS_WIN)
 
 }  // namespace
 
+#if defined(OS_WIN)
+
 base::FilePath GetStabilityDir(const base::FilePath& user_data_dir) {
   return user_data_dir.AppendASCII("Stability");
 }
@@ -84,5 +89,15 @@
                                       base::File::FLAG_READ |
                                       base::File::FLAG_DELETE_ON_CLOSE);
 }
+#endif  // defined(OS_WIN)
+
+void SetStabilityDataInt(base::StringPiece name, int64_t value) {
+  base::debug::GlobalActivityTracker* global_tracker =
+      base::debug::GlobalActivityTracker::Get();
+  if (!global_tracker)
+    return;  // Activity tracking isn't enabled.
+
+  global_tracker->user_data().SetInt(name, value);
+}
 
 }  // namespace browser_watcher
diff --git a/components/browser_watcher/stability_debugging_win.h b/components/browser_watcher/stability_debugging.h
similarity index 70%
rename from components/browser_watcher/stability_debugging_win.h
rename to components/browser_watcher/stability_debugging.h
index 3ac14be..e856941 100644
--- a/components/browser_watcher/stability_debugging_win.h
+++ b/components/browser_watcher/stability_debugging.h
@@ -2,15 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_WIN_H_
-#define COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_WIN_H_
+#ifndef COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_H_
+#define COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_H_
+
+#include <stdint.h>
 
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/process/process.h"
+#include "base/strings/string_piece.h"
 
 namespace browser_watcher {
 
+#if defined(OS_WIN)
+
 // Returns the the stability debugging directory.
 base::FilePath GetStabilityDir(const base::FilePath& user_data_dir);
 
@@ -26,6 +31,11 @@
 // Marks the stability file for deletion.
 void MarkStabilityFileForDeletion(const base::FilePath& user_data_dir);
 
+#endif  // defined(OS_WIN)
+
+// Adds or updates the global stability user data.
+void SetStabilityDataInt(base::StringPiece name, int64_t value);
+
 }  // namespace browser_watcher
 
-#endif  // COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_WIN_H_
+#endif  // COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_H_
diff --git a/components/browser_watcher/watcher_metrics_provider_win.cc b/components/browser_watcher/watcher_metrics_provider_win.cc
index 57a1d28e..74db4f5 100644
--- a/components/browser_watcher/watcher_metrics_provider_win.cc
+++ b/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -24,7 +24,7 @@
 #include "base/win/registry.h"
 #include "components/browser_watcher/features.h"
 #include "components/browser_watcher/postmortem_report_collector.h"
-#include "components/browser_watcher/stability_debugging_win.h"
+#include "components/browser_watcher/stability_debugging.h"
 #include "third_party/crashpad/crashpad/client/crash_report_database.h"
 
 namespace browser_watcher {
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc
index fd9e1db..2299b95 100644
--- a/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/content_settings/core/browser/cookie_settings.h"
 
+#include "base/message_loop/message_loop.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/content_settings/core/common/pref_names.h"
@@ -38,6 +39,10 @@
   ~CookieSettingsTest() override { settings_map_->ShutdownOnUIThread(); }
 
  protected:
+  // There must be a valid ThreadTaskRunnerHandle in HostContentSettingsMap's
+  // scope.
+  base::MessageLoop message_loop_;
+
   sync_preferences::TestingPrefServiceSyncable prefs_;
   scoped_refptr<HostContentSettingsMap> settings_map_;
   scoped_refptr<CookieSettings> cookie_settings_;
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
index 16e073e..89fae03 100644
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -14,6 +14,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/clock.h"
 #include "build/build_config.h"
 #include "components/content_settings/core/browser/content_settings_default_provider.h"
@@ -178,7 +179,7 @@
 HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs,
                                                bool is_incognito_profile,
                                                bool is_guest_profile)
-    :
+    : RefcountedKeyedService(base::ThreadTaskRunnerHandle::Get()),
 #ifndef NDEBUG
       used_from_thread_id_(base::PlatformThread::CurrentId()),
 #endif
@@ -827,6 +828,7 @@
 }
 
 HostContentSettingsMap::~HostContentSettingsMap() {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!prefs_);
 }
 
diff --git a/components/cryptauth/BUILD.gn b/components/cryptauth/BUILD.gn
index 1bfdc1b..a1cec1d 100644
--- a/components/cryptauth/BUILD.gn
+++ b/components/cryptauth/BUILD.gn
@@ -73,6 +73,8 @@
     "mock_cryptauth_client.h",
     "mock_sync_scheduler.cc",
     "mock_sync_scheduler.h",
+    "remote_device_test_util.cc",
+    "remote_device_test_util.h",
   ]
 
   public_deps = [
diff --git a/components/cryptauth/DEPS b/components/cryptauth/DEPS
index e6c99c9..531dbff44 100644
--- a/components/cryptauth/DEPS
+++ b/components/cryptauth/DEPS
@@ -1,7 +1,7 @@
 include_rules = [
   "+components/gcm_driver",
   "+components/prefs",
-  "+components/proximity_auth",
+  "+components/proximity_auth/logging",
   "+crypto",
   "+google_apis",
   "+net",
diff --git a/components/cryptauth/eid_generator_unittest.cc b/components/cryptauth/eid_generator_unittest.cc
index 61c78f0d..18a73e3 100644
--- a/components/cryptauth/eid_generator_unittest.cc
+++ b/components/cryptauth/eid_generator_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
-#include "components/proximity_auth/remote_device.h"
+#include "components/cryptauth/remote_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/cryptauth/remote_device.cc b/components/cryptauth/remote_device.cc
index da0a0583..2787438 100644
--- a/components/cryptauth/remote_device.cc
+++ b/components/cryptauth/remote_device.cc
@@ -29,13 +29,13 @@
 
 RemoteDevice::~RemoteDevice() {}
 
-std::string RemoteDevice::GetDeviceId() {
+std::string RemoteDevice::GetDeviceId() const {
    std::string to_return;
    base::Base64Encode(public_key, &to_return);
    return to_return;
 }
 
-std::string RemoteDevice::GetTruncatedDeviceIdForLogs() {
+std::string RemoteDevice::GetTruncatedDeviceIdForLogs() const {
    std::string id = GetDeviceId();
    if (id.length() <= 10) {
       return id;
@@ -44,4 +44,14 @@
    return id.substr(0, 5) + "..." + id.substr(id.length() - 5, id.length());
 }
 
+bool RemoteDevice::operator==(const RemoteDevice& other) const {
+   return user_id == other.user_id
+         && name == other.name
+         && public_key == other.public_key
+         && bluetooth_type == other.bluetooth_type
+         && bluetooth_address == other.bluetooth_address
+         && persistent_symmetric_key == other.persistent_symmetric_key
+         && sign_in_challenge == other.sign_in_challenge;
+}
+
 }  // namespace cryptauth
diff --git a/components/cryptauth/remote_device.h b/components/cryptauth/remote_device.h
index 369bc7f..5539055 100644
--- a/components/cryptauth/remote_device.h
+++ b/components/cryptauth/remote_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
-#define COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
+#ifndef COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_H
+#define COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_H
 
 #include <string>
 #include <vector>
@@ -34,16 +34,18 @@
   ~RemoteDevice();
 
   // Returns a unique ID for the device.
-  std::string GetDeviceId();
+  std::string GetDeviceId() const;
 
   // Returns a shortened device ID for the purpose of concise logging (device
   // IDs are often so long that logs are difficult to read). Note that this
   // ID is not guaranteed to be unique, so it should only be used for log.
-  std::string GetTruncatedDeviceIdForLogs();
+  std::string GetTruncatedDeviceIdForLogs() const;
+
+  bool operator==(const RemoteDevice& other) const;
 };
 
 typedef std::vector<RemoteDevice> RemoteDeviceList;
 
 }  // namespace cryptauth
 
-#endif  // COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
+#endif  // COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_H
diff --git a/components/cryptauth/remote_device_test_util.cc b/components/cryptauth/remote_device_test_util.cc
new file mode 100644
index 0000000..73fe092
--- /dev/null
+++ b/components/cryptauth/remote_device_test_util.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 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/cryptauth/remote_device_test_util.h"
+
+#include "base/base64.h"
+
+namespace cryptauth {
+
+std::vector<RemoteDevice> GenerateTestRemoteDevices(size_t num_to_create) {
+  std::vector<RemoteDevice> generated_devices;
+
+  for (size_t i = 0; i < num_to_create; i++) {
+    RemoteDevice device;
+    device.public_key = "publicKey" + std::to_string(i);
+    generated_devices.push_back(device);
+  }
+
+  return generated_devices;
+}
+
+}  // namespace cryptauth
diff --git a/components/cryptauth/remote_device_test_util.h b/components/cryptauth/remote_device_test_util.h
new file mode 100644
index 0000000..dad2954e9
--- /dev/null
+++ b/components/cryptauth/remote_device_test_util.h
@@ -0,0 +1,18 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_TEST_UTIL_H
+#define COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_TEST_UTIL_H
+
+#include <vector>
+
+#include "components/cryptauth/remote_device.h"
+
+namespace cryptauth {
+
+std::vector<RemoteDevice> GenerateTestRemoteDevices(size_t num_to_create);
+
+}  // namespace cryptauth
+
+#endif  // COMPONENTS_CRYPTAUTH_REMOTE_DEVICE_TEST_UTIL_H
diff --git a/components/domain_reliability/dispatcher.cc b/components/domain_reliability/dispatcher.cc
index 3abef20..c4efdd0 100644
--- a/components/domain_reliability/dispatcher.cc
+++ b/components/domain_reliability/dispatcher.cc
@@ -83,6 +83,17 @@
   }
 }
 
+void DomainReliabilityDispatcher::RunAllTasksForTesting() {
+  std::set<Task*> tasks;
+  for (auto& task : tasks_)
+    tasks.insert(task.get());
+
+  for (auto* task : tasks) {
+    DCHECK(task);
+    RunAndDeleteTask(task);
+  }
+}
+
 void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
   DCHECK(task);
   DCHECK(!task->eligible);
diff --git a/components/domain_reliability/dispatcher.h b/components/domain_reliability/dispatcher.h
index 41cb511..b65d404 100644
--- a/components/domain_reliability/dispatcher.h
+++ b/components/domain_reliability/dispatcher.h
@@ -35,9 +35,15 @@
                     base::TimeDelta min_delay,
                     base::TimeDelta max_delay);
 
-  // Runs all tasks whose minimum delay has already passed.
+  // Runs all existing tasks whose minimum delay has already passed. Does not
+  // run tasks added by those existing tasks, even if their minimum delay has
+  // already passed.
   void RunEligibleTasks();
 
+  // Runs all waiting or eligible tasks, regardless of whether their minimum
+  // delay has passed.
+  void RunAllTasksForTesting();
+
  private:
   struct Task;
 
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc
index c789be78..9c56882e 100644
--- a/components/domain_reliability/monitor.cc
+++ b/components/domain_reliability/monitor.cc
@@ -155,6 +155,10 @@
                                                 url_request_context_getter);
 }
 
+void DomainReliabilityMonitor::Shutdown() {
+  uploader_->Shutdown();
+}
+
 void DomainReliabilityMonitor::AddBakedInConfigs() {
   DCHECK(OnNetworkThread());
   DCHECK(moved_to_network_thread_);
@@ -249,6 +253,10 @@
   return context_manager_.AddContextForConfig(std::move(config));
 }
 
+void DomainReliabilityMonitor::ForceUploadsForTesting() {
+  dispatcher_.RunAllTasksForTesting();
+}
+
 std::unique_ptr<DomainReliabilityContext>
 DomainReliabilityMonitor::CreateContextForConfig(
     std::unique_ptr<const DomainReliabilityConfig> config) {
diff --git a/components/domain_reliability/monitor.h b/components/domain_reliability/monitor.h
index a5a2726..29ba993 100644
--- a/components/domain_reliability/monitor.h
+++ b/components/domain_reliability/monitor.h
@@ -88,6 +88,10 @@
       const scoped_refptr<net::URLRequestContextGetter>&
           url_request_context_getter);
 
+  // Shuts down the monitor prior to destruction. Currently, ensures that there
+  // are no pending uploads, to avoid hairy lifetime issues at destruction.
+  void Shutdown();
+
   // Populates the monitor with contexts that were configured at compile time.
   void AddBakedInConfigs();
 
@@ -130,6 +134,10 @@
     return context_manager_.contexts_size_for_testing();
   }
 
+  // Forces all pending uploads to run now, even if their minimum delay has not
+  // yet passed.
+  void ForceUploadsForTesting();
+
   // DomainReliabilityContext::Factory implementation:
   std::unique_ptr<DomainReliabilityContext> CreateContextForConfig(
       std::unique_ptr<const DomainReliabilityConfig> config) override;
diff --git a/components/domain_reliability/monitor_unittest.cc b/components/domain_reliability/monitor_unittest.cc
index 8fc589a3..2e46fda2 100644
--- a/components/domain_reliability/monitor_unittest.cc
+++ b/components/domain_reliability/monitor_unittest.cc
@@ -68,6 +68,10 @@
     monitor_.SetDiscardUploads(false);
   }
 
+  ~DomainReliabilityMonitorTest() override {
+    monitor_.Shutdown();
+  }
+
   static RequestInfo MakeRequestInfo() {
     RequestInfo request;
     request.status = net::URLRequestStatus();
diff --git a/components/domain_reliability/service.cc b/components/domain_reliability/service.cc
index cdc91d7dc..92eec42 100644
--- a/components/domain_reliability/service.cc
+++ b/components/domain_reliability/service.cc
@@ -18,6 +18,15 @@
 
 namespace {
 
+void AddContextForTestingOnNetworkTaskRunner(
+    base::WeakPtr<DomainReliabilityMonitor> monitor,
+    std::unique_ptr<const DomainReliabilityConfig> config) {
+  if (!monitor)
+    return;
+
+  monitor->AddContextForTesting(std::move(config));
+}
+
 std::unique_ptr<base::Value> GetWebUIDataOnNetworkTaskRunner(
     base::WeakPtr<DomainReliabilityMonitor> monitor) {
   if (!monitor) {
@@ -83,6 +92,36 @@
         callback);
   }
 
+  void SetDiscardUploadsForTesting(bool discard_uploads) override {
+    DCHECK(network_task_runner_.get());
+
+    network_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&DomainReliabilityMonitor::SetDiscardUploads,
+                   monitor_,
+                   discard_uploads));
+  }
+
+  void AddContextForTesting(
+      std::unique_ptr<const DomainReliabilityConfig> config) override {
+    DCHECK(network_task_runner_.get());
+
+    network_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&AddContextForTestingOnNetworkTaskRunner,
+                   monitor_,
+                   base::Passed(&config)));
+  }
+
+  void ForceUploadsForTesting() override {
+    DCHECK(network_task_runner_.get());
+
+    network_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&DomainReliabilityMonitor::ForceUploadsForTesting,
+                   monitor_));
+  }
+
  private:
   std::string upload_reporter_string_;
   base::WeakPtr<DomainReliabilityMonitor> monitor_;
diff --git a/components/domain_reliability/service.h b/components/domain_reliability/service.h
index f0dd617..a96c9fa 100644
--- a/components/domain_reliability/service.h
+++ b/components/domain_reliability/service.h
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 #include "components/domain_reliability/clear_mode.h"
+#include "components/domain_reliability/config.h"
 #include "components/domain_reliability/domain_reliability_export.h"
 #include "components/keyed_service/core/keyed_service.h"
 
@@ -63,6 +64,14 @@
       const base::Callback<void(std::unique_ptr<base::Value>)>& callback)
       const = 0;
 
+  virtual void SetDiscardUploadsForTesting(
+      bool discard_uploads) = 0;
+
+  virtual void AddContextForTesting(
+      std::unique_ptr<const DomainReliabilityConfig> config) = 0;
+
+  virtual void ForceUploadsForTesting() = 0;
+
  protected:
   DomainReliabilityService();
 
diff --git a/components/domain_reliability/uploader.cc b/components/domain_reliability/uploader.cc
index f7d4cd9..19dd56d 100644
--- a/components/domain_reliability/uploader.cc
+++ b/components/domain_reliability/uploader.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/supports_user_data.h"
 #include "components/domain_reliability/util.h"
@@ -58,9 +59,12 @@
           net::URLRequestContextGetter>& url_request_context_getter)
       : time_(time),
         url_request_context_getter_(url_request_context_getter),
-        discard_uploads_(true) {}
+        discard_uploads_(true),
+        shutdown_(false) {}
 
-  ~DomainReliabilityUploaderImpl() override {}
+  ~DomainReliabilityUploaderImpl() override {
+    DCHECK(shutdown_);
+  }
 
   // DomainReliabilityUploader implementation:
   void UploadReport(
@@ -71,7 +75,7 @@
     VLOG(1) << "Uploading report to " << upload_url;
     VLOG(2) << "Report JSON: " << report_json;
 
-    if (discard_uploads_) {
+    if (discard_uploads_ || shutdown_) {
       VLOG(1) << "Discarding report instead of uploading.";
       UploadResult result;
       result.status = UploadResult::SUCCESS;
@@ -92,7 +96,7 @@
         UploadUserData::CreateCreateDataCallback(max_upload_depth + 1));
     fetcher->Start();
 
-    upload_callbacks_[fetcher] = {std::move(owned_fetcher), callback};
+    uploads_[fetcher] = {std::move(owned_fetcher), callback};
 
     base::TimeTicks now = base::TimeTicks::Now();
     if (!last_upload_start_time_.is_null()) {
@@ -107,12 +111,18 @@
     VLOG(1) << "Setting discard_uploads to " << discard_uploads;
   }
 
+  void Shutdown() override {
+    DCHECK(!shutdown_);
+    shutdown_ = true;
+    uploads_.clear();
+  }
+
   // net::URLFetcherDelegate implementation:
   void OnURLFetchComplete(const net::URLFetcher* fetcher) override {
     DCHECK(fetcher);
 
-    auto callback_it = upload_callbacks_.find(fetcher);
-    DCHECK(callback_it != upload_callbacks_.end());
+    auto callback_it = uploads_.find(fetcher);
+    DCHECK(callback_it != uploads_.end());
 
     int net_error = GetNetErrorFromURLRequestStatus(fetcher->GetStatus());
     int http_response_code = fetcher->GetResponseCode();
@@ -145,7 +155,7 @@
                                        &result);
     callback_it->second.second.Run(result);
 
-    upload_callbacks_.erase(callback_it);
+    uploads_.erase(callback_it);
   }
 
  private:
@@ -155,9 +165,10 @@
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
   std::map<const net::URLFetcher*,
            std::pair<std::unique_ptr<net::URLFetcher>, UploadCallback>>
-      upload_callbacks_;
+      uploads_;
   bool discard_uploads_;
   base::TimeTicks last_upload_start_time_;
+  bool shutdown_;
 };
 
 }  // namespace
@@ -190,4 +201,6 @@
   return data->depth();
 }
 
+void DomainReliabilityUploader::Shutdown() {}
+
 }  // namespace domain_reliability
diff --git a/components/domain_reliability/uploader.h b/components/domain_reliability/uploader.h
index 6962711c..c72148f 100644
--- a/components/domain_reliability/uploader.h
+++ b/components/domain_reliability/uploader.h
@@ -65,6 +65,11 @@
                             const GURL& upload_url,
                             const UploadCallback& callback) = 0;
 
+  // Shuts down the uploader prior to destruction. Currently, terminates pending
+  // uploads and prevents the uploader from starting new ones to avoid hairy
+  // lifetime issues at destruction.
+  virtual void Shutdown();
+
   virtual void set_discard_uploads(bool discard_uploads) = 0;
 
   static int GetURLRequestUploadDepth(const net::URLRequest& request);
diff --git a/components/domain_reliability/uploader_unittest.cc b/components/domain_reliability/uploader_unittest.cc
index 4aeb6dd..0b99fc0 100644
--- a/components/domain_reliability/uploader_unittest.cc
+++ b/components/domain_reliability/uploader_unittest.cc
@@ -91,7 +91,7 @@
 
     if (result_.net_error == net::OK)
       NotifyHeadersComplete();
-    else
+    else if (result_.net_error != net::ERR_IO_PENDING)
       NotifyStartError(net::URLRequestStatus::FromError(result_.net_error));
   }
 
@@ -111,7 +111,7 @@
 
 class UploadInterceptor : public net::URLRequestInterceptor {
  public:
-  UploadInterceptor() : last_upload_depth_(-1) {}
+  UploadInterceptor() : request_count_(0), last_upload_depth_(-1) {}
 
   ~UploadInterceptor() override {
     EXPECT_TRUE(results_.empty());
@@ -127,6 +127,8 @@
     last_upload_depth_ =
         DomainReliabilityUploader::GetURLRequestUploadDepth(*request);
 
+    ++request_count_;
+
     return new UploadMockURLRequestJob(request, delegate, result);
   }
 
@@ -155,10 +157,12 @@
     results_.push_back(result);
   }
 
+  int request_count() const { return request_count_; }
   int last_upload_depth() const { return last_upload_depth_; }
 
  private:
   mutable std::list<MockUploadResult> results_;
+  mutable int request_count_;
   mutable int last_upload_depth_;
 };
 
@@ -204,6 +208,10 @@
 
   DomainReliabilityUploader* uploader() const { return uploader_.get(); }
   UploadInterceptor* interceptor() const { return interceptor_; }
+  scoped_refptr<net::TestURLRequestContextGetter>
+      url_request_context_getter() {
+    return url_request_context_getter_;
+  }
 
  private:
   base::MessageLoopForIO message_loop_;
@@ -214,6 +222,7 @@
 };
 
 TEST_F(DomainReliabilityUploaderTest, Null) {
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, SuccessfulUpload) {
@@ -224,6 +233,8 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, c.called_count());
   EXPECT_TRUE(c.last_result().is_success());
+
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, NetworkErrorUpload) {
@@ -234,6 +245,8 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, c.called_count());
   EXPECT_TRUE(c.last_result().is_failure());
+
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, ServerErrorUpload) {
@@ -244,6 +257,8 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, c.called_count());
   EXPECT_TRUE(c.last_result().is_failure());
+
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, RetryAfterUpload) {
@@ -256,6 +271,8 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, c.called_count());
   EXPECT_TRUE(c.last_result().is_retry_after());
+
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, UploadDepth1) {
@@ -267,6 +284,8 @@
   EXPECT_EQ(1u, c.called_count());
 
   EXPECT_EQ(1, interceptor()->last_upload_depth());
+
+  uploader()->Shutdown();
 }
 
 TEST_F(DomainReliabilityUploaderTest, UploadDepth2) {
@@ -278,6 +297,34 @@
   EXPECT_EQ(1u, c.called_count());
 
   EXPECT_EQ(2, interceptor()->last_upload_depth());
+
+  uploader()->Shutdown();
+}
+
+TEST_F(DomainReliabilityUploaderTest, UploadCanceledAtShutdown) {
+  interceptor()->ExpectRequestAndReturnError(net::ERR_IO_PENDING);
+
+  TestUploadCallback c;
+  uploader()->UploadReport("{}", 1, GURL(kUploadURL), c.callback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1, interceptor()->request_count());
+  EXPECT_EQ(0u, c.called_count());
+
+  uploader()->Shutdown();
+
+  EXPECT_EQ(0u, c.called_count());
+
+  url_request_context_getter()->GetURLRequestContext()->AssertNoURLRequests();
+}
+
+TEST_F(DomainReliabilityUploaderTest, NoUploadAfterShutdown) {
+  uploader()->Shutdown();
+
+  TestUploadCallback c;
+  uploader()->UploadReport("{}", 1, GURL(kUploadURL), c.callback());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, c.called_count());
+  EXPECT_EQ(0, interceptor()->request_count());
 }
 
 }  // namespace
diff --git a/components/keyed_service/core/refcounted_keyed_service.cc b/components/keyed_service/core/refcounted_keyed_service.cc
index 6bc4758..04a1ea5 100644
--- a/components/keyed_service/core/refcounted_keyed_service.cc
+++ b/components/keyed_service/core/refcounted_keyed_service.cc
@@ -4,15 +4,13 @@
 
 #include "components/keyed_service/core/refcounted_keyed_service.h"
 
-#include "base/location.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include <utility>
 
 namespace impl {
 
 // static
 void RefcountedKeyedServiceTraits::Destruct(const RefcountedKeyedService* obj) {
-  if (obj->task_runner_.get() != nullptr &&
-      obj->task_runner_.get() != base::ThreadTaskRunnerHandle::Get()) {
+  if (obj->task_runner_ && !obj->task_runner_->RunsTasksOnCurrentThread()) {
     obj->task_runner_->DeleteSoon(FROM_HERE, obj);
   } else {
     delete obj;
@@ -25,9 +23,7 @@
 }
 
 RefcountedKeyedService::RefcountedKeyedService(
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
-    : task_runner_(task_runner) {
-}
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : task_runner_(std::move(task_runner)) {}
 
-RefcountedKeyedService::~RefcountedKeyedService() {
-}
+RefcountedKeyedService::~RefcountedKeyedService() = default;
diff --git a/components/keyed_service/core/refcounted_keyed_service.h b/components/keyed_service/core/refcounted_keyed_service.h
index 891fc28..1cf7f8c 100644
--- a/components/keyed_service/core/refcounted_keyed_service.h
+++ b/components/keyed_service/core/refcounted_keyed_service.h
@@ -6,8 +6,8 @@
 #define COMPONENTS_KEYED_SERVICE_CORE_REFCOUNTED_KEYED_SERVICE_H_
 
 #include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
 #include "base/sequenced_task_runner_helpers.h"
-#include "base/single_thread_task_runner.h"
 #include "components/keyed_service/core/keyed_service_export.h"
 
 class RefcountedKeyedService;
@@ -29,7 +29,7 @@
 // be after the corresponding BrowserContext has been destroyed.
 //
 // Optionally, if you initialize your service with the constructor that takes a
-// single thread task runner, your service will be deleted on that thread. We
+// SequencedTaskRunner, your service will be deleted on that sequence. We
 // can't use content::DeleteOnThread<> directly because RefcountedKeyedService
 // must not depend on //content.
 class KEYED_SERVICE_EXPORT RefcountedKeyedService
@@ -44,19 +44,19 @@
   virtual void ShutdownOnUIThread() = 0;
 
  protected:
-  // If your service does not need to be deleted on a specific thread, use the
+  // If your service does not need to be deleted on a specific sequence, use the
   // default constructor.
   RefcountedKeyedService();
 
-  // If you need your service to be deleted on a specific thread (for example,
+  // If you need your service to be deleted on a specific sequence (for example,
   // you're converting a service that used content::DeleteOnThread<IO>), then
-  // use this constructor with a reference to the SingleThreadTaskRunner (you
+  // use this constructor with a reference to the SequencedTaskRunner (e.g., you
   // can get it from content::BrowserThread::GetTaskRunnerForThread).
   explicit RefcountedKeyedService(
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+      scoped_refptr<base::SequencedTaskRunner> task_runner);
 
   // The second pass destruction can happen anywhere unless you specify which
-  // thread this service must be destroyed on by using the second constructor.
+  // sequence this service must be destroyed on by using the second constructor.
   virtual ~RefcountedKeyedService();
 
  private:
@@ -65,8 +65,8 @@
   friend class base::RefCountedThreadSafe<RefcountedKeyedService,
                                           impl::RefcountedKeyedServiceTraits>;
 
-  // Do we have to delete this object on a specific thread?
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  // Do we have to delete this object on a specific sequence?
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 };
 
 #endif  // COMPONENTS_KEYED_SERVICE_CORE_REFCOUNTED_KEYED_SERVICE_H_
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index ca83e67..765994f 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -85,6 +85,8 @@
     ":call_stack_profile_params",
     "//base",
     "//base:base_static",
+    "//components/browser_watcher:stability",
+    "//components/browser_watcher:stability_data",
     "//components/prefs",
     "//components/variations",
     "//third_party/zlib:compression_utils",
diff --git a/components/metrics/DEPS b/components/metrics/DEPS
index 29757f4..3156f34 100644
--- a/components/metrics/DEPS
+++ b/components/metrics/DEPS
@@ -2,6 +2,7 @@
 # dependencies to a minimal set.
 include_rules = [
   "-components",
+  "+components/browser_watcher",
   "+components/compression",
   "+components/metrics",
   "+components/prefs",
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc
index cc0e457e..46da809 100644
--- a/components/metrics/metrics_service.cc
+++ b/components/metrics/metrics_service.cc
@@ -149,6 +149,8 @@
 #include "base/time/time.h"
 #include "base/tracked_objects.h"
 #include "build/build_config.h"
+#include "components/browser_watcher/stability_data_names.h"
+#include "components/browser_watcher/stability_debugging.h"
 #include "components/metrics/data_use_tracker.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/metrics_log_manager.h"
@@ -446,13 +448,11 @@
 }
 
 void MetricsService::RecordStartOfSessionEnd() {
-  LogCleanShutdown();
-  RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false);
+  LogCleanShutdown(false);
 }
 
 void MetricsService::RecordCompletedSessionEnd() {
-  LogCleanShutdown();
-  RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true);
+  LogCleanShutdown(true);
 }
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
@@ -499,6 +499,8 @@
                                        PrefService* local_state) {
   execution_phase_ = execution_phase;
   local_state->SetInteger(prefs::kStabilityExecutionPhase, execution_phase_);
+  browser_watcher::SetStabilityDataInt(
+      browser_watcher::kStabilityExecutionPhase, execution_phase_);
 }
 
 void MetricsService::RecordBreakpadRegistration(bool success) {
@@ -1209,7 +1211,8 @@
     provider->RecordInitialHistogramSnapshots(&histogram_snapshot_manager_);
 }
 
-void MetricsService::LogCleanShutdown() {
+void MetricsService::LogCleanShutdown(bool end_completed) {
+  DCHECK(IsSingleThreaded());
   // Redundant setting to assure that we always reset this value at shutdown
   // (and that we don't use some alternate path, and not call LogCleanShutdown).
   clean_shutdown_status_ = CLEANLY_SHUTDOWN;
@@ -1217,11 +1220,7 @@
   clean_exit_beacon_.WriteBeaconValue(true);
   RecordCurrentState(local_state_);
   SetExecutionPhase(MetricsService::SHUTDOWN_COMPLETE, local_state_);
-}
-
-void MetricsService::RecordBooleanPrefValue(const char* path, bool value) {
-  DCHECK(IsSingleThreaded());
-  local_state_->SetBoolean(path, value);
+  local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, end_completed);
   RecordCurrentState(local_state_);
 }
 
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h
index 562f465..abfe507d 100644
--- a/components/metrics/metrics_service.h
+++ b/components/metrics/metrics_service.h
@@ -361,15 +361,12 @@
   void IncrementLongPrefsValue(const char* path);
 
   // Records that the browser was shut down cleanly.
-  void LogCleanShutdown();
+  void LogCleanShutdown(bool end_completed);
 
   // Records state that should be periodically saved, like uptime and
   // buffered plugin stability statistics.
   void RecordCurrentState(PrefService* pref);
 
-  // Sets the value of the specified path in prefs and schedules a save.
-  void RecordBooleanPrefValue(const char* path, bool value);
-
   // Notifies observers on a synthetic trial list change.
   void NotifySyntheticTrialObservers();
 
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 251c669..b37377d 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -131,6 +131,7 @@
     "remote/test_utils.cc",
     "remote/test_utils.h",
     "sessions/foreign_sessions_suggestions_provider_unittest.cc",
+    "sessions/tab_delegate_sync_adapter_unittest.cc",
   ]
 
   deps = [
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc
index 4ddd3920..8f7733d 100644
--- a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc
+++ b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc
@@ -45,18 +45,40 @@
 }
 
 void TabDelegateSyncAdapter::OnStateChanged() {
-  // Ignored.
+  // OnStateChanged gets called very frequently, and usually is not important.
+  // But there are some events, like disabling sync and signing out, that are
+  // only captured through OnStateChange. In an attempt to send as few messages
+  // as possible, track if there was session data, and always/only invoke the
+  // callback when transitioning between states. This will also capture the case
+  // when Open Tab is added/removed from syncing types. Note that this requires
+  // the object behind GetOpenTabsUIDelegate() to have its real data when it
+  // becomes available. Otherwise we might transition to think we have session
+  // data, but invoke our callback while the GetOpenTabsUIDelegate() returns bad
+  // results. Fortunately, this isn't a problem. GetOpenTabsUIDelegate() is
+  // guarded by verifying the data type is RUNNING, which always means the
+  // sessions merge has already happened.
+  if (had_session_data_ != HasSessionsData()) {
+    InvokeCallback();
+  }
 }
 
 void TabDelegateSyncAdapter::OnSyncConfigurationCompleted() {
-  InvokeCallback();
+  // Ignored. This event can let us know when the set of enabled data types
+  // change. However, we want to avoid useless notifications as much as
+  // possible, and all of the information captured in this event will also be
+  // covered by OnStateChange.
 }
 
 void TabDelegateSyncAdapter::OnForeignSessionUpdated() {
+  // Foreign tab data changed, always invoke the callback to generate new
+  // suggestions. Interestingly, this is only triggered after sync model type
+  // apply, not after merge. The merge case should always be handled by
+  // OnStateChange.
   InvokeCallback();
 }
 
 void TabDelegateSyncAdapter::InvokeCallback() {
+  had_session_data_ = HasSessionsData();
   if (!change_callback_.is_null()) {
     change_callback_.Run();
   }
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h
index 8796444c..cac1ca42 100644
--- a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h
+++ b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h
@@ -45,6 +45,10 @@
   syncer::SyncService* sync_service_;
   base::Closure change_callback_;
 
+  // Represents whether there was session data the last time |change_callback_|
+  // was invoked.
+  bool had_session_data_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(TabDelegateSyncAdapter);
 };
 
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc b/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc
new file mode 100644
index 0000000..b10c7d56
--- /dev/null
+++ b/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc
@@ -0,0 +1,152 @@
+// Copyright 2016 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/ntp_snippets/sessions/tab_delegate_sync_adapter.h"
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/sync/driver/fake_sync_service.h"
+#include "components/sync_sessions/open_tabs_ui_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::RefCountedMemory;
+using sessions::SessionTab;
+using sessions::SessionWindow;
+using syncer::SyncServiceObserver;
+using sync_sessions::SyncedSession;
+using sync_sessions::OpenTabsUIDelegate;
+using testing::Test;
+
+namespace ntp_snippets {
+namespace {
+
+class TestSyncService : public syncer::FakeSyncService {
+ public:
+  TestSyncService() {}
+  OpenTabsUIDelegate* GetOpenTabsUIDelegate() override { return tabs_; }
+  OpenTabsUIDelegate* tabs_ = nullptr;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestSyncService);
+};
+
+class MockOpenTabsUIDelegate : public OpenTabsUIDelegate {
+ public:
+  MockOpenTabsUIDelegate() {}
+  MOCK_CONST_METHOD2(GetSyncedFaviconForPageURL,
+                     bool(const std::string&,
+                          scoped_refptr<RefCountedMemory>*));
+  MOCK_METHOD1(GetAllForeignSessions, bool(std::vector<const SyncedSession*>*));
+  MOCK_METHOD3(GetForeignTab,
+               bool(const std::string&,
+                    SessionID::id_type,
+                    const SessionTab**));
+  MOCK_METHOD1(DeleteForeignSession, void(const std::string&));
+  MOCK_METHOD2(GetForeignSession,
+               bool(const std::string&, std::vector<const SessionWindow*>*));
+  MOCK_METHOD2(GetForeignSessionTabs,
+               bool(const std::string&, std::vector<const SessionTab*>*));
+  MOCK_METHOD1(GetLocalSession, bool(const SyncedSession**));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockOpenTabsUIDelegate);
+};
+
+class TabDelegateSyncAdapterTest : public Test {
+ public:
+  TabDelegateSyncAdapterTest() : adapter_(&service_) {
+    adapter_.SubscribeForForeignTabChange(base::Bind(
+        &TabDelegateSyncAdapterTest::OnChange, base::Unretained(this)));
+  }
+
+  SyncServiceObserver* observer() { return &adapter_; }
+
+  void SetHasOpenTabs(bool is_enabled) {
+    service_.tabs_ = is_enabled ? &tabs_ : nullptr;
+  }
+
+  void OnChange() { ++callback_count_; }
+
+  int CallbackCount() { return callback_count_; }
+
+ private:
+  MockOpenTabsUIDelegate tabs_;
+  TestSyncService service_;
+  TabDelegateSyncAdapter adapter_;
+  int callback_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TabDelegateSyncAdapterTest);
+};
+
+// CallbackCount should only trigger on transitions between having and not
+// having open tabs.
+TEST_F(TabDelegateSyncAdapterTest, CallbackCount) {
+  ASSERT_EQ(0, CallbackCount());
+  observer()->OnStateChanged();
+  EXPECT_EQ(0, CallbackCount());
+
+  SetHasOpenTabs(true);
+  observer()->OnStateChanged();
+  EXPECT_EQ(1, CallbackCount());
+  observer()->OnStateChanged();
+  EXPECT_EQ(1, CallbackCount());
+
+  SetHasOpenTabs(false);
+  observer()->OnStateChanged();
+  EXPECT_EQ(2, CallbackCount());
+  observer()->OnStateChanged();
+  EXPECT_EQ(2, CallbackCount());
+
+  // OnSyncCycleCompleted should behave like OnStateChanged.
+  observer()->OnSyncCycleCompleted();
+  EXPECT_EQ(2, CallbackCount());
+  SetHasOpenTabs(true);
+  observer()->OnSyncCycleCompleted();
+  EXPECT_EQ(3, CallbackCount());
+  observer()->OnSyncCycleCompleted();
+  EXPECT_EQ(3, CallbackCount());
+}
+
+// No callback should be invoked from OnSyncConfigurationCompleted.
+TEST_F(TabDelegateSyncAdapterTest, OnSyncConfigurationCompleted) {
+  ASSERT_EQ(0, CallbackCount());
+
+  observer()->OnSyncConfigurationCompleted();
+  EXPECT_EQ(0, CallbackCount());
+
+  SetHasOpenTabs(true);
+  observer()->OnSyncConfigurationCompleted();
+  EXPECT_EQ(0, CallbackCount());
+}
+
+// OnForeignSessionUpdated should always trigger a callback.
+TEST_F(TabDelegateSyncAdapterTest, OnForeignSessionUpdated) {
+  ASSERT_EQ(0, CallbackCount());
+  observer()->OnForeignSessionUpdated();
+  EXPECT_EQ(1, CallbackCount());
+  observer()->OnForeignSessionUpdated();
+  EXPECT_EQ(2, CallbackCount());
+
+  SetHasOpenTabs(true);
+  observer()->OnForeignSessionUpdated();
+  EXPECT_EQ(3, CallbackCount());
+  observer()->OnForeignSessionUpdated();
+  EXPECT_EQ(4, CallbackCount());
+}
+
+// If OnForeignSessionUpdated is called before OnStateChanged, then calling
+// OnStateChanged should not trigger a callback.
+TEST_F(TabDelegateSyncAdapterTest, OnForeignSessionUpdatedUpdatesState) {
+  SetHasOpenTabs(true);
+  observer()->OnForeignSessionUpdated();
+  EXPECT_EQ(1, CallbackCount());
+
+  observer()->OnStateChanged();
+  EXPECT_EQ(1, CallbackCount());
+}
+
+}  // namespace
+}  // namespace ntp_snippets
diff --git a/components/proximity_auth/remote_device.h b/components/proximity_auth/remote_device.h
deleted file mode 100644
index a484a2a..0000000
--- a/components/proximity_auth/remote_device.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
-#define COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
-
-#include <string>
-#include <vector>
-
-namespace cryptauth {
-
-struct RemoteDevice {
- public:
-  enum BluetoothType { BLUETOOTH_CLASSIC, BLUETOOTH_LE };
-
-  std::string user_id;
-  std::string name;
-  std::string public_key;
-  BluetoothType bluetooth_type;
-  std::string bluetooth_address;
-  std::string persistent_symmetric_key;
-  std::string sign_in_challenge;
-
-  RemoteDevice();
-  RemoteDevice(const std::string& user_id,
-               const std::string& name,
-               const std::string& public_key,
-               BluetoothType bluetooth_type,
-               const std::string& bluetooth_address,
-               const std::string& persistent_symmetric_key,
-               std::string sign_in_challenge);
-  RemoteDevice(const RemoteDevice& other);
-  ~RemoteDevice();
-};
-
-typedef std::vector<RemoteDevice> RemoteDeviceList;
-
-}  // namespace cryptauth
-
-#endif  // COMPONENTS_PROXIMITY_AUTH_REMOTE_DEVICE_H
diff --git a/components/sync/driver/glue/sync_backend_host_impl.cc b/components/sync/driver/glue/sync_backend_host_impl.cc
index eb78914..06173a76 100644
--- a/components/sync/driver/glue/sync_backend_host_impl.cc
+++ b/components/sync/driver/glue/sync_backend_host_impl.cc
@@ -184,9 +184,7 @@
   DCHECK(!host_);
 
   if (invalidation_handler_registered_) {
-    if (reason == DISABLE_SYNC) {
-      UnregisterInvalidationIds();
-    }
+    CHECK(invalidator_->UpdateRegisteredInvalidationIds(this, ObjectIdSet()));
     invalidator_->UnregisterInvalidationHandler(this);
     invalidator_ = nullptr;
   }
@@ -203,12 +201,6 @@
   registrar_ = nullptr;
 }
 
-void SyncBackendHostImpl::UnregisterInvalidationIds() {
-  if (invalidation_handler_registered_) {
-    CHECK(invalidator_->UpdateRegisteredInvalidationIds(this, ObjectIdSet()));
-  }
-}
-
 ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes(
     ConfigureReason reason,
     const DataTypeConfigStateMap& config_state_map,
diff --git a/components/sync/driver/glue/sync_backend_host_impl.h b/components/sync/driver/glue/sync_backend_host_impl.h
index 55d6686..958805c 100644
--- a/components/sync/driver/glue/sync_backend_host_impl.h
+++ b/components/sync/driver/glue/sync_backend_host_impl.h
@@ -68,7 +68,6 @@
       WARN_UNUSED_RESULT;
   void StopSyncingForShutdown() override;
   void Shutdown(ShutdownReason reason) override;
-  void UnregisterInvalidationIds() override;
   ModelTypeSet ConfigureDataTypes(
       ConfigureReason reason,
       const DataTypeConfigStateMap& config_state_map,
diff --git a/components/sync/engine/fake_sync_engine.cc b/components/sync/engine/fake_sync_engine.cc
index c22ce88..3dab254 100644
--- a/components/sync/engine/fake_sync_engine.cc
+++ b/components/sync/engine/fake_sync_engine.cc
@@ -37,8 +37,6 @@
 
 void FakeSyncEngine::Shutdown(ShutdownReason reason) {}
 
-void FakeSyncEngine::UnregisterInvalidationIds() {}
-
 ModelTypeSet FakeSyncEngine::ConfigureDataTypes(
     ConfigureReason reason,
     const DataTypeConfigStateMap& config_state_map,
diff --git a/components/sync/engine/fake_sync_engine.h b/components/sync/engine/fake_sync_engine.h
index ac8ff25..618fcdec 100644
--- a/components/sync/engine/fake_sync_engine.h
+++ b/components/sync/engine/fake_sync_engine.h
@@ -43,8 +43,6 @@
 
   void Shutdown(ShutdownReason reason) override;
 
-  void UnregisterInvalidationIds() override;
-
   ModelTypeSet ConfigureDataTypes(
       ConfigureReason reason,
       const DataTypeConfigStateMap& config_state_map,
diff --git a/components/sync/engine/sync_engine.h b/components/sync/engine/sync_engine.h
index faf18d6..cdfff52 100644
--- a/components/sync/engine/sync_engine.h
+++ b/components/sync/engine/sync_engine.h
@@ -131,10 +131,6 @@
   // Must be called *after* StopSyncingForShutdown.
   virtual void Shutdown(ShutdownReason reason) = 0;
 
-  // Removes all current registrations from the backend on the
-  // InvalidationService.
-  virtual void UnregisterInvalidationIds() = 0;
-
   // Changes the set of data types that are currently being synced.
   // The ready_task will be run when configuration is done with the
   // set of all types that failed configuration (i.e., if its argument
diff --git a/components/sync_sessions/open_tabs_ui_delegate.h b/components/sync_sessions/open_tabs_ui_delegate.h
index cf8fd5f..66b11d4 100644
--- a/components/sync_sessions/open_tabs_ui_delegate.h
+++ b/components/sync_sessions/open_tabs_ui_delegate.h
@@ -34,7 +34,7 @@
   // session |tag|. Caller does NOT own the SessionTab object.
   // Returns true if the foreign session and tab were found, false otherwise.
   virtual bool GetForeignTab(const std::string& tag,
-                             const SessionID::id_type tab_id,
+                             SessionID::id_type tab_id,
                              const sessions::SessionTab** tab) = 0;
 
   // Delete a foreign session and all its sync data.
diff --git a/components/sync_sessions/sessions_sync_manager.h b/components/sync_sessions/sessions_sync_manager.h
index 5f2b5981..66ec40e 100644
--- a/components/sync_sessions/sessions_sync_manager.h
+++ b/components/sync_sessions/sessions_sync_manager.h
@@ -90,7 +90,7 @@
       const std::string& tag,
       std::vector<const sessions::SessionWindow*>* windows) override;
   bool GetForeignTab(const std::string& tag,
-                     const SessionID::id_type tab_id,
+                     SessionID::id_type tab_id,
                      const sessions::SessionTab** tab) override;
   bool GetForeignSessionTabs(
       const std::string& tag,
diff --git a/components/test_runner/event_sender.h b/components/test_runner/event_sender.h
index c108011b..6a6d7707 100644
--- a/components/test_runner/event_sender.h
+++ b/components/test_runner/event_sender.h
@@ -20,6 +20,7 @@
 #include "third_party/WebKit/public/platform/WebDragOperation.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEventResult.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "third_party/WebKit/public/platform/WebTouchPoint.h"
 
diff --git a/content/browser/DEPS b/content/browser/DEPS
index d85ab38..c4c944f 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -68,6 +68,7 @@
   "+third_party/WebKit/public/platform/WebGestureEvent.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
   "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
+  "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebNavigationHintType.h",
   "+third_party/WebKit/public/platform/WebPageVisibilityState.h",
   "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index e2326c4..0f1869cc 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -199,8 +199,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
-                       AccessibilityEventsAddChild) {
-  RunEventTest(FILE_PATH_LITERAL("add-child.html"));
+                       AccessibilityEventsAddChildOfBody) {
+  RunEventTest(FILE_PATH_LITERAL("add-child-of-body.html"));
 }
 
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
diff --git a/content/browser/dom_storage/dom_storage_context_impl.cc b/content/browser/dom_storage/dom_storage_context_impl.cc
index a42eda4b..2b945de 100644
--- a/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -8,6 +8,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
@@ -74,12 +76,12 @@
     const base::FilePath& localstorage_directory,
     const base::FilePath& sessionstorage_directory,
     storage::SpecialStoragePolicy* special_storage_policy,
-    DOMStorageTaskRunner* task_runner)
+    scoped_refptr<DOMStorageTaskRunner> task_runner)
     : localstorage_directory_(localstorage_directory),
       sessionstorage_directory_(sessionstorage_directory),
-      task_runner_(task_runner),
-      session_id_offset_(
-          abs((g_session_id_offset_sequence++ % 10)) * kSessionIdOffsetAmount),
+      task_runner_(std::move(task_runner)),
+      session_id_offset_(abs((g_session_id_offset_sequence++ % 10)) *
+                         kSessionIdOffsetAmount),
       session_id_sequence_(session_id_offset_),
       is_shutdown_(false),
       force_keep_session_state_(false),
diff --git a/content/browser/dom_storage/dom_storage_context_impl.h b/content/browser/dom_storage/dom_storage_context_impl.h
index c8cf956..acea443 100644
--- a/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/content/browser/dom_storage/dom_storage_context_impl.h
@@ -112,7 +112,7 @@
   DOMStorageContextImpl(const base::FilePath& localstorage_directory,
                         const base::FilePath& sessionstorage_directory,
                         storage::SpecialStoragePolicy* special_storage_policy,
-                        DOMStorageTaskRunner* task_runner);
+                        scoped_refptr<DOMStorageTaskRunner> task_runner);
 
   // Returns the directory path for localStorage, or an empty directory, if
   // there is no backing on disk.
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc
index 67353fd..b8059d9 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -14,8 +14,10 @@
 #include "base/memory/memory_coordinator_client_registry.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/filesystem/public/interfaces/directory.mojom.h"
 #include "components/leveldb/public/interfaces/leveldb.mojom.h"
@@ -26,8 +28,10 @@
 #include "content/browser/leveldb_wrapper_impl.h"
 #include "content/browser/memory/memory_coordinator.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/local_storage_usage_info.h"
 #include "content/public/browser/session_storage_usage_info.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "mojo/common/common_type_converters.h"
 #include "services/file/public/interfaces/constants.mojom.h"
@@ -274,18 +278,41 @@
   base::FilePath data_path;
   if (!profile_path.empty())
     data_path = profile_path.Append(local_partition_path);
-  base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
+
+  scoped_refptr<base::SequencedTaskRunner> primary_sequence;
+  scoped_refptr<base::SequencedTaskRunner> commit_sequence;
+  if (GetContentClient()->browser()->ShouldRedirectDOMStorageTaskRunner()) {
+    // TaskPriority::USER_BLOCKING as an experiment because this is currently
+    // believed to be blocking synchronous IPCs from the renderers:
+    // http://crbug.com/665588 (yes we want to fix that bug, but are taking it
+    // as an opportunity to experiment with the scheduler).
+    base::TaskTraits dom_storage_traits =
+        base::TaskTraits()
+            .WithShutdownBehavior(base::TaskShutdownBehavior::BLOCK_SHUTDOWN)
+            .WithFileIO()
+            .WithPriority(base::TaskPriority::USER_BLOCKING);
+    primary_sequence =
+        base::CreateSequencedTaskRunnerWithTraits(dom_storage_traits);
+    commit_sequence =
+        base::CreateSequencedTaskRunnerWithTraits(dom_storage_traits);
+  } else {
+    base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
+    primary_sequence = worker_pool->GetSequencedTaskRunner(
+        worker_pool->GetNamedSequenceToken("dom_storage_primary"));
+    commit_sequence = worker_pool->GetSequencedTaskRunner(
+        worker_pool->GetNamedSequenceToken("dom_storage_commit"));
+  }
+  DCHECK(primary_sequence);
+  DCHECK(commit_sequence);
+
   context_ = new DOMStorageContextImpl(
       data_path.empty() ? data_path
                         : data_path.AppendASCII(kLocalStorageDirectory),
       data_path.empty() ? data_path
                         : data_path.AppendASCII(kSessionStorageDirectory),
       special_storage_policy,
-      new DOMStorageWorkerPoolTaskRunner(
-          worker_pool,
-          worker_pool->GetNamedSequenceToken("dom_storage_primary"),
-          worker_pool->GetNamedSequenceToken("dom_storage_commit"),
-          BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get()));
+      new DOMStorageWorkerPoolTaskRunner(std::move(primary_sequence),
+                                         std::move(commit_sequence)));
 
   if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
     base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
diff --git a/content/browser/dom_storage/dom_storage_task_runner.cc b/content/browser/dom_storage/dom_storage_task_runner.cc
index c0d00d5..21eb54d 100644
--- a/content/browser/dom_storage/dom_storage_task_runner.cc
+++ b/content/browser/dom_storage/dom_storage_task_runner.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
@@ -15,20 +17,12 @@
 // DOMStorageWorkerPoolTaskRunner
 
 DOMStorageWorkerPoolTaskRunner::DOMStorageWorkerPoolTaskRunner(
-    base::SequencedWorkerPool* sequenced_worker_pool,
-    base::SequencedWorkerPool::SequenceToken primary_sequence_token,
-    base::SequencedWorkerPool::SequenceToken commit_sequence_token,
-    base::SingleThreadTaskRunner* delayed_task_task_runner)
-    : task_runner_(delayed_task_task_runner),
-      sequenced_worker_pool_(sequenced_worker_pool),
-      primary_sequence_token_(primary_sequence_token),
-      commit_sequence_token_(commit_sequence_token) {
-  primary_sequence_checker_.DetachFromSequence();
-  commit_sequence_checker_.DetachFromSequence();
-}
+    scoped_refptr<base::SequencedTaskRunner> primary_sequence,
+    scoped_refptr<base::SequencedTaskRunner> commit_sequence)
+    : primary_sequence_(std::move(primary_sequence)),
+      commit_sequence_(std::move(commit_sequence)) {}
 
-DOMStorageWorkerPoolTaskRunner::~DOMStorageWorkerPoolTaskRunner() {
-}
+DOMStorageWorkerPoolTaskRunner::~DOMStorageWorkerPoolTaskRunner() = default;
 
 bool DOMStorageWorkerPoolTaskRunner::RunsTasksOnCurrentThread() const {
   // It is valid for an implementation to always return true.
@@ -39,61 +33,39 @@
     const tracked_objects::Location& from_here,
     const base::Closure& task,
     base::TimeDelta delay) {
-  // Note base::TaskRunner implements PostTask in terms of PostDelayedTask
-  // with a delay of zero, we detect that usage and avoid the unecessary
-  // trip thru the message loop.
-  if (delay.is_zero()) {
-    return sequenced_worker_pool_->PostSequencedWorkerTaskWithShutdownBehavior(
-        primary_sequence_token_, from_here, task,
-        base::SequencedWorkerPool::BLOCK_SHUTDOWN);
-  }
-  // Post a task to call this->PostTask() after the delay.
-  return task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(base::IgnoreResult(&DOMStorageWorkerPoolTaskRunner::PostTask),
-                 this, from_here, task),
-      delay);
+  return primary_sequence_->PostDelayedTask(from_here, task, delay);
 }
 
 bool DOMStorageWorkerPoolTaskRunner::PostShutdownBlockingTask(
     const tracked_objects::Location& from_here,
     SequenceID sequence_id,
     const base::Closure& task) {
-  return sequenced_worker_pool_->PostSequencedWorkerTaskWithShutdownBehavior(
-      IDtoToken(sequence_id), from_here, task,
-      base::SequencedWorkerPool::BLOCK_SHUTDOWN);
+  return GetSequencedTaskRunner(sequence_id)->PostTask(from_here, task);
 }
 
 void DOMStorageWorkerPoolTaskRunner::AssertIsRunningOnPrimarySequence() const {
-  DCHECK(primary_sequence_checker_.CalledOnValidSequence());
+  DCHECK(primary_sequence_->RunsTasksOnCurrentThread());
 }
 
 void DOMStorageWorkerPoolTaskRunner::AssertIsRunningOnCommitSequence() const {
-  DCHECK(commit_sequence_checker_.CalledOnValidSequence());
+  DCHECK(commit_sequence_->RunsTasksOnCurrentThread());
 }
 
 scoped_refptr<base::SequencedTaskRunner>
 DOMStorageWorkerPoolTaskRunner::GetSequencedTaskRunner(SequenceID sequence_id) {
-  return sequenced_worker_pool_->GetSequencedTaskRunner(IDtoToken(sequence_id));
-}
-
-base::SequencedWorkerPool::SequenceToken
-DOMStorageWorkerPoolTaskRunner::IDtoToken(SequenceID id) const {
-  if (id == PRIMARY_SEQUENCE)
-    return primary_sequence_token_;
-  DCHECK_EQ(COMMIT_SEQUENCE, id);
-  return commit_sequence_token_;
+  if (sequence_id == PRIMARY_SEQUENCE)
+    return primary_sequence_;
+  DCHECK_EQ(COMMIT_SEQUENCE, sequence_id);
+  return commit_sequence_;
 }
 
 // MockDOMStorageTaskRunner
 
 MockDOMStorageTaskRunner::MockDOMStorageTaskRunner(
-    base::SingleThreadTaskRunner* task_runner)
-    : task_runner_(task_runner) {
-}
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : task_runner_(std::move(task_runner)) {}
 
-MockDOMStorageTaskRunner::~MockDOMStorageTaskRunner() {
-}
+MockDOMStorageTaskRunner::~MockDOMStorageTaskRunner() = default;
 
 bool MockDOMStorageTaskRunner::RunsTasksOnCurrentThread() const {
   return task_runner_->RunsTasksOnCurrentThread();
diff --git a/content/browser/dom_storage/dom_storage_task_runner.h b/content/browser/dom_storage/dom_storage_task_runner.h
index 1bdc3bc0..67f400f 100644
--- a/content/browser/dom_storage/dom_storage_task_runner.h
+++ b/content/browser/dom_storage/dom_storage_task_runner.h
@@ -8,15 +8,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
 #include "content/common/content_export.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace content {
 
 // DOMStorage uses two task sequences (primary vs commit) to avoid
@@ -58,17 +52,15 @@
   ~DOMStorageTaskRunner() override {}
 };
 
-// A derived class used in chromium that utilizes a SequenceWorkerPool
-// under dom_storage specific SequenceTokens. The |delayed_task_loop|
-// is used to delay scheduling on the worker pool.
+// A DOMStorageTaskRunner which manages a primary and a commit sequence.
 class CONTENT_EXPORT DOMStorageWorkerPoolTaskRunner :
       public DOMStorageTaskRunner {
  public:
+  // |primary_sequence| and |commit_sequence| should have
+  // TaskShutdownBehaviour::BLOCK_SHUTDOWN semantics.
   DOMStorageWorkerPoolTaskRunner(
-      base::SequencedWorkerPool* sequenced_worker_pool,
-      base::SequencedWorkerPool::SequenceToken primary_sequence_token,
-      base::SequencedWorkerPool::SequenceToken commit_sequence_token,
-      base::SingleThreadTaskRunner* delayed_task_task_runner);
+      scoped_refptr<base::SequencedTaskRunner> primary_sequence,
+      scoped_refptr<base::SequencedTaskRunner> commit_sequence);
 
   bool RunsTasksOnCurrentThread() const override;
 
@@ -90,26 +82,22 @@
   ~DOMStorageWorkerPoolTaskRunner() override;
 
  private:
+  scoped_refptr<base::SequencedTaskRunner> primary_sequence_;
+  scoped_refptr<base::SequencedTaskRunner> commit_sequence_;
 
-  base::SequencedWorkerPool::SequenceToken IDtoToken(SequenceID id) const;
-
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  const scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool_;
-  base::SequencedWorkerPool::SequenceToken primary_sequence_token_;
-  base::SequenceChecker primary_sequence_checker_;
-  base::SequencedWorkerPool::SequenceToken commit_sequence_token_;
-  base::SequenceChecker commit_sequence_checker_;
+  DISALLOW_COPY_AND_ASSIGN(DOMStorageWorkerPoolTaskRunner);
 };
 
 // A derived class used in unit tests that ignores all delays so
 // we don't block in unit tests waiting for timeouts to expire.
 // There is no distinction between [non]-shutdown-blocking or
 // the primary sequence vs the commit sequence in the mock,
-// all tasks are scheduled on |message_loop| with zero delay.
+// all tasks are scheduled on |task_runner| with zero delay.
 class CONTENT_EXPORT MockDOMStorageTaskRunner :
       public DOMStorageTaskRunner {
  public:
-  explicit MockDOMStorageTaskRunner(base::SingleThreadTaskRunner* task_runner);
+  explicit MockDOMStorageTaskRunner(
+      scoped_refptr<base::SequencedTaskRunner> task_runner);
 
   bool RunsTasksOnCurrentThread() const override;
 
@@ -131,7 +119,9 @@
   ~MockDOMStorageTaskRunner() override;
 
  private:
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockDOMStorageTaskRunner);
 };
 
 }  // namespace content
diff --git a/content/browser/payments/payment_app_content_unittest_base.cc b/content/browser/payments/payment_app_content_unittest_base.cc
new file mode 100644
index 0000000..c0c581b2a
--- /dev/null
+++ b/content/browser/payments/payment_app_content_unittest_base.cc
@@ -0,0 +1,118 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/payments/payment_app_content_unittest_base.h"
+
+#include <stdint.h>
+
+#include <set>
+#include <utility>
+
+#include "base/files/file_path.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace content {
+
+namespace {
+
+void RegisterServiceWorkerCallback(bool* called,
+                                   ServiceWorkerStatusCode status,
+                                   const std::string& status_message,
+                                   int64_t registration_id) {
+  EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
+  *called = true;
+}
+
+}  // namespace
+
+PaymentAppContentUnitTestBase::PaymentAppContentUnitTestBase()
+    : thread_bundle_(
+          new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP)),
+      embedded_worker_helper_(new EmbeddedWorkerTestHelper(base::FilePath())),
+      storage_partition_impl_(
+          new StoragePartitionImpl(embedded_worker_helper_->browser_context(),
+                                   base::FilePath(),
+                                   nullptr)),
+      payment_app_context_(new PaymentAppContextImpl()) {
+  embedded_worker_helper_->context_wrapper()->set_storage_partition(
+      storage_partition_impl_.get());
+  payment_app_context_->Init(embedded_worker_helper_->context_wrapper());
+  base::RunLoop().RunUntilIdle();
+}
+
+PaymentAppContentUnitTestBase::~PaymentAppContentUnitTestBase() {
+  payment_app_context_->Shutdown();
+  base::RunLoop().RunUntilIdle();
+}
+
+PaymentAppManager* PaymentAppContentUnitTestBase::CreatePaymentAppManager(
+    const GURL& scope_url,
+    const GURL& sw_script_url) {
+  // Register service worker for payment app manager.
+  bool called = false;
+  embedded_worker_helper_->context()->RegisterServiceWorker(
+      scope_url, sw_script_url, nullptr,
+      base::Bind(&RegisterServiceWorkerCallback, &called));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(called);
+
+  // This function should eventually return created payment app manager
+  // but there is no way to get last created payment app manager from
+  // payment_app_context_->payment_app_managers_ because its type is std::map
+  // and can not ensure its order. So, just make a set of existing payment app
+  // managers before creating a new manager and then check what is a new thing.
+  std::set<PaymentAppManager*> existing_managers;
+  for (const auto& existing_manager :
+       payment_app_context_->payment_app_managers_) {
+    existing_managers.insert(existing_manager.first);
+  }
+
+  // Create a new payment app manager.
+  payments::mojom::PaymentAppManagerPtr manager;
+  mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request =
+      mojo::GetProxy(&manager);
+  payment_app_managers_.push_back(std::move(manager));
+  payment_app_context_->CreatePaymentAppManager(std::move(request));
+  base::RunLoop().RunUntilIdle();
+
+  // Find a last registered payment app manager.
+  for (const auto& candidate_manager :
+       payment_app_context_->payment_app_managers_) {
+    if (!base::ContainsKey(existing_managers, candidate_manager.first))
+      return candidate_manager.first;
+  }
+
+  NOTREACHED();
+  return nullptr;
+}
+
+void PaymentAppContentUnitTestBase::SetManifest(
+    PaymentAppManager* manager,
+    const std::string& scope,
+    payments::mojom::PaymentAppManifestPtr manifest,
+    const PaymentAppManager::SetManifestCallback& callback) {
+  ASSERT_NE(nullptr, manager);
+  manager->SetManifest(scope, std::move(manifest), callback);
+  base::RunLoop().RunUntilIdle();
+}
+
+void PaymentAppContentUnitTestBase::GetManifest(
+    PaymentAppManager* manager,
+    const std::string& scope,
+    const PaymentAppManager::GetManifestCallback& callback) {
+  ASSERT_NE(nullptr, manager);
+  manager->GetManifest(scope, callback);
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace content
diff --git a/content/browser/payments/payment_app_content_unittest_base.h b/content/browser/payments/payment_app_content_unittest_base.h
new file mode 100644
index 0000000..d9cc41e
--- /dev/null
+++ b/content/browser/payments/payment_app_content_unittest_base.h
@@ -0,0 +1,56 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_CONTENT_UNITTEST_BASE_H_
+#define CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_CONTENT_UNITTEST_BASE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/payments/payment_app.mojom.h"
+#include "content/browser/payments/payment_app_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class EmbeddedWorkerTestHelper;
+class PaymentAppContextImpl;
+class StoragePartitionImpl;
+class TestBrowserThreadBundle;
+
+class PaymentAppContentUnitTestBase : public testing::Test {
+ protected:
+  PaymentAppContentUnitTestBase();
+  ~PaymentAppContentUnitTestBase() override;
+
+  PaymentAppContextImpl* payment_app_context() const {
+    return payment_app_context_.get();
+  }
+  PaymentAppManager* CreatePaymentAppManager(const GURL& scope_url,
+                                             const GURL& sw_script_url);
+  void SetManifest(PaymentAppManager* manager,
+                   const std::string& scope,
+                   payments::mojom::PaymentAppManifestPtr manifest,
+                   const PaymentAppManager::SetManifestCallback& callback);
+  void GetManifest(PaymentAppManager* manager,
+                   const std::string& scope,
+                   const PaymentAppManager::GetManifestCallback& callback);
+
+ private:
+  std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
+  std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
+  std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
+  scoped_refptr<PaymentAppContextImpl> payment_app_context_;
+  std::vector<payments::mojom::PaymentAppManagerPtr> payment_app_managers_;
+
+  DISALLOW_COPY_AND_ASSIGN(PaymentAppContentUnitTestBase);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_PAYMENTS_PAYMENT_APP_CONTENT_UNITTEST_BASE_H_
diff --git a/content/browser/payments/payment_app_context_impl.cc b/content/browser/payments/payment_app_context_impl.cc
index 37a3fcbf..eb5a955 100644
--- a/content/browser/payments/payment_app_context_impl.cc
+++ b/content/browser/payments/payment_app_context_impl.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
-#include "content/browser/payments/payment_app_database.h"
 #include "content/browser/payments/payment_app_manager.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -64,7 +63,10 @@
 
 void PaymentAppContextImpl::GetAllManifests(
     const GetAllManifestsCallback& callback) {
-  NOTIMPLEMENTED();
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&PaymentAppContextImpl::GetAllManifestsOnIO, this, callback));
 }
 
 PaymentAppContextImpl::~PaymentAppContextImpl() {
@@ -101,4 +103,21 @@
   is_shutdown_ = true;
 }
 
+void PaymentAppContextImpl::GetAllManifestsOnIO(
+    const GetAllManifestsCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  payment_app_database()->ReadAllManifests(base::Bind(
+      &PaymentAppContextImpl::DidGetAllManifestsOnIO, this, callback));
+}
+
+void PaymentAppContextImpl::DidGetAllManifestsOnIO(
+    const GetAllManifestsCallback& callback,
+    Manifests manifests) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(callback, base::Passed(std::move(manifests))));
+}
+
 }  // namespace content
diff --git a/content/browser/payments/payment_app_context_impl.h b/content/browser/payments/payment_app_context_impl.h
index 824b5c27..8785bbc 100644
--- a/content/browser/payments/payment_app_context_impl.h
+++ b/content/browser/payments/payment_app_context_impl.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/payments/payment_app.mojom.h"
+#include "content/browser/payments/payment_app_database.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/payment_app_context.h"
 
@@ -66,12 +67,11 @@
   PaymentAppDatabase* payment_app_database() const;
 
   // PaymentAppContext implementation:
+  // Should be accessed only on the UI thread.
   void GetAllManifests(const GetAllManifestsCallback& callback) override;
 
- protected:
-  friend class PaymentAppManagerTest;
-
  private:
+  friend class PaymentAppContentUnitTestBase;
   friend class base::RefCountedThreadSafe<PaymentAppContextImpl>;
   ~PaymentAppContextImpl() override;
 
@@ -84,6 +84,10 @@
   void ShutdownOnIO();
   void DidShutdown();
 
+  void GetAllManifestsOnIO(const GetAllManifestsCallback& callback);
+  void DidGetAllManifestsOnIO(const GetAllManifestsCallback& callback,
+                              PaymentAppDatabase::Manifests manifests);
+
   // Only accessed on the IO thread.
   std::unique_ptr<PaymentAppDatabase> payment_app_database_;
 
diff --git a/content/browser/payments/payment_app_context_impl_unittest.cc b/content/browser/payments/payment_app_context_impl_unittest.cc
new file mode 100644
index 0000000..213e021
--- /dev/null
+++ b/content/browser/payments/payment_app_context_impl_unittest.cc
@@ -0,0 +1,114 @@
+// Copyright 2016 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 <cstddef>
+#include <string>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "components/payments/payment_app.mojom.h"
+#include "content/browser/payments/payment_app_content_unittest_base.h"
+#include "content/browser/payments/payment_app_context_impl.h"
+#include "content/public/browser/payment_app_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class PaymentAppManager;
+
+namespace {
+
+void SetManifestCallback(bool* called,
+                         payments::mojom::PaymentAppManifestError* out_error,
+                         payments::mojom::PaymentAppManifestError error) {
+  *called = true;
+  *out_error = error;
+}
+
+void GetAllManifestsCallback(bool* called,
+                             PaymentAppContext::Manifests* out_manifests,
+                             PaymentAppContext::Manifests manifests) {
+  *called = true;
+  *out_manifests = std::move(manifests);
+}
+
+}  // namespace
+
+class PaymentAppContextTest : public PaymentAppContentUnitTestBase {
+ public:
+  PaymentAppContextTest() {}
+  ~PaymentAppContextTest() override {}
+
+  void GetAllManifests(PaymentAppContext::GetAllManifestsCallback callback) {
+    payment_app_context()->GetAllManifests(callback);
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void CreatePaymentApp(const GURL& scope_url, const GURL& sw_script_url) {
+    PaymentAppManager* manager =
+        CreatePaymentAppManager(scope_url, sw_script_url);
+
+    payments::mojom::PaymentAppOptionPtr option =
+        payments::mojom::PaymentAppOption::New();
+    option->name = "Visa ****";
+    option->id = "payment-app-id";
+    option->icon = std::string("payment-app-icon");
+    option->enabled_methods.push_back("visa");
+
+    payments::mojom::PaymentAppManifestPtr manifest =
+        payments::mojom::PaymentAppManifest::New();
+    manifest->icon = std::string("payment-app-icon");
+    manifest->name = scope_url.spec();
+    manifest->options.push_back(std::move(option));
+
+    payments::mojom::PaymentAppManifestError error = payments::mojom::
+        PaymentAppManifestError::MANIFEST_STORAGE_OPERATION_FAILED;
+    bool called = false;
+    SetManifest(manager, scope_url.spec(), std::move(manifest),
+                base::Bind(&SetManifestCallback, &called, &error));
+    ASSERT_TRUE(called);
+
+    ASSERT_EQ(error, payments::mojom::PaymentAppManifestError::NONE);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PaymentAppContextTest);
+};
+
+TEST_F(PaymentAppContextTest, Test) {
+  static const struct {
+    const char* scopeUrl;
+    const char* scriptUrl;
+  } kPaymentAppInfo[] = {
+      {"https://example.com/a", "https://example.com/a/script.js"},
+      {"https://example.com/b", "https://example.com/b/script.js"},
+      {"https://example.com/c", "https://example.com/c/script.js"}};
+
+  for (size_t i = 0; i < arraysize(kPaymentAppInfo); i++) {
+    CreatePaymentApp(GURL(kPaymentAppInfo[i].scopeUrl),
+                     GURL(kPaymentAppInfo[i].scriptUrl));
+  }
+
+  PaymentAppContext::Manifests manifests;
+  bool called = false;
+  GetAllManifests(base::Bind(&GetAllManifestsCallback, &called, &manifests));
+  ASSERT_TRUE(called);
+
+  ASSERT_EQ(manifests.size(), 3U);
+  size_t i = 0;
+  for (const auto& manifest : manifests) {
+    EXPECT_EQ(manifest.second->icon.value(), "payment-app-icon");
+    EXPECT_EQ(manifest.second->name, kPaymentAppInfo[i++].scopeUrl);
+    ASSERT_EQ(manifest.second->options.size(), 1U);
+    EXPECT_EQ(manifest.second->options[0]->icon.value(), "payment-app-icon");
+    EXPECT_EQ(manifest.second->options[0]->name, "Visa ****");
+    EXPECT_EQ(manifest.second->options[0]->id, "payment-app-id");
+    ASSERT_EQ(manifest.second->options[0]->enabled_methods.size(), 1U);
+    EXPECT_EQ(manifest.second->options[0]->enabled_methods[0], "visa");
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/payments/payment_app_database.cc b/content/browser/payments/payment_app_database.cc
index 765de42..1809cc3 100644
--- a/content/browser/payments/payment_app_database.cc
+++ b/content/browser/payments/payment_app_database.cc
@@ -19,6 +19,32 @@
 
 const char kPaymentAppManifestDataKey[] = "PaymentAppManifestData";
 
+payments::mojom::PaymentAppManifestPtr DeserializePaymentAppManifest(
+    const std::string& input) {
+  PaymentAppManifestProto manifest_proto;
+  if (!manifest_proto.ParseFromString(input))
+    return nullptr;
+
+  payments::mojom::PaymentAppManifestPtr manifest =
+      payments::mojom::PaymentAppManifest::New();
+  manifest->name = manifest_proto.name();
+  if (manifest_proto.has_icon())
+    manifest->icon = manifest_proto.icon();
+  for (const auto& option_proto : manifest_proto.options()) {
+    payments::mojom::PaymentAppOptionPtr option =
+        payments::mojom::PaymentAppOption::New();
+    option->name = option_proto.name();
+    if (option_proto.has_icon())
+      option->icon = option_proto.icon();
+    option->id = option_proto.id();
+    for (const auto& method : option_proto.enabled_methods())
+      option->enabled_methods.push_back(method);
+    manifest->options.push_back(std::move(option));
+  }
+
+  return manifest;
+}
+
 }  // namespace
 
 PaymentAppDatabase::PaymentAppDatabase(
@@ -52,6 +78,16 @@
                         weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
+void PaymentAppDatabase::ReadAllManifests(
+    const ReadAllManifestsCallback& callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  service_worker_context_->GetUserDataForAllRegistrations(
+      kPaymentAppManifestDataKey,
+      base::Bind(&PaymentAppDatabase::DidReadAllManifests,
+                 weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
 void PaymentAppDatabase::DidFindRegistrationToWriteManifest(
     payments::mojom::PaymentAppManifestPtr manifest,
     const WriteManifestCallback& callback,
@@ -127,34 +163,41 @@
     return;
   }
 
-  PaymentAppManifestProto manifest_proto;
-  bool success = manifest_proto.ParseFromString(data[0]);
-  if (!success) {
+  payments::mojom::PaymentAppManifestPtr manifest =
+      DeserializePaymentAppManifest(data[0]);
+  if (!manifest) {
     callback.Run(payments::mojom::PaymentAppManifest::New(),
                  payments::mojom::PaymentAppManifestError::
                      MANIFEST_STORAGE_OPERATION_FAILED);
     return;
   }
 
-  payments::mojom::PaymentAppManifestPtr manifest =
-      payments::mojom::PaymentAppManifest::New();
-  manifest->name = manifest_proto.name();
-  if (manifest_proto.has_icon())
-    manifest->icon = manifest_proto.icon();
-  for (const auto& option_proto : manifest_proto.options()) {
-    payments::mojom::PaymentAppOptionPtr option =
-        payments::mojom::PaymentAppOption::New();
-    option->name = option_proto.name();
-    if (option_proto.has_icon())
-      option->icon = option_proto.icon();
-    option->id = option_proto.id();
-    for (const auto& method : option_proto.enabled_methods())
-      option->enabled_methods.push_back(method);
-    manifest->options.push_back(std::move(option));
-  }
-
   callback.Run(std::move(manifest),
                payments::mojom::PaymentAppManifestError::NONE);
 }
 
+void PaymentAppDatabase::DidReadAllManifests(
+    const ReadAllManifestsCallback& callback,
+    const std::vector<std::pair<int64_t, std::string>>& raw_data,
+    ServiceWorkerStatusCode status) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (status != SERVICE_WORKER_OK) {
+    callback.Run(Manifests());
+    return;
+  }
+
+  Manifests manifests;
+  for (const auto& item_of_raw_data : raw_data) {
+    payments::mojom::PaymentAppManifestPtr manifest =
+        DeserializePaymentAppManifest(item_of_raw_data.second);
+    if (!manifest)
+      continue;
+
+    manifests.push_back(
+        ManifestWithID(item_of_raw_data.first, std::move(manifest)));
+  }
+
+  callback.Run(std::move(manifests));
+}
+
 }  // namespace content
diff --git a/content/browser/payments/payment_app_database.h b/content/browser/payments/payment_app_database.h
index d27b7d838..faeab1f 100644
--- a/content/browser/payments/payment_app_database.h
+++ b/content/browser/payments/payment_app_database.h
@@ -28,6 +28,10 @@
   using ReadManifestCallback =
       base::Callback<void(payments::mojom::PaymentAppManifestPtr,
                           payments::mojom::PaymentAppManifestError)>;
+  using ManifestWithID =
+      std::pair<int64_t, payments::mojom::PaymentAppManifestPtr>;
+  using Manifests = std::vector<ManifestWithID>;
+  using ReadAllManifestsCallback = base::Callback<void(Manifests)>;
 
   explicit PaymentAppDatabase(
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
@@ -37,6 +41,7 @@
                      payments::mojom::PaymentAppManifestPtr manifest,
                      const WriteManifestCallback& callback);
   void ReadManifest(const GURL& scope, const ReadManifestCallback& callback);
+  void ReadAllManifests(const ReadAllManifestsCallback& callback);
 
  private:
   // WriteManifest callbacks
@@ -57,6 +62,12 @@
                        const std::vector<std::string>& data,
                        ServiceWorkerStatusCode status);
 
+  // ReadAllManifests callbacks
+  void DidReadAllManifests(
+      const ReadAllManifestsCallback& callback,
+      const std::vector<std::pair<int64_t, std::string>>& raw_data,
+      ServiceWorkerStatusCode status);
+
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
   base::WeakPtrFactory<PaymentAppDatabase> weak_ptr_factory_;
 
diff --git a/content/browser/payments/payment_app_manager.h b/content/browser/payments/payment_app_manager.h
index 12287ab..bff1918 100644
--- a/content/browser/payments/payment_app_manager.h
+++ b/content/browser/payments/payment_app_manager.h
@@ -27,7 +27,7 @@
   ~PaymentAppManager() override;
 
  private:
-  friend class PaymentAppManagerTest;
+  friend class PaymentAppContentUnitTestBase;
 
   // payments::mojom::PaymentAppManager methods:
   void SetManifest(const std::string& scope,
diff --git a/content/browser/payments/payment_app_manager_unittest.cc b/content/browser/payments/payment_app_manager_unittest.cc
index 3ad5513..c680ed6 100644
--- a/content/browser/payments/payment_app_manager_unittest.cc
+++ b/content/browser/payments/payment_app_manager_unittest.cc
@@ -2,24 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/payments/payment_app_manager.h"
-
-#include <memory>
 #include <utility>
-#include <vector>
 
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/run_loop.h"
+#include "base/macros.h"
 #include "components/payments/payment_app.mojom.h"
-#include "content/browser/service_worker/embedded_worker_test_helper.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "content/browser/payments/payment_app_content_unittest_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace content {
 namespace {
@@ -29,16 +18,6 @@
 const char kUnregisteredServiceWorkerPattern[] =
     "https://example.com/unregistered";
 
-void RegisterServiceWorkerCallback(bool* called,
-                                   int64_t* store_registration_id,
-                                   ServiceWorkerStatusCode status,
-                                   const std::string& status_message,
-                                   int64_t registration_id) {
-  EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
-  *called = true;
-  *store_registration_id = registration_id;
-}
-
 void SetManifestCallback(bool* called,
                          payments::mojom::PaymentAppManifestError* out_error,
                          payments::mojom::PaymentAppManifestError error) {
@@ -75,65 +54,17 @@
 
 }  // namespace
 
-class PaymentAppManagerTest : public testing::Test {
+class PaymentAppManagerTest : public PaymentAppContentUnitTestBase {
  public:
-  PaymentAppManagerTest()
-      : thread_bundle_(
-            new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP)),
-        embedded_worker_helper_(new EmbeddedWorkerTestHelper(base::FilePath())),
-        storage_partition_impl_(new StoragePartitionImpl(
-            embedded_worker_helper_->browser_context(),
-            base::FilePath(), nullptr)),
-        sw_registration_id_(0) {
-    embedded_worker_helper_->context_wrapper()->set_storage_partition(
-        storage_partition_impl_.get());
-
-    payment_app_context_ = new PaymentAppContextImpl();
-    payment_app_context_->Init(embedded_worker_helper_->context_wrapper());
-
-    bool called = false;
-    embedded_worker_helper_->context()->RegisterServiceWorker(
-        GURL(kServiceWorkerPattern), GURL(kServiceWorkerScript), NULL,
-        base::Bind(&RegisterServiceWorkerCallback, &called,
-                   &sw_registration_id_));
-    base::RunLoop().RunUntilIdle();
-    EXPECT_TRUE(called);
-
-    mojo::InterfaceRequest<payments::mojom::PaymentAppManager> request =
-        mojo::GetProxy(&service_);
-    payment_app_context_->CreatePaymentAppManager(std::move(request));
-    base::RunLoop().RunUntilIdle();
-
-    manager_ = payment_app_context_->payment_app_managers_.begin()->first;
-    EXPECT_NE(nullptr, manager_);
+  PaymentAppManagerTest() {
+    manager_ = CreatePaymentAppManager(GURL(kServiceWorkerPattern),
+                                       GURL(kServiceWorkerScript));
+    EXPECT_NE(manager_, nullptr);
   }
 
-  ~PaymentAppManagerTest() override {
-    payment_app_context_->Shutdown();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void SetManifest(const std::string& scope,
-                   payments::mojom::PaymentAppManifestPtr manifest,
-                   const PaymentAppManager::SetManifestCallback& callback) {
-    manager_->SetManifest(scope, std::move(manifest), callback);
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void GetManifest(const std::string& scope,
-                   const PaymentAppManager::GetManifestCallback& callback) {
-    manager_->GetManifest(scope, callback);
-    base::RunLoop().RunUntilIdle();
-  }
+  PaymentAppManager* payment_app_manager() const { return manager_; }
 
  private:
-  std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
-  std::unique_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
-  std::unique_ptr<StoragePartitionImpl> storage_partition_impl_;
-  int64_t sw_registration_id_;
-  scoped_refptr<PaymentAppContextImpl> payment_app_context_;
-  payments::mojom::PaymentAppManagerPtr service_;
-
   // Owned by payment_app_context_.
   PaymentAppManager* manager_;
 
@@ -144,25 +75,27 @@
   bool called = false;
   payments::mojom::PaymentAppManifestError error = payments::mojom::
       PaymentAppManifestError::MANIFEST_STORAGE_OPERATION_FAILED;
-  SetManifest(kServiceWorkerPattern, CreatePaymentAppManifestForTest(),
+  SetManifest(payment_app_manager(), kServiceWorkerPattern,
+              CreatePaymentAppManifestForTest(),
               base::Bind(&SetManifestCallback, &called, &error));
-
   ASSERT_TRUE(called);
+
   ASSERT_EQ(error, payments::mojom::PaymentAppManifestError::NONE);
 
   called = false;
   payments::mojom::PaymentAppManifestPtr read_manifest;
   payments::mojom::PaymentAppManifestError read_error = payments::mojom::
       PaymentAppManifestError::MANIFEST_STORAGE_OPERATION_FAILED;
-  GetManifest(kServiceWorkerPattern, base::Bind(&GetManifestCallback, &called,
-                                                &read_manifest, &read_error));
-
+  GetManifest(
+      payment_app_manager(), kServiceWorkerPattern,
+      base::Bind(&GetManifestCallback, &called, &read_manifest, &read_error));
   ASSERT_TRUE(called);
+
   ASSERT_EQ(read_error, payments::mojom::PaymentAppManifestError::NONE);
-  EXPECT_EQ(read_manifest->icon, std::string("payment-app-icon"));
+  EXPECT_EQ(read_manifest->icon.value(), "payment-app-icon");
   EXPECT_EQ(read_manifest->name, "Payment App");
   ASSERT_EQ(read_manifest->options.size(), 1U);
-  EXPECT_EQ(read_manifest->options[0]->icon, std::string("payment-app-icon"));
+  EXPECT_EQ(read_manifest->options[0]->icon.value(), "payment-app-icon");
   EXPECT_EQ(read_manifest->options[0]->name, "Visa ****");
   EXPECT_EQ(read_manifest->options[0]->id, "payment-app-id");
   ASSERT_EQ(read_manifest->options[0]->enabled_methods.size(), 1U);
@@ -173,11 +106,11 @@
   bool called = false;
   payments::mojom::PaymentAppManifestError error =
       payments::mojom::PaymentAppManifestError::NONE;
-  SetManifest(kUnregisteredServiceWorkerPattern,
+  SetManifest(payment_app_manager(), kUnregisteredServiceWorkerPattern,
               CreatePaymentAppManifestForTest(),
               base::Bind(&SetManifestCallback, &called, &error));
-
   ASSERT_TRUE(called);
+
   EXPECT_EQ(error, payments::mojom::PaymentAppManifestError::NO_ACTIVE_WORKER);
 }
 
@@ -187,10 +120,10 @@
   payments::mojom::PaymentAppManifestError read_error =
       payments::mojom::PaymentAppManifestError::NONE;
   GetManifest(
-      kUnregisteredServiceWorkerPattern,
+      payment_app_manager(), kUnregisteredServiceWorkerPattern,
       base::Bind(&GetManifestCallback, &called, &read_manifest, &read_error));
-
   ASSERT_TRUE(called);
+
   EXPECT_EQ(read_error,
             payments::mojom::PaymentAppManifestError::NO_ACTIVE_WORKER);
 }
@@ -200,10 +133,11 @@
   payments::mojom::PaymentAppManifestPtr read_manifest;
   payments::mojom::PaymentAppManifestError read_error =
       payments::mojom::PaymentAppManifestError::NONE;
-  GetManifest(kServiceWorkerPattern, base::Bind(&GetManifestCallback, &called,
-                                                &read_manifest, &read_error));
-
+  GetManifest(
+      payment_app_manager(), kServiceWorkerPattern,
+      base::Bind(&GetManifestCallback, &called, &read_manifest, &read_error));
   ASSERT_TRUE(called);
+
   EXPECT_EQ(read_error, payments::mojom::PaymentAppManifestError::
                             MANIFEST_STORAGE_OPERATION_FAILED);
 }
diff --git a/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h b/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
index 76924471..d58516d 100644
--- a/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
+++ b/content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_RAILS_FILTER_MAC_H_
 
 #include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
 namespace content {
diff --git a/content/browser/renderer_host/input/touch_emulator.h b/content/browser/renderer_host/input/touch_emulator.h
index 6baee6e..5c02fbb5 100644
--- a/content/browser/renderer_host/input/touch_emulator.h
+++ b/content/browser/renderer_host/input/touch_emulator.h
@@ -16,6 +16,10 @@
 #include "ui/events/gesture_detection/gesture_provider_config_helper.h"
 #include "ui/gfx/geometry/size_f.h"
 
+namespace blink {
+class WebMouseWheelEvent;
+}
+
 namespace content {
 
 // Emulates touch input with mouse and keyboard.
diff --git a/content/browser/renderer_host/input/touch_emulator_unittest.cc b/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 600badd5..4c23f76 100644
--- a/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/time/time.h"
 #include "content/browser/renderer_host/input/touch_emulator_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/events/blink/web_input_event_traits.h"
 
 using blink::WebGestureEvent;
diff --git a/content/browser/renderer_host/input/web_input_event_builders_android.h b/content/browser/renderer_host/input/web_input_event_builders_android.h
index ffba982..e845c3d 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -11,6 +11,7 @@
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace content {
 
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac.h b/content/browser/renderer_host/input/web_input_event_builders_mac.h
index 03a3d6ca..02b8a9e 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_mac.h
+++ b/content/browser/renderer_host/input/web_input_event_builders_mac.h
@@ -8,6 +8,7 @@
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 @class NSEvent;
 @class NSView;
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index 746a7b59..42757f3 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -9,6 +9,7 @@
 #include "content/browser/renderer_host/overscroll_controller_delegate.h"
 #include "content/public/browser/overscroll_configuration.h"
 #include "content/public/common/content_switches.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 using blink::WebInputEvent;
 
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index e3822dab..a750b03 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -120,7 +120,7 @@
  private:
   friend class BackgroundSyncManagerTest;
   friend class BackgroundSyncServiceImplTest;
-  friend class PaymentAppManagerTest;
+  friend class PaymentAppContentUnitTestBase;
   friend class StoragePartitionImplMap;
   FRIEND_TEST_ALL_PREFIXES(StoragePartitionShaderClearTest, ClearShaderCache);
   FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
diff --git a/content/common/DEPS b/content/common/DEPS
index 66adccce..c36293e 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -23,6 +23,7 @@
   "+third_party/WebKit/public/platform/WebHistoryScrollRestorationType.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
   "+third_party/WebKit/public/platform/WebInsecureRequestPolicy.h",
+  "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h",
   "+third_party/WebKit/public/platform/WebPageVisibilityState.h",
   "+third_party/WebKit/public/platform/WebReferrerPolicy.h",
diff --git a/content/common/input/event_with_latency_info.h b/content/common/input/event_with_latency_info.h
index 750b15d..e9c17ce 100644
--- a/content/common/input/event_with_latency_info.h
+++ b/content/common/input/event_with_latency_info.h
@@ -10,6 +10,7 @@
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/scoped_web_input_event.h"
 #include "ui/events/latency_info.h"
diff --git a/content/common/input/gesture_event_stream_validator.cc b/content/common/input/gesture_event_stream_validator.cc
index 14028ca0..8f20205 100644
--- a/content/common/input/gesture_event_stream_validator.cc
+++ b/content/common/input/gesture_event_stream_validator.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "ui/events/blink/web_input_event_traits.h"
 
diff --git a/content/common/input/input_event_stream_validator.cc b/content/common/input/input_event_stream_validator.cc
index 8025fb8d..fac93dc 100644
--- a/content/common/input/input_event_stream_validator.cc
+++ b/content/common/input/input_event_stream_validator.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "content/public/common/content_switches.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "ui/events/blink/web_input_event_traits.h"
 
diff --git a/content/common/input/input_param_traits_unittest.cc b/content/common/input/input_param_traits_unittest.cc
index ba9e95e..fea7582a 100644
--- a/content/common/input/input_param_traits_unittest.cc
+++ b/content/common/input/input_param_traits_unittest.cc
@@ -19,6 +19,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace content {
 namespace {
diff --git a/content/common/input/synthetic_web_input_event_builders.h b/content/common/input/synthetic_web_input_event_builders.h
index 219264c..10cd518 100644
--- a/content/common/input/synthetic_web_input_event_builders.h
+++ b/content/common/input/synthetic_web_input_event_builders.h
@@ -9,6 +9,7 @@
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 // Provides sensible creation of default WebInputEvents for testing purposes.
 
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index b7cdf32..53c4b23 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -441,6 +441,10 @@
   return nullptr;
 }
 
+bool ContentBrowserClient::ShouldRedirectDOMStorageTaskRunner() {
+  return false;
+}
+
 bool ContentBrowserClient::RedirectNonUINonIOBrowserThreadsToTaskScheduler() {
   return false;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 0d9ccbb..a7d5b8b 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -815,6 +815,10 @@
   // Performs any necessary PostTask API redirection to the task scheduler.
   virtual void PerformExperimentalTaskSchedulerRedirections() {}
 
+  // Returns true if the DOMStorageTaskRunner should be redirected to the task
+  // scheduler.
+  virtual bool ShouldRedirectDOMStorageTaskRunner();
+
   // If this returns true, all BrowserThreads (but UI/IO) that support it on
   // this platform will experimentally be redirected to TaskScheduler.
   virtual bool RedirectNonUINonIOBrowserThreadsToTaskScheduler();
diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h
index 0cda573d..2021572 100644
--- a/content/public/browser/render_widget_host.h
+++ b/content/public/browser/render_widget_host.h
@@ -28,6 +28,7 @@
 
 namespace blink {
 class WebMouseEvent;
+class WebMouseWheelEvent;
 }
 
 namespace content {
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index fac5648..5e17cb57 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -406,7 +406,7 @@
       "navigator.mediaDevices.enumerateDevices()"
       ".then(function(devices) {"
         "devices.forEach(function(device) {"
-          "if (device.kind == 'video-input') {"
+          "if (device.kind == 'videoinput') {"
             "window.domAutomationController.send('has-video-input-device');"
             "return;"
           "}"
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 248b36b1..a96612f 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -30,6 +30,7 @@
 #include "content/renderer/sad_plugin.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/web/WebAXObject.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc
index 8659f38..82605cc1 100644
--- a/content/renderer/input/render_widget_input_handler.cc
+++ b/content/renderer/input/render_widget_input_handler.cc
@@ -25,6 +25,7 @@
 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
 #include "third_party/WebKit/public/platform/WebFloatSize.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h"
 #include "ui/events/blink/web_input_event_traits.h"
 #include "ui/events/latency_info.h"
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index 4924cc68..867da2e 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -110,11 +110,21 @@
   for (int i = 0; i < dest->channels(); ++i)
     web_audio_dest_data[i] = dest->channel(i);
 
+  if (!delay.is_zero()) {  // Zero values are send at the first call.
+    // Substruct the bus duration to get hardware delay.
+    delay -= media::AudioTimestampHelper::FramesToTime(dest->frames(),
+                                                       params_.sample_rate());
+  }
+  DCHECK_GE(delay, base::TimeDelta());
+
   // TODO(xians): Remove the following |web_audio_source_data| after
   // changing the blink interface.
   WebVector<float*> web_audio_source_data(static_cast<size_t>(0));
   client_callback_->render(web_audio_source_data, web_audio_dest_data,
-                           dest->frames());
+                           dest->frames(), delay.InSecondsF(),
+                           (delay_timestamp - base::TimeTicks()).InSecondsF(),
+                           prior_frames_skipped);
+
   return dest->frames();
 }
 
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 3de53eb..046312b 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -23,6 +23,7 @@
 #include "ppapi/shared_impl/ppb_input_event_shared.h"
 #include "third_party/WebKit/public/platform/WebGamepads.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 
 using ppapi::InputEventData;
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index f5cf7b3..1d2b4b0 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -22,6 +22,7 @@
 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebLayer.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "third_party/WebKit/public/platform/WebSize.h"
 #include "third_party/WebKit/public/web/WebWidget.h"
 #include "ui/gfx/geometry/size_conversions.h"
diff --git a/content/renderer/renderer.sb b/content/renderer/renderer.sb
index da6a7c0..fb81878eb 100644
--- a/content/renderer/renderer.sb
+++ b/content/renderer/renderer.sb
@@ -12,6 +12,7 @@
 (allow mach-lookup (global-name "com.apple.FontObjectsServer"))
 (allow mach-lookup (global-name "com.apple.FontServer"))
 (allow mach-lookup (global-name "com.apple.fonts"))
+(allow file-read* (extension "com.apple.app-sandbox.read")) ; https://crbug.com/662686
 
 ; Allow read-only connection to launchservicesd. https://crbug.com/533537
 (allow mach-lookup (global-name "com.apple.lsd.mapdb"))
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 7622839..c46efd4 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1140,6 +1140,9 @@
     "../browser/notifications/notification_id_generator_unittest.cc",
     "../browser/notifications/platform_notification_context_unittest.cc",
     "../browser/notifications/type_converters_unittest.cc",
+    "../browser/payments/payment_app_content_unittest_base.cc",
+    "../browser/payments/payment_app_content_unittest_base.h",
+    "../browser/payments/payment_app_context_impl_unittest.cc",
     "../browser/payments/payment_app_manager_unittest.cc",
     "../browser/presentation/presentation_service_impl_unittest.cc",
     "../browser/presentation/presentation_type_converters_unittest.cc",
diff --git a/content/test/data/accessibility/event/add-child-of-body-expected-win.txt b/content/test/data/accessibility/event/add-child-of-body-expected-win.txt
new file mode 100644
index 0000000..c1071fc
--- /dev/null
+++ b/content/test/data/accessibility/event/add-child-of-body-expected-win.txt
@@ -0,0 +1 @@
+EVENT_OBJECT_SHOW on role=div
diff --git a/content/test/data/accessibility/event/add-child-of-body.html b/content/test/data/accessibility/event/add-child-of-body.html
new file mode 100644
index 0000000..c475bdbf
--- /dev/null
+++ b/content/test/data/accessibility/event/add-child-of-body.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!--
+We can't remove individual attributes from event tests. Only whole lines.
+Remove the IA2_EVENT_TEXT_INSERTED on role=body event because its value
+attribute changes depending on which machine the test is being run.
+@WIN-DENY:*value=*
+-->
+<html>
+<body>
+<div>Hello</div>
+<script>
+  function go() {
+    var div = document.createElement('div');
+    div.textContent = 'world';
+    document.body.appendChild(div);
+  }
+</script>
+</body>
+</html>
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index f5e9a844..d886f8d 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -28,12 +28,6 @@
     self.Fail('Pixel_ScissorTestWithPreserveDrawingBuffer',
         ['android'], bug=521588)
 
-    # TODO(xlai): Check / generate reference images.
-    self.Fail('Pixel_OffscreenCanvasTransferBeforeStyleResize',
-              bug=655335)
-    self.Fail('Pixel_OffscreenCanvasTransferAfterStyleResize',
-              bug=655335)
-
     # TODO(ccameron) fix these on Mac Retina
     # self.Fail('Pixel_CSS3DBlueBox', ['mac'], bug=533690)
 
diff --git a/device/generic_sensor/linux/sensor_data_linux.cc b/device/generic_sensor/linux/sensor_data_linux.cc
index fcc21c2..f4ee366 100644
--- a/device/generic_sensor/linux/sensor_data_linux.cc
+++ b/device/generic_sensor/linux/sensor_data_linux.cc
@@ -20,14 +20,17 @@
 const char kChangedAxisKernelVersion[] = "3.18.0";
 #endif
 
-const base::FilePath::CharType* kSensorsBasePath =
-    FILE_PATH_LITERAL("/sys/bus/iio/devices");
-
 void InitAmbientLightSensorData(SensorPathsLinux* data) {
   std::vector<std::string> file_names{
       "in_illuminance0_input", "in_illuminance_input", "in_illuminance0_raw",
-      "in_illuminance_raw"};
+      "in_illuminance_raw", "in_intensity_both_raw"};
   data->sensor_file_names.push_back(std::move(file_names));
+  data->sensor_frequency_file_name = "in_intensity_sampling_frequency";
+  data->sensor_scale_name = "in_intensity_scale";
+  data->apply_scaling_func = base::Bind(
+      [](double scaling_value, double offset, SensorReading& reading) {
+        reading.values[0] = scaling_value * (reading.values[0] + offset);
+      });
   data->default_configuration =
       PlatformSensorConfiguration(kDefaultAmbientLightFrequencyHz);
 }
@@ -160,11 +163,8 @@
 
 }  // namespace
 
-SensorPathsLinux::SensorPathsLinux()
-    : base_path_sensor_linux(kSensorsBasePath) {}
-
+SensorPathsLinux::SensorPathsLinux() = default;
 SensorPathsLinux::~SensorPathsLinux() = default;
-
 SensorPathsLinux::SensorPathsLinux(const SensorPathsLinux& other) = default;
 
 bool InitSensorData(SensorType type, SensorPathsLinux* data) {
diff --git a/device/generic_sensor/linux/sensor_data_linux.h b/device/generic_sensor/linux/sensor_data_linux.h
index b98523d..5f82898 100644
--- a/device/generic_sensor/linux/sensor_data_linux.h
+++ b/device/generic_sensor/linux/sensor_data_linux.h
@@ -25,8 +25,6 @@
   SensorPathsLinux();
   ~SensorPathsLinux();
   SensorPathsLinux(const SensorPathsLinux& other);
-  // Provides a base path to all sensors.
-  const base::FilePath::CharType* base_path_sensor_linux;
   // Provides an array of sensor file names to be searched for.
   // Different sensors might have up to 3 different file name arrays.
   // One file must be found from each array.
diff --git a/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
index bf38911..e30846d3 100644
--- a/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
+++ b/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -177,6 +177,7 @@
 
   // Creates sensor files according to SensorPathsLinux.
   // Existence of sensor read files mean existence of a sensor.
+  // If |frequency| or |scaling| is zero, the corresponding file is not created.
   void InitializeSupportedSensor(SensorType type,
                                  double frequency,
                                  double offset,
@@ -186,7 +187,7 @@
     EXPECT_TRUE(InitSensorData(type, &data));
 
     base::FilePath sensor_dir = sensors_dir_.GetPath();
-    if (!data.sensor_scale_name.empty()) {
+    if (!data.sensor_scale_name.empty() && scaling != 0) {
       base::FilePath sensor_scale_file =
           base::FilePath(sensor_dir).Append(data.sensor_scale_name);
       WriteValueToFile(sensor_scale_file, scaling);
@@ -198,7 +199,7 @@
       WriteValueToFile(sensor_offset_file, offset);
     }
 
-    if (!data.sensor_frequency_file_name.empty()) {
+    if (!data.sensor_frequency_file_name.empty() && frequency != 0) {
       base::FilePath sensor_frequency_file =
           base::FilePath(sensor_dir).Append(data.sensor_frequency_file_name);
       WriteValueToFile(sensor_frequency_file, frequency);
@@ -511,22 +512,18 @@
       sizeof(SensorReadingSharedBuffer),
       SensorReadingSharedBuffer::GetOffset(SensorType::ACCELEROMETER));
 
-  double sensor_values[3] = {4.5, -2.45, -3.29};
-  InitializeSupportedSensor(
-      SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
-      kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_values);
-
   // As long as WaitOnSensorReadingChangedEvent() waits until client gets a
-  // a notification about readings changed, the frequency file must be deleted
-  // to make the sensor device manager identify this sensor with ON_CHANGE
-  // reporting mode. This will allow the MockPlatformSensorClient to
+  // a notification about readings changed, the frequency file must not be
+  // created to make the sensor device manager identify this sensor with
+  // ON_CHANGE reporting mode. This can be done by sending |kZero| as a
+  // frequency value, which means a file is not created.
+  // This will allow the MockPlatformSensorClient to
   // receive a notification and test if reading values are right. Otherwise
   // the test will not know when data is ready.
-  SensorPathsLinux data;
-  EXPECT_TRUE(InitSensorData(SensorType::ACCELEROMETER, &data));
-  base::FilePath frequency_file = base::FilePath(sensors_dir_.GetPath())
-                                      .Append(data.sensor_frequency_file_name);
-  DeleteFile(frequency_file);
+  double sensor_values[3] = {4.5, -2.45, -3.29};
+  InitializeSupportedSensor(SensorType::ACCELEROMETER, kZero,
+                            kAccelerometerOffsetValue,
+                            kAccelerometerScalingValue, sensor_values);
 
   InitializeMockUdevMethods(sensors_dir_.GetPath());
   SetServiceStart();
@@ -567,22 +564,17 @@
       sizeof(SensorReadingSharedBuffer),
       SensorReadingSharedBuffer::GetOffset(SensorType::GYROSCOPE));
 
-  double sensor_values[3] = {2.2, -3.8, -108.7};
-  InitializeSupportedSensor(SensorType::GYROSCOPE, kGyroscopeFrequencyValue,
-                            kGyroscopeOffsetValue, kGyroscopeScalingValue,
-                            sensor_values);
-
   // As long as WaitOnSensorReadingChangedEvent() waits until client gets a
-  // a notification about readings changed, the frequency file must be deleted
-  // to make the sensor device manager identify this sensor with ON_CHANGE
-  // reporting mode. This will allow the MockPlatformSensorClient to
+  // a notification about readings changed, the frequency file must not be
+  // created to make the sensor device manager identify this sensor with
+  // ON_CHANGE reporting mode. This can be done by sending |kZero| as a
+  // frequency value, which means a file is not created.
+  // This will allow the MockPlatformSensorClient to
   // receive a notification and test if reading values are right. Otherwise
   // the test will not know when data is ready.
-  SensorPathsLinux data;
-  EXPECT_TRUE(InitSensorData(SensorType::GYROSCOPE, &data));
-  base::FilePath frequency_file = base::FilePath(sensors_dir_.GetPath())
-                                      .Append(data.sensor_frequency_file_name);
-  DeleteFile(frequency_file);
+  double sensor_values[3] = {2.2, -3.8, -108.7};
+  InitializeSupportedSensor(SensorType::GYROSCOPE, kZero, kGyroscopeOffsetValue,
+                            kGyroscopeScalingValue, sensor_values);
 
   InitializeMockUdevMethods(sensors_dir_.GetPath());
   SetServiceStart();
@@ -624,22 +616,18 @@
       sizeof(SensorReadingSharedBuffer),
       SensorReadingSharedBuffer::GetOffset(SensorType::MAGNETOMETER));
 
-  double sensor_values[3] = {2.2, -3.8, -108.7};
-  InitializeSupportedSensor(
-      SensorType::MAGNETOMETER, kMagnetometerFrequencyValue,
-      kMagnetometerOffsetValue, kMagnetometerScalingValue, sensor_values);
-
   // As long as WaitOnSensorReadingChangedEvent() waits until client gets a
-  // a notification about readings changed, the frequency file must be deleted
-  // to make the sensor device manager identify this sensor with ON_CHANGE
-  // reporting mode. This will allow the MockPlatformSensorClient to
+  // a notification about readings changed, the frequency file must not be
+  // created to make the sensor device manager identify this sensor with
+  // ON_CHANGE reporting mode. This can be done by sending |kZero| as a
+  // frequency value, which means a file is not created.
+  // This will allow the MockPlatformSensorClient to
   // receive a notification and test if reading values are right. Otherwise
   // the test will not know when data is ready.
-  SensorPathsLinux data;
-  EXPECT_TRUE(InitSensorData(SensorType::MAGNETOMETER, &data));
-  base::FilePath frequency_file = base::FilePath(sensors_dir_.GetPath())
-                                      .Append(data.sensor_frequency_file_name);
-  DeleteFile(frequency_file);
+  double sensor_values[3] = {2.2, -3.8, -108.7};
+  InitializeSupportedSensor(SensorType::MAGNETOMETER, kZero,
+                            kMagnetometerOffsetValue, kMagnetometerScalingValue,
+                            sensor_values);
 
   InitializeMockUdevMethods(sensors_dir_.GetPath());
   SetServiceStart();
diff --git a/docs/android_studio.md b/docs/android_studio.md
index bb85dba..ee3a6025 100644
--- a/docs/android_studio.md
+++ b/docs/android_studio.md
@@ -29,7 +29,7 @@
 
 To import the project:
 
-* Use "Import Project", and select the directory containing the generated project.
+* Use "Import Project", and select the directory containing the generated project, by default `out-gn/Debug/gradle`.
 
 You need to re-run `generate_gradle.py` whenever `BUILD.gn` files change.
 
@@ -76,6 +76,10 @@
 * Turn on automatic import:
     * Help -&gt; Find Action -&gt; "Auto Import"
         * Tick all the boxes under "Java" and change the dropdown to "All".
+* Turn on documentation on mouse hover:
+    * Help -&gt; Find Action -&gt; "Show quick documentation on mouse move"
+* Turn on line numbers:
+    * Help -&gt; Find Action -&gt; "Show line numbers"
 
 ### Useful Shortcuts
 
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn
index 6098597..03ee799 100644
--- a/extensions/renderer/BUILD.gn
+++ b/extensions/renderer/BUILD.gn
@@ -302,6 +302,10 @@
     "scoped_web_frame.h",
     "script_context_set_unittest.cc",
     "script_context_unittest.cc",
+    "string_source_map.cc",
+    "string_source_map.h",
+    "test_v8_extension_configuration.cc",
+    "test_v8_extension_configuration.h",
     "utils_unittest.cc",
   ]
 
diff --git a/extensions/renderer/module_system_test.cc b/extensions/renderer/module_system_test.cc
index 3ea5ce5..96f834e 100644
--- a/extensions/renderer/module_system_test.cc
+++ b/extensions/renderer/module_system_test.cc
@@ -23,7 +23,8 @@
 #include "extensions/renderer/logging_native_handler.h"
 #include "extensions/renderer/object_backed_native_handler.h"
 #include "extensions/renderer/safe_builtins.h"
-#include "extensions/renderer/source_map.h"
+#include "extensions/renderer/string_source_map.h"
+#include "extensions/renderer/test_v8_extension_configuration.h"
 #include "extensions/renderer/utils_native_handler.h"
 #include "ui/base/resource/resource_bundle.h"
 
@@ -38,30 +39,6 @@
   }
 };
 
-class V8ExtensionConfigurator {
- public:
-  V8ExtensionConfigurator()
-      : safe_builtins_(SafeBuiltins::CreateV8Extension()),
-        names_(1, safe_builtins_->name()),
-        configuration_(
-            new v8::ExtensionConfiguration(static_cast<int>(names_.size()),
-                                           names_.data())) {
-    v8::RegisterExtension(safe_builtins_.get());
-  }
-
-  v8::ExtensionConfiguration* GetConfiguration() {
-    return configuration_.get();
-  }
-
- private:
-  std::unique_ptr<v8::Extension> safe_builtins_;
-  std::vector<const char*> names_;
-  std::unique_ptr<v8::ExtensionConfiguration> configuration_;
-};
-
-base::LazyInstance<V8ExtensionConfigurator>::Leaky g_v8_extension_configurator =
-    LAZY_INSTANCE_INITIALIZER;
-
 }  // namespace
 
 // Native JS functions for doing asserts.
@@ -100,40 +77,13 @@
   bool failed_;
 };
 
-// Source map that operates on std::strings.
-class ModuleSystemTestEnvironment::StringSourceMap : public SourceMap {
- public:
-  StringSourceMap() {}
-  ~StringSourceMap() override {}
-
-  v8::Local<v8::String> GetSource(v8::Isolate* isolate,
-                                 const std::string& name) const override {
-    const auto& source_map_iter = source_map_.find(name);
-    if (source_map_iter == source_map_.end())
-      return v8::Local<v8::String>();
-    return v8::String::NewFromUtf8(isolate, source_map_iter->second.c_str());
-  }
-
-  bool Contains(const std::string& name) const override {
-    return source_map_.count(name);
-  }
-
-  void RegisterModule(const std::string& name, const std::string& source) {
-    CHECK_EQ(0u, source_map_.count(name)) << "Module " << name << " not found";
-    source_map_[name] = source;
-  }
-
- private:
-  std::map<std::string, std::string> source_map_;
-};
-
 ModuleSystemTestEnvironment::ModuleSystemTestEnvironment(v8::Isolate* isolate)
     : isolate_(isolate),
       context_holder_(new gin::ContextHolder(isolate_)),
       handle_scope_(isolate_),
       source_map_(new StringSourceMap()) {
   context_holder_->SetContext(v8::Context::New(
-      isolate, g_v8_extension_configurator.Get().GetConfiguration()));
+      isolate, TestV8ExtensionConfiguration::GetConfiguration()));
   context_.reset(new ScriptContext(context_holder_->context(),
                                    nullptr,  // WebFrame
                                    nullptr,  // Extension
diff --git a/extensions/renderer/module_system_test.h b/extensions/renderer/module_system_test.h
index 495048e..1cfbb7c4 100644
--- a/extensions/renderer/module_system_test.h
+++ b/extensions/renderer/module_system_test.h
@@ -13,11 +13,11 @@
 #include "v8/include/v8.h"
 
 namespace extensions {
+class StringSourceMap;
 
 class ModuleSystemTestEnvironment {
  public:
   class AssertNatives;
-  class StringSourceMap;
 
   explicit ModuleSystemTestEnvironment(v8::Isolate* isolate);
   ~ModuleSystemTestEnvironment();
diff --git a/extensions/renderer/string_source_map.cc b/extensions/renderer/string_source_map.cc
new file mode 100644
index 0000000..1e2d184
--- /dev/null
+++ b/extensions/renderer/string_source_map.cc
@@ -0,0 +1,34 @@
+// Copyright 2016 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 "extensions/renderer/string_source_map.h"
+
+#include "gin/converter.h"
+
+namespace extensions {
+
+StringSourceMap::StringSourceMap() {}
+StringSourceMap::~StringSourceMap() {}
+
+v8::Local<v8::String> StringSourceMap::GetSource(
+    v8::Isolate* isolate,
+    const std::string& name) const {
+  const auto& iter = sources_.find(name);
+  if (iter == sources_.end())
+    return v8::Local<v8::String>();
+  return gin::StringToV8(isolate, iter->second);
+}
+
+bool StringSourceMap::Contains(const std::string& name) const {
+  return sources_.find(name) != sources_.end();
+}
+
+void StringSourceMap::RegisterModule(const std::string& name,
+                                     const std::string& source) {
+  CHECK_EQ(0u, sources_.count(name)) << "A module for '" << name
+                                     << "' already exists.";
+  sources_[name] = source;
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/string_source_map.h b/extensions/renderer/string_source_map.h
new file mode 100644
index 0000000..df3f60f
--- /dev/null
+++ b/extensions/renderer/string_source_map.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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 EXTENSIONS_RENDERER_STRING_SOURCE_MAP_H_
+#define EXTENSIONS_RENDERER_STRING_SOURCE_MAP_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "extensions/renderer/source_map.h"
+
+namespace extensions {
+
+// A testing implementation of the source map that takes strings for source
+// contents.
+class StringSourceMap : public SourceMap {
+ public:
+  StringSourceMap();
+  ~StringSourceMap() override;
+
+  // Adds a new string to be used in the source map.
+  void RegisterModule(const std::string& name, const std::string& source);
+
+  // SourceMap:
+  v8::Local<v8::String> GetSource(v8::Isolate* isolate,
+                                  const std::string& name) const override;
+  bool Contains(const std::string& name) const override;
+
+ private:
+  std::map<std::string, std::string> sources_;
+
+  DISALLOW_COPY_AND_ASSIGN(StringSourceMap);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_RENDERER_STRING_SOURCE_MAP_H_
diff --git a/extensions/renderer/test_v8_extension_configuration.cc b/extensions/renderer/test_v8_extension_configuration.cc
new file mode 100644
index 0000000..20b96cf6
--- /dev/null
+++ b/extensions/renderer/test_v8_extension_configuration.cc
@@ -0,0 +1,36 @@
+// Copyright 2016 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 "extensions/renderer/test_v8_extension_configuration.h"
+
+#include "base/lazy_instance.h"
+#include "extensions/renderer/safe_builtins.h"
+#include "v8/include/v8.h"
+
+namespace extensions {
+
+namespace {
+
+base::LazyInstance<TestV8ExtensionConfiguration>::Leaky
+    g_v8_extension_configuration = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+TestV8ExtensionConfiguration::TestV8ExtensionConfiguration()
+    : safe_builtins_(SafeBuiltins::CreateV8Extension()),
+      v8_extension_names_(1, safe_builtins_->name()),
+      v8_extension_configuration_(new v8::ExtensionConfiguration(
+          static_cast<int>(v8_extension_names_.size()),
+          v8_extension_names_.data())) {
+  v8::RegisterExtension(safe_builtins_.get());
+}
+
+TestV8ExtensionConfiguration::~TestV8ExtensionConfiguration() {}
+
+// static
+v8::ExtensionConfiguration* TestV8ExtensionConfiguration::GetConfiguration() {
+  return g_v8_extension_configuration.Get().v8_extension_configuration_.get();
+}
+
+}  // namespace extensions
diff --git a/extensions/renderer/test_v8_extension_configuration.h b/extensions/renderer/test_v8_extension_configuration.h
new file mode 100644
index 0000000..d3f946a52
--- /dev/null
+++ b/extensions/renderer/test_v8_extension_configuration.h
@@ -0,0 +1,39 @@
+// Copyright 2016 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 EXTENSIONS_RENDERER_TEST_V8_EXTENSION_CONFIGURATION_H_
+#define EXTENSIONS_RENDERER_TEST_V8_EXTENSION_CONFIGURATION_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+
+namespace v8 {
+class Extension;
+class ExtensionConfiguration;
+}
+
+namespace extensions {
+
+// A test helper to allow for the instantiation of the SafeBuiltins
+// v8::Extension, which is needed by most/all of our custom bindings.
+class TestV8ExtensionConfiguration {
+ public:
+  TestV8ExtensionConfiguration();
+  ~TestV8ExtensionConfiguration();
+
+  static v8::ExtensionConfiguration* GetConfiguration();
+
+ private:
+  std::unique_ptr<v8::Extension> safe_builtins_;
+  std::vector<const char*> v8_extension_names_;
+  std::unique_ptr<v8::ExtensionConfiguration> v8_extension_configuration_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestV8ExtensionConfiguration);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_RENDERER_TEST_V8_EXTENSION_CONFIGURATION_H_
diff --git a/ios/build/bots/chromium.fyi/ClangToTiOS.json b/ios/build/bots/chromium.fyi/ClangToTiOS.json
index 8ab8a37..d4df254 100644
--- a/ios/build/bots/chromium.fyi/ClangToTiOS.json
+++ b/ios/build/bots/chromium.fyi/ClangToTiOS.json
@@ -13,6 +13,9 @@
     "target_cpu=\"arm\"",
     "target_os=\"ios\""
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "env": {
     "LLVM_FORCE_HEAD_REVISION": "YES"
   },
diff --git a/ios/build/bots/chromium.fyi/EarlGreyiOS.json b/ios/build/bots/chromium.fyi/EarlGreyiOS.json
index 94c1d01..e0ecb05 100644
--- a/ios/build/bots/chromium.fyi/EarlGreyiOS.json
+++ b/ios/build/bots/chromium.fyi/EarlGreyiOS.json
@@ -14,6 +14,9 @@
     "target_os=\"ios\"",
     "use_goma=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Debug",
   "sdk": "iphonesimulator10.0",
diff --git a/ios/build/bots/chromium.fyi/GomaCanaryiOS.json b/ios/build/bots/chromium.fyi/GomaCanaryiOS.json
index 789157d5d..88a2106 100644
--- a/ios/build/bots/chromium.fyi/GomaCanaryiOS.json
+++ b/ios/build/bots/chromium.fyi/GomaCanaryiOS.json
@@ -14,6 +14,9 @@
     "target_os=\"ios\"",
     "use_goma=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "use_goma_canary": true,
   "compiler": "ninja",
   "configuration": "Release",
diff --git a/ios/build/bots/chromium.fyi/ios-simulator.json b/ios/build/bots/chromium.fyi/ios-simulator.json
index cd3a9d5..8edc76b3 100644
--- a/ios/build/bots/chromium.fyi/ios-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios-simulator.json
@@ -16,6 +16,9 @@
     "target_os=\"ios\"",
     "use_goma=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Debug",
   "sdk": "iphonesimulator10.0",
diff --git a/ios/build/bots/chromium.mac/ios-device-xcode-clang.json b/ios/build/bots/chromium.mac/ios-device-xcode-clang.json
index 3af7e59..29ebf1b 100644
--- a/ios/build/bots/chromium.mac/ios-device-xcode-clang.json
+++ b/ios/build/bots/chromium.mac/ios-device-xcode-clang.json
@@ -19,6 +19,9 @@
     "use_goma=true",
     "use_xcode_clang=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Release",
   "sdk": "iphoneos10.0",
diff --git a/ios/build/bots/chromium.mac/ios-device.json b/ios/build/bots/chromium.mac/ios-device.json
index 007ebeb..dfdc186 100644
--- a/ios/build/bots/chromium.mac/ios-device.json
+++ b/ios/build/bots/chromium.mac/ios-device.json
@@ -18,6 +18,9 @@
     "target_os=\"ios\"",
     "use_goma=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Release",
   "sdk": "iphoneos10.0",
diff --git a/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json b/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
index 4460b36..8343ac0 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
@@ -20,6 +20,9 @@
     "use_goma=true",
     "use_xcode_clang=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Debug",
   "sdk": "iphonesimulator10.0",
diff --git a/ios/build/bots/chromium.mac/ios-simulator.json b/ios/build/bots/chromium.mac/ios-simulator.json
index c90a0b3..145f90f4 100644
--- a/ios/build/bots/chromium.mac/ios-simulator.json
+++ b/ios/build/bots/chromium.mac/ios-simulator.json
@@ -19,6 +19,9 @@
     "target_os=\"ios\"",
     "use_goma=true"
   ],
+  "additional_compile_targets": [
+    "ios:all"
+  ],
   "compiler": "ninja",
   "configuration": "Debug",
   "sdk": "iphonesimulator10.0",
diff --git a/ios/web/public/test/earl_grey/web_view_matchers.h b/ios/web/public/test/earl_grey/web_view_matchers.h
index 71379f68..450d39c 100644
--- a/ios/web/public/test/earl_grey/web_view_matchers.h
+++ b/ios/web/public/test/earl_grey/web_view_matchers.h
@@ -30,14 +30,6 @@
 id<GREYMatcher> webViewContainingBlockedImage(std::string image_id,
                                               WebState* web_state);
 
-// Matcher for WKWebView containing a blocked |image_id|.  When blocked, the
-// image will be smaller than |expected_size|.
-// Note: deprecated. Use webViewContainingBlockedImage(std::string, WebState*)
-// instead. TODO(crbug.com/673520): Remove this method.
-id<GREYMatcher> webViewContainingBlockedImage(std::string image_id,
-                                              CGSize expected_size,
-                                              WebState* web_state);
-
 // Matcher for WKWebView containing an html element which matches |selector|.
 id<GREYMatcher> webViewCssSelector(std::string selector, WebState* web_state);
 
diff --git a/ios/web/public/test/earl_grey/web_view_matchers.mm b/ios/web/public/test/earl_grey/web_view_matchers.mm
index 3981962..435e303 100644
--- a/ios/web/public/test/earl_grey/web_view_matchers.mm
+++ b/ios/web/public/test/earl_grey/web_view_matchers.mm
@@ -156,12 +156,8 @@
   if (!image)
     return grey_nil();
 
-  return webViewContainingBlockedImage(image_id, image.size, web_state);
-}
+  CGSize expected_size = image.size;
 
-id<GREYMatcher> webViewContainingBlockedImage(std::string image_id,
-                                              CGSize expected_size,
-                                              WebState* web_state) {
   MatchesBlock matches = ^BOOL(WKWebView*) {
     return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{
       NSString* const kGetElementAttributesScript = [NSString
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 1044f0f3..cca20f6 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -127,6 +127,7 @@
 
 #if !defined(MOJO_RENDERER)
 #if defined(OPUS_FIXED_POINT)
+// NOTE: Hashes are specific to ARM devices. x86 will not match.
 static const char kOpusEndTrimmingHash_1[] =
     "-4.57,-5.66,-6.52,-6.30,-4.37,-3.61,";
 static const char kOpusEndTrimmingHash_2[] =
@@ -136,7 +137,7 @@
 static const char kOpusSmallCodecDelayHash_1[] =
     "-0.48,-0.09,1.27,1.06,1.54,-0.22,";
 static const char kOpusSmallCodecDelayHash_2[] =
-    "0.29,0.15,-0.19,0.25,0.68,0.83,";
+    "0.29,0.14,-0.20,0.24,0.68,0.83,";
 #else
 // Hash for a full playthrough of "opus-trimming-test.(webm|ogg)".
 static const char kOpusEndTrimmingHash_1[] =
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index b2f1152..3d7bdfb 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -32,6 +32,7 @@
 using base::StringPrintf;
 using base::TestMockTimeTaskRunner;
 using ::testing::_;
+using ::testing::AtLeast;
 using ::testing::Invoke;
 using ::testing::Mock;
 using ::testing::StrictMock;
@@ -213,25 +214,19 @@
                              ScheduleUpdatePrefsOnNetworkThreadConcrete));
   }
 
-  void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly() {
+  void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(int times) {
     EXPECT_CALL(*http_server_props_manager_,
                 ScheduleUpdatePrefsOnNetworkThread(_))
+        .Times(AtLeast(times))
         .WillRepeatedly(Invoke(http_server_props_manager_.get(),
                                &TestingHttpServerPropertiesManager::
                                    ScheduleUpdatePrefsOnNetworkThreadConcrete));
   }
 
-  void ExpectPrefsUpdate() {
+  void ExpectPrefsUpdate(int times) {
     EXPECT_CALL(*http_server_props_manager_,
                 UpdatePrefsFromCacheOnNetworkThread(_))
-        .WillOnce(Invoke(http_server_props_manager_.get(),
-                         &TestingHttpServerPropertiesManager::
-                             UpdatePrefsFromCacheOnNetworkThreadConcrete));
-  }
-
-  void ExpectPrefsUpdateRepeatedly() {
-    EXPECT_CALL(*http_server_props_manager_,
-                UpdatePrefsFromCacheOnNetworkThread(_))
+        .Times(times)
         .WillRepeatedly(
             Invoke(http_server_props_manager_.get(),
                    &TestingHttpServerPropertiesManager::
@@ -487,7 +482,7 @@
 TEST_P(HttpServerPropertiesManagerTest, BadCachedHostPortPair) {
   ExpectCacheUpdate();
   // The prefs are automatically updated in the case corruption is detected.
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
@@ -577,7 +572,7 @@
 TEST_P(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) {
   ExpectCacheUpdate();
   // The prefs are automatically updated in the case corruption is detected.
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
@@ -638,7 +633,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, SupportsSpdy) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   // Post an update task to the network thread. SetSupportsSpdy calls
@@ -670,11 +665,11 @@
 // update could also be scheduled once the previous scheduled update is
 // completed.
 TEST_P(HttpServerPropertiesManagerTest,
-       SinglePrefUpdateForTwoSpdyServerCacheChangese) {
+       SinglePrefUpdateForTwoSpdyServerCacheChanges) {
   http_server_props_manager_->set_pref_update_delay(
       base::TimeDelta::FromMilliseconds(60));
-  ExpectPrefsUpdateRepeatedly();
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+  ExpectPrefsUpdate(2);
+  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(3);
 
   // Post an update task to the network thread. SetSupportsSpdy calls
   // ScheduleUpdatePrefsOnNetworkThread with a delay of 60ms.
@@ -728,7 +723,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServices) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
@@ -759,7 +754,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
@@ -814,7 +809,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, ConfirmAlternativeService) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
 
   url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
   EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
@@ -867,7 +862,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   IPAddress address;
@@ -894,7 +889,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, ServerNetworkStats) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   url::SchemeHostPort mail_server("http", "mail.google.com", 80);
@@ -924,7 +919,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, QuicServerInfo) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectScheduleUpdatePrefsOnNetworkThread();
 
   QuicServerId mail_quic_server_id("mail.google.com", 80);
@@ -957,8 +952,8 @@
   // thus can not mock the pref task runner.
   SetUpWithNonTaskRunner();
 
-  ExpectPrefsUpdate();
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+  ExpectPrefsUpdate(1);
+  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
 
   url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
   http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
@@ -995,7 +990,7 @@
 
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
 
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
 
   // Clear http server data, time out if we do not get a completion callback.
   http_server_props_manager_->Clear(base::MessageLoop::QuitWhenIdleClosure());
@@ -1120,7 +1115,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) {
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
 
   const url::SchemeHostPort server_www("http", "www.google.com", 80);
   const url::SchemeHostPort server_mail("http", "mail.google.com", 80);
@@ -1163,7 +1158,7 @@
   http_server_props_manager_->SetSupportsQuic(true, actual_address);
 
   // Update cache.
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectCacheUpdate();
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
 
@@ -1270,7 +1265,7 @@
 // Do not persist expired or broken alternative service entries to disk.
 TEST_P(HttpServerPropertiesManagerTest,
        DoNotPersistExpiredOrBrokenAlternativeService) {
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly();
+  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(2);
 
   AlternativeServiceInfoVector alternative_service_info_vector;
 
@@ -1300,7 +1295,7 @@
       server, alternative_service_info_vector);
 
   // Update cache.
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   ExpectCacheUpdate();
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
 
@@ -1446,7 +1441,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
-  ExpectPrefsUpdate();
+  ExpectPrefsUpdate(1);
   // Post an update task.
   http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThread();
   // Shutdown comes before the task is executed.
diff --git a/net/nqe/network_qualities_prefs_manager.cc b/net/nqe/network_qualities_prefs_manager.cc
index 64c9f5c..2284e0bc 100644
--- a/net/nqe/network_qualities_prefs_manager.cc
+++ b/net/nqe/network_qualities_prefs_manager.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/rand_util.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -56,7 +57,7 @@
     std::unique_ptr<PrefDelegate> pref_delegate)
     : pref_delegate_(std::move(pref_delegate)),
       pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      prefs_(pref_delegate_->GetDictionaryValue().CreateDeepCopy()),
+      prefs_(pref_delegate_->GetDictionaryValue()),
       network_quality_estimator_(nullptr),
       read_prefs_startup_(ConvertDictionaryValueToMap(prefs_.get())),
       pref_weak_ptr_factory_(this) {
@@ -132,16 +133,26 @@
                         cached_network_quality.effective_connection_type()));
 
   if (prefs_->size() > kMaxCacheSize) {
-    // Delete one value that has key different than |network_id|.
+    // Delete one randomly selected value that has a key that is different from
+    // |network_id|.
     DCHECK_EQ(kMaxCacheSize + 1, prefs_->size());
+    // Generate a random number between 0 and |kMaxCacheSize| -1 (both
+    // inclusive) since the number of network IDs in |prefs_| other than
+    // |network_id| is |kMaxCacheSize|.
+    int index_to_delete = base::RandInt(0, kMaxCacheSize - 1);
+
     for (base::DictionaryValue::Iterator it(*prefs_); !it.IsAtEnd();
          it.Advance()) {
-      const nqe::internal::NetworkID it_network_id =
-          nqe::internal::NetworkID::FromString(it.key());
-      if (it_network_id != network_id) {
+      // Delete the kth element in the dictionary, not including the element
+      // that represents the current network. k == |index_to_delete|.
+      if (nqe::internal::NetworkID::FromString(it.key()) == network_id)
+        continue;
+
+      if (index_to_delete == 0) {
         prefs_->RemovePath(it.key(), nullptr);
         break;
       }
+      index_to_delete--;
     }
   }
   DCHECK_GE(kMaxCacheSize, prefs_->size());
@@ -153,7 +164,7 @@
 ParsedPrefs NetworkQualitiesPrefsManager::ForceReadPrefsForTesting() const {
   DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
   std::unique_ptr<base::DictionaryValue> value(
-      pref_delegate_->GetDictionaryValue().CreateDeepCopy());
+      pref_delegate_->GetDictionaryValue());
   return ConvertDictionaryValueToMap(value.get());
 }
 
diff --git a/net/nqe/network_qualities_prefs_manager.h b/net/nqe/network_qualities_prefs_manager.h
index 5915109..db315e3 100644
--- a/net/nqe/network_qualities_prefs_manager.h
+++ b/net/nqe/network_qualities_prefs_manager.h
@@ -54,8 +54,8 @@
     // Sets the persistent pref to the given value.
     virtual void SetDictionaryValue(const base::DictionaryValue& value) = 0;
 
-    // Returns the peristent prefs.
-    virtual const base::DictionaryValue& GetDictionaryValue() = 0;
+    // Returns a copy of the persistent prefs.
+    virtual std::unique_ptr<base::DictionaryValue> GetDictionaryValue() = 0;
   };
 
   // Creates an instance of the NetworkQualitiesPrefsManager. Ownership of
diff --git a/net/nqe/network_qualities_prefs_manager_unittest.cc b/net/nqe/network_qualities_prefs_manager_unittest.cc
index a171bb0..c25d43c 100644
--- a/net/nqe/network_qualities_prefs_manager_unittest.cc
+++ b/net/nqe/network_qualities_prefs_manager_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/test/histogram_tester.h"
 #include "base/threading/thread_checker.h"
 #include "base/values.h"
 #include "net/base/network_change_notifier.h"
@@ -40,11 +41,11 @@
     ASSERT_EQ(value.size(), value_->size());
   }
 
-  const base::DictionaryValue& GetDictionaryValue() override {
+  std::unique_ptr<base::DictionaryValue> GetDictionaryValue() override {
     DCHECK(thread_checker_.CalledOnValidThread());
 
     read_count_++;
-    return *(value_.get());
+    return value_->CreateDeepCopy();
   }
 
   size_t write_count() const {
@@ -225,6 +226,11 @@
         NOTREACHED();
     }
   }
+
+  base::HistogramTester histogram_tester;
+  estimator.OnPrefsRead(read_prefs);
+  histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", 3, 1);
+
   manager.ShutdownOnPrefThread();
 }
 
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index 93db077b..4261e35 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -788,6 +788,8 @@
   effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
   effective_connection_type_at_last_main_frame_ =
       EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
+  rtt_observations_size_at_last_ect_computation_ = 0;
+  throughput_observations_size_at_last_ect_computation_ = 0;
 
   // Update the local state as part of preparation for the new connection.
   current_network_id_ = GetCurrentNetworkID();
@@ -1390,6 +1392,15 @@
     rtt_observations_.AddObservation(rtt_observation);
     NotifyObserversOfRTT(rtt_observation);
   }
+
+  if (cached_network_quality.network_quality().transport_rtt() !=
+      nqe::internal::InvalidRTT()) {
+    RttObservation rtt_observation(
+        cached_network_quality.network_quality().transport_rtt(), now,
+        NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+    rtt_observations_.AddObservation(rtt_observation);
+    NotifyObserversOfRTT(rtt_observation);
+  }
   return true;
 }
 
@@ -1600,9 +1611,74 @@
     const std::map<nqe::internal::NetworkID,
                    nqe::internal::CachedNetworkQuality> read_prefs) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
   UMA_HISTOGRAM_COUNTS("NQE.Prefs.ReadSize", read_prefs.size());
-  // TODO(tbansal): crbug.com/490870. Incorporate the network quality into the
-  // current estimates.
+  for (auto& it : read_prefs) {
+    EffectiveConnectionType effective_connection_type =
+        it.second.effective_connection_type();
+    if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
+        effective_connection_type == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+      continue;
+    }
+
+    // RTT and throughput values are not set in the prefs.
+    DCHECK_EQ(nqe::internal::InvalidRTT(),
+              it.second.network_quality().http_rtt());
+    DCHECK_EQ(nqe::internal::InvalidRTT(),
+              it.second.network_quality().transport_rtt());
+    DCHECK_EQ(nqe::internal::kInvalidThroughput,
+              it.second.network_quality().downstream_throughput_kbps());
+
+    nqe::internal::NetworkQuality network_quality(
+        typical_network_quality_[effective_connection_type].http_rtt(),
+        typical_network_quality_[effective_connection_type].transport_rtt(),
+        typical_network_quality_[effective_connection_type]
+            .downstream_throughput_kbps());
+
+    nqe::internal::CachedNetworkQuality cached_network_quality(
+        base::TimeTicks::Now(), network_quality, effective_connection_type);
+
+    network_quality_store_->Add(it.first, cached_network_quality);
+    MaybeUpdateNetworkQualityFromCache(it.first, cached_network_quality);
+  }
+}
+
+void NetworkQualityEstimator::MaybeUpdateNetworkQualityFromCache(
+    const nqe::internal::NetworkID& network_id,
+    const nqe::internal::CachedNetworkQuality& cached_network_quality) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (network_id != current_network_id_)
+    return;
+
+  // Since the cached network quality is for the current network, add it to
+  // the current observations.
+  RttObservation http_rtt_observation(
+      cached_network_quality.network_quality().http_rtt(),
+      base::TimeTicks::Now(),
+      NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
+  rtt_observations_.AddObservation(http_rtt_observation);
+  NotifyObserversOfRTT(http_rtt_observation);
+
+  RttObservation transport_rtt_observation(
+      cached_network_quality.network_quality().transport_rtt(),
+      base::TimeTicks::Now(),
+      NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
+  rtt_observations_.AddObservation(transport_rtt_observation);
+  NotifyObserversOfRTT(transport_rtt_observation);
+
+  // TODO(tbansal): crbug.com/673977: Remove this check.
+  if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
+      nqe::internal::kInvalidThroughput) {
+    ThroughputObservation throughput_observation(
+        cached_network_quality.network_quality().downstream_throughput_kbps(),
+        base::TimeTicks::Now(),
+        NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
+    downstream_throughput_kbps_observations_.AddObservation(
+        throughput_observation);
+    NotifyObserversOfThroughput(throughput_observation);
+  }
+
+  ComputeEffectiveConnectionType();
 }
 
 }  // namespace net
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h
index 6bd7019..50ae428 100644
--- a/net/nqe/network_quality_estimator.h
+++ b/net/nqe/network_quality_estimator.h
@@ -489,8 +489,12 @@
   // Virtualized for testing.
   virtual nqe::internal::NetworkID GetCurrentNetworkID() const;
 
+  // Notifies RTT observers of |observation|. May also trigger recomputation
+  // of effective connection type.
   void NotifyObserversOfRTT(const RttObservation& observation);
 
+  // Notifies throughput observers of |observation|. May also trigger
+  // recomputation of effective connection type.
   void NotifyObserversOfThroughput(const ThroughputObservation& observation);
 
   // Returns true only if the |request| can be used for RTT estimation.
@@ -579,6 +583,13 @@
   // if there is a change in its value.
   void ComputeEffectiveConnectionType();
 
+  // May update the network quality of the current network if |network_id|
+  // matches the ID of the current network. |cached_network_quality| is the
+  // cached network quality of the network with id |network_id|.
+  void MaybeUpdateNetworkQualityFromCache(
+      const nqe::internal::NetworkID& network_id,
+      const nqe::internal::CachedNetworkQuality& cached_network_quality);
+
   // Determines if the requests to local host can be used in estimating the
   // network quality. Set to true only for tests.
   bool use_localhost_requests_;
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index cc598319..740c785 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -118,6 +118,17 @@
     observations_.push_back(Observation(rtt_ms, timestamp, source));
   }
 
+  // Returns the last received RTT observation that has source set to |source|.
+  base::TimeDelta last_rtt(NetworkQualityObservationSource source) {
+    for (std::vector<Observation>::reverse_iterator i = observations_.rbegin();
+         i != observations_.rend(); ++i) {
+      Observation observation = *i;
+      if (observation.source == source)
+        return base::TimeDelta::FromMilliseconds(observation.rtt_ms);
+    }
+    return nqe::internal::InvalidRTT();
+  }
+
  private:
   std::vector<Observation> observations_;
 };
@@ -343,6 +354,10 @@
   TestThroughputObserver throughput_observer;
   estimator.AddThroughputObserver(&throughput_observer);
 
+  // |observer| should be notified as soon as it is added.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1U, observer.effective_connection_types().size());
+
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
   histogram_tester.ExpectBucketCount("NQE.CachedNetworkQualityAvailable", true,
@@ -353,7 +368,9 @@
   // Verify that the cached network quality was read, and observers were
   // notified. |observer| must be notified once right after it was added, and
   // once again after the cached network quality was read.
-  EXPECT_EQ(2U, observer.effective_connection_types().size());
+  EXPECT_LE(2U, observer.effective_connection_types().size());
+  EXPECT_EQ(estimator.GetEffectiveConnectionType(),
+            observer.effective_connection_types().back());
   EXPECT_EQ(1U, rtt_observer.observations().size());
   EXPECT_EQ(1U, throughput_observer.observations().size());
 }
@@ -2577,4 +2594,114 @@
   }
 }
 
+// Verify that the cached network qualities from the prefs are correctly used.
+TEST(NetworkQualityEstimatorTest, OnPrefsRead) {
+  base::HistogramTester histogram_tester;
+
+  // Construct the read prefs.
+  std::map<nqe::internal::NetworkID, nqe::internal::CachedNetworkQuality>
+      read_prefs;
+  read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+                                      "test_ect_2g")] =
+      nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G);
+  read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_WIFI,
+                                      "test_ect_slow_2g")] =
+      nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+  read_prefs[nqe::internal::NetworkID(NetworkChangeNotifier::CONNECTION_4G,
+                                      "test_ect_4g")] =
+      nqe::internal::CachedNetworkQuality(EFFECTIVE_CONNECTION_TYPE_4G);
+
+  std::map<std::string, std::string> variation_params;
+  variation_params["effective_connection_type_algorithm"] =
+      "TransportRTTOrDownstreamThroughput";
+  // Disable default platform values so that the effect of cached estimates
+  // at the time of startup can be studied in isolation.
+  TestNetworkQualityEstimator estimator(
+      std::unique_ptr<net::ExternalEstimateProvider>(), variation_params, true,
+      true, false /* use_default_platform_values */);
+
+  // Add observers.
+  TestRTTObserver rtt_observer;
+  TestThroughputObserver throughput_observer;
+  TestRTTAndThroughputEstimatesObserver rtt_throughput_observer;
+  TestEffectiveConnectionTypeObserver effective_connection_type_observer;
+  estimator.AddRTTObserver(&rtt_observer);
+  estimator.AddThroughputObserver(&throughput_observer);
+  estimator.AddRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+  estimator.AddEffectiveConnectionTypeObserver(
+      &effective_connection_type_observer);
+
+  std::string network_name("test_ect_2g");
+
+  estimator.SimulateNetworkChange(
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+  EXPECT_EQ(0u, rtt_observer.observations().size());
+  EXPECT_EQ(0u, throughput_observer.observations().size());
+  EXPECT_LE(0, rtt_throughput_observer.notifications_received());
+
+  // Simulate reading of prefs.
+  estimator.OnPrefsRead(read_prefs);
+  histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", read_prefs.size(),
+                                      1);
+
+  // Taken from network_quality_estimator_params.cc.
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
+            rtt_observer.last_rtt(
+                NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
+            rtt_observer.last_rtt(
+                NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+  EXPECT_EQ(0u, throughput_observer.observations().size());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
+            rtt_throughput_observer.http_rtt());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
+            rtt_throughput_observer.transport_rtt());
+  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+            rtt_throughput_observer.downstream_throughput_kbps());
+  EXPECT_LE(
+      1u,
+      effective_connection_type_observer.effective_connection_types().size());
+  // Compare the ECT stored in prefs with the observer's last entry.
+  EXPECT_EQ(
+      read_prefs[nqe::internal::NetworkID(
+                     NetworkChangeNotifier::CONNECTION_WIFI, network_name)]
+          .effective_connection_type(),
+      effective_connection_type_observer.effective_connection_types().back());
+
+  // Change to a different connection type.
+  network_name = "test_ect_slow_2g";
+  estimator.SimulateNetworkChange(
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, network_name);
+
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(3600),
+            rtt_observer.last_rtt(
+                NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE));
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(3000),
+            rtt_observer.last_rtt(
+                NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE));
+  EXPECT_EQ(0u, throughput_observer.observations().size());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(3600),
+            rtt_throughput_observer.http_rtt());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(3000),
+            rtt_throughput_observer.transport_rtt());
+  EXPECT_EQ(nqe::internal::kInvalidThroughput,
+            rtt_throughput_observer.downstream_throughput_kbps());
+  EXPECT_LE(
+      2u,
+      effective_connection_type_observer.effective_connection_types().size());
+  // Compare with the last entry.
+  EXPECT_EQ(
+      read_prefs[nqe::internal::NetworkID(
+                     NetworkChangeNotifier::CONNECTION_WIFI, network_name)]
+          .effective_connection_type(),
+      effective_connection_type_observer.effective_connection_types().back());
+
+  // Cleanup.
+  estimator.RemoveRTTObserver(&rtt_observer);
+  estimator.RemoveThroughputObserver(&throughput_observer);
+  estimator.RemoveRTTAndThroughputEstimatesObserver(&rtt_throughput_observer);
+  estimator.RemoveEffectiveConnectionTypeObserver(
+      &effective_connection_type_observer);
+}
+
 }  // namespace net
diff --git a/net/quic/chromium/quic_chromium_client_stream.cc b/net/quic/chromium/quic_chromium_client_stream.cc
index 47a0630..2cff4b807 100644
--- a/net/quic/chromium/quic_chromium_client_stream.cc
+++ b/net/quic/chromium/quic_chromium_client_stream.cc
@@ -123,7 +123,7 @@
 size_t QuicChromiumClientStream::WriteHeaders(
     SpdyHeaderBlock header_block,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   if (!session()->IsCryptoHandshakeConfirmed()) {
     auto entry = header_block.find(":method");
     DCHECK(entry != header_block.end());
@@ -134,7 +134,7 @@
       base::Bind(&QuicRequestNetLogCallback, id(), &header_block,
                  QuicSpdyStream::priority()));
   return QuicSpdyStream::WriteHeaders(std::move(header_block), fin,
-                                      ack_notifier_delegate);
+                                      std::move(ack_notifier_delegate));
 }
 
 SpdyPriority QuicChromiumClientStream::priority() const {
diff --git a/net/quic/chromium/quic_chromium_client_stream.h b/net/quic/chromium/quic_chromium_client_stream.h
index f34be225..4cf4cd2 100644
--- a/net/quic/chromium/quic_chromium_client_stream.h
+++ b/net/quic/chromium/quic_chromium_client_stream.h
@@ -78,9 +78,10 @@
   void OnDataAvailable() override;
   void OnClose() override;
   void OnCanWrite() override;
-  size_t WriteHeaders(SpdyHeaderBlock header_block,
-                      bool fin,
-                      QuicAckListenerInterface* ack_notifier_delegate) override;
+  size_t WriteHeaders(
+      SpdyHeaderBlock header_block,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override;
   SpdyPriority priority() const override;
 
   // While the server's set_priority shouldn't be called externally, the creator
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc
index 975fb0c4..997e955 100644
--- a/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -85,7 +85,7 @@
                                 QuicIOVector data,
                                 QuicStreamOffset offset,
                                 bool fin,
-                                QuicAckListenerInterface*));
+                                scoped_refptr<QuicAckListenerInterface>));
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
                     QuicRstStreamErrorCode error,
@@ -111,15 +111,17 @@
       SpdyHeaderBlock headers,
       bool fin,
       SpdyPriority priority,
-      QuicAckListenerInterface* ack_notifier_delegate) override {
-    return WriteHeadersMock(id, headers, fin, priority, ack_notifier_delegate);
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override {
+    return WriteHeadersMock(id, headers, fin, priority,
+                            std::move(ack_notifier_delegate));
   }
   MOCK_METHOD5(WriteHeadersMock,
                size_t(QuicStreamId id,
                       const SpdyHeaderBlock& headers,
                       bool fin,
                       SpdyPriority priority,
-                      QuicAckListenerInterface* ack_notifier_delegate));
+                      const scoped_refptr<QuicAckListenerInterface>&
+                          ack_notifier_delegate));
   MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
 
   using QuicSession::ActivateStream;
diff --git a/net/quic/core/quic_ack_listener_interface.cc b/net/quic/core/quic_ack_listener_interface.cc
index 35ec6103..e599d59 100644
--- a/net/quic/core/quic_ack_listener_interface.cc
+++ b/net/quic/core/quic_ack_listener_interface.cc
@@ -6,11 +6,10 @@
 
 namespace net {
 
-AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener,
-                                       QuicPacketLength data_length)
-    : ack_listener(listener), length(data_length) {
-  DCHECK(listener != nullptr);
-}
+AckListenerWrapper::AckListenerWrapper(
+    scoped_refptr<QuicAckListenerInterface> listener,
+    QuicPacketLength data_length)
+    : ack_listener(std::move(listener)), length(data_length) {}
 
 AckListenerWrapper::AckListenerWrapper(const AckListenerWrapper& other) =
     default;
diff --git a/net/quic/core/quic_ack_listener_interface.h b/net/quic/core/quic_ack_listener_interface.h
index c841fe8..8316da9 100644
--- a/net/quic/core/quic_ack_listener_interface.h
+++ b/net/quic/core/quic_ack_listener_interface.h
@@ -35,7 +35,7 @@
 };
 
 struct QUIC_EXPORT_PRIVATE AckListenerWrapper {
-  AckListenerWrapper(QuicAckListenerInterface* listener,
+  AckListenerWrapper(scoped_refptr<QuicAckListenerInterface> listener,
                      QuicPacketLength data_length);
   AckListenerWrapper(const AckListenerWrapper& other);
   ~AckListenerWrapper();
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 06c05f678..b63b3ada 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -1116,7 +1116,7 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* listener) {
+    scoped_refptr<QuicAckListenerInterface> listener) {
   if (!fin && iov.total_length == 0) {
     QUIC_BUG << "Attempt to send empty stream frame";
     return QuicConsumedData(0, false);
@@ -1135,9 +1135,10 @@
       iov.total_length > kMaxPacketSize) {
     // Use the fast path to send full data packets.
     return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin,
-                                                 listener);
+                                                 std::move(listener));
   }
-  return packet_generator_.ConsumeData(id, iov, offset, fin, listener);
+  return packet_generator_.ConsumeData(id, iov, offset, fin,
+                                       std::move(listener));
 }
 
 void QuicConnection::SendRstStream(QuicStreamId id,
diff --git a/net/quic/core/quic_connection.h b/net/quic/core/quic_connection.h
index 61260c5..97466180 100644
--- a/net/quic/core/quic_connection.h
+++ b/net/quic/core/quic_connection.h
@@ -347,11 +347,12 @@
   // If |listener| is provided, then it will be informed once ACKs have been
   // received for all the packets written in this call.
   // The |listener| is not owned by the QuicConnection and must outlive it.
-  virtual QuicConsumedData SendStreamData(QuicStreamId id,
-                                          QuicIOVector iov,
-                                          QuicStreamOffset offset,
-                                          bool fin,
-                                          QuicAckListenerInterface* listener);
+  virtual QuicConsumedData SendStreamData(
+      QuicStreamId id,
+      QuicIOVector iov,
+      QuicStreamOffset offset,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> listener);
 
   // Send a RST_STREAM frame to the peer.
   virtual void SendRstStream(QuicStreamId id,
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index aa7f049..e60eac3e 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -516,13 +516,14 @@
       StringPiece data,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* listener) {
+      scoped_refptr<QuicAckListenerInterface> listener) {
     if (id != kCryptoStreamId && this->encryption_level() == ENCRYPTION_NONE) {
       this->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
     }
     struct iovec iov;
     QuicIOVector data_iov(MakeIOVector(data, &iov));
-    return QuicConnection::SendStreamData(id, data_iov, offset, fin, listener);
+    return QuicConnection::SendStreamData(id, data_iov, offset, fin,
+                                          std::move(listener));
   }
 
   QuicConsumedData SendStreamData3() {
@@ -4616,7 +4617,7 @@
   EXPECT_CALL(*listener, OnPacketAcked(_, _)).Times(1);
 
   // Send some data, which will register the listener to be notified.
-  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get());
+  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener);
 
   // Process an ACK from the server which should trigger the callback.
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -4633,7 +4634,7 @@
 
   // Send some data, which will register the listener to be notified. This will
   // not be ACKed and so the listener should never be called.
-  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener.get());
+  connection_.SendStreamDataWithString(1, "foo", 0, !kFin, listener);
 
   // Send some other data which we will ACK.
   connection_.SendStreamDataWithString(1, "foo", 0, !kFin, nullptr);
@@ -4661,7 +4662,7 @@
 
   // Send four packets, and register to be notified on ACK of packet 2.
   connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr);
-  connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener.get());
+  connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener);
   connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr);
   connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr);
 
@@ -4695,7 +4696,7 @@
 
   QuicTime default_retransmission_time =
       clock_.ApproximateNow() + DefaultRetransmissionTime();
-  connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener.get());
+  connection_.SendStreamDataWithString(3, "foo", 0, !kFin, listener);
   EXPECT_EQ(1u, stop_waiting()->least_unacked);
 
   EXPECT_EQ(1u, writer_->header().packet_number);
@@ -4732,7 +4733,7 @@
 
   // Send four packets, and register to be notified on ACK of packet 2.
   connection_.SendStreamDataWithString(3, "foo", 0, !kFin, nullptr);
-  connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener.get());
+  connection_.SendStreamDataWithString(3, "bar", 0, !kFin, listener);
   connection_.SendStreamDataWithString(3, "baz", 0, !kFin, nullptr);
   connection_.SendStreamDataWithString(3, "qux", 0, !kFin, nullptr);
 
@@ -4827,7 +4828,7 @@
   // Regression test for b/18594622
   scoped_refptr<MockAckListener> listener(new MockAckListener);
   EXPECT_QUIC_BUG(
-      connection_.SendStreamDataWithString(3, "", 0, !kFin, listener.get()),
+      connection_.SendStreamDataWithString(3, "", 0, !kFin, listener),
       "Attempt to send empty stream frame");
 }
 
diff --git a/net/quic/core/quic_headers_stream.cc b/net/quic/core/quic_headers_stream.cc
index 8eca9f0..0e64661 100644
--- a/net/quic/core/quic_headers_stream.cc
+++ b/net/quic/core/quic_headers_stream.cc
@@ -69,9 +69,11 @@
  public:
   // |extra_bytes| should be initialized to the size of the HTTP/2
   // DATA frame header inserted when forced HOL blocking is enabled.
-  ForceHolAckListener(QuicAckListenerInterface* stream_ack_listener,
-                      int extra_bytes)
-      : stream_ack_listener_(stream_ack_listener), extra_bytes_(extra_bytes) {
+  ForceHolAckListener(
+      scoped_refptr<QuicAckListenerInterface> stream_ack_listener,
+      int extra_bytes)
+      : stream_ack_listener_(std::move(stream_ack_listener)),
+        extra_bytes_(extra_bytes) {
     DCHECK_GE(extra_bytes, 0);
   }
 
@@ -337,11 +339,12 @@
 
 QuicHeadersStream::~QuicHeadersStream() {}
 
-size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id,
-                                       SpdyHeaderBlock headers,
-                                       bool fin,
-                                       SpdyPriority priority,
-                                       QuicAckListenerInterface* ack_listener) {
+size_t QuicHeadersStream::WriteHeaders(
+    QuicStreamId stream_id,
+    SpdyHeaderBlock headers,
+    bool fin,
+    SpdyPriority priority,
+    scoped_refptr<QuicAckListenerInterface> ack_listener) {
   SpdyHeadersIR headers_frame(stream_id, std::move(headers));
   headers_frame.set_fin(fin);
   if (session()->perspective() == Perspective::IS_CLIENT) {
@@ -350,7 +353,7 @@
   }
   SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
   WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
-                    ack_listener);
+                    std::move(ack_listener));
   return frame.size();
 }
 
@@ -378,19 +381,19 @@
     QuicStreamId id,
     StringPiece data,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   SpdyDataIR spdy_data(id, data);
   spdy_data.set_fin(fin);
   SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
   scoped_refptr<ForceHolAckListener> ack_listener;
   if (ack_notifier_delegate != nullptr) {
-    ack_listener = new ForceHolAckListener(ack_notifier_delegate,
+    ack_listener = new ForceHolAckListener(std::move(ack_notifier_delegate),
                                            frame.size() - data.length());
   }
   // Use buffered writes so that coherence of framing is preserved
   // between streams.
   WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
-                    ack_listener.get());
+                    std::move(ack_listener));
 }
 
 QuicConsumedData QuicHeadersStream::WritevStreamData(
@@ -398,7 +401,7 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   const size_t max_len =
       kSpdyInitialFrameSizeLimit - SpdyConstants::kDataFrameMinimumSize;
 
@@ -406,7 +409,7 @@
   size_t total_length = iov.total_length;
 
   if (total_length == 0 && fin) {
-    WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate);
+    WriteDataFrame(id, StringPiece(), true, std::move(ack_notifier_delegate));
     result.fin_consumed = true;
     return result;
   }
diff --git a/net/quic/core/quic_headers_stream.h b/net/quic/core/quic_headers_stream.h
index 4c7885c..7ca6e9d 100644
--- a/net/quic/core/quic_headers_stream.h
+++ b/net/quic/core/quic_headers_stream.h
@@ -51,11 +51,12 @@
   // Writes |headers| for |stream_id| in an HTTP/2 HEADERS frame to the peer.
   // If |fin| is true, the fin flag will be set on the HEADERS frame.  Returns
   // the size, in bytes, of the resulting HEADERS frame.
-  virtual size_t WriteHeaders(QuicStreamId stream_id,
-                              SpdyHeaderBlock headers,
-                              bool fin,
-                              SpdyPriority priority,
-                              QuicAckListenerInterface* ack_listener);
+  virtual size_t WriteHeaders(
+      QuicStreamId stream_id,
+      SpdyHeaderBlock headers,
+      bool fin,
+      SpdyPriority priority,
+      scoped_refptr<QuicAckListenerInterface> ack_listener);
 
   // Write |headers| for |promised_stream_id| on |original_stream_id| in a
   // PUSH_PROMISE frame to peer.
@@ -71,7 +72,7 @@
       QuicIOVector iov,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate);
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // QuicStream implementation
   void OnDataAvailable() override;
@@ -140,10 +141,11 @@
   bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin);
   bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len);
   // Helper for |WritevStreamData()|.
-  void WriteDataFrame(QuicStreamId stream_id,
-                      base::StringPiece data,
-                      bool fin,
-                      QuicAckListenerInterface* ack_notifier_delegate);
+  void WriteDataFrame(
+      QuicStreamId stream_id,
+      base::StringPiece data,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Returns true if the session is still connected.
   bool IsConnected();
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc
index 65727a1..f8d9eb6b 100644
--- a/net/quic/core/quic_headers_stream_test.cc
+++ b/net/quic/core/quic_headers_stream_test.cc
@@ -264,7 +264,7 @@
 
   QuicConsumedData SaveIovAndNotifyAckListener(
       const QuicIOVector& data,
-      QuicAckListenerInterface* ack_listener) {
+      const scoped_refptr<QuicAckListenerInterface>& ack_listener) {
     QuicConsumedData result = SaveIov(data);
     if (ack_listener) {
       ack_listener->OnPacketAcked(result.bytes_consumed,
@@ -324,8 +324,8 @@
                                 SpdyPriority priority,
                                 bool is_request) {
     // Write the headers and capture the outgoing data
-    EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
-                                     false, nullptr))
+    EXPECT_CALL(session_,
+                WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
         .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
     headers_stream_->WriteHeaders(stream_id, headers_.Clone(), fin, priority,
                                   nullptr);
@@ -443,8 +443,8 @@
     QuicStreamId promised_stream_id = NextPromisedStreamId();
     if (perspective() == Perspective::IS_SERVER) {
       // Write the headers and capture the outgoing data
-      EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
-                                       false, nullptr))
+      EXPECT_CALL(session_,
+                  WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
           .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
       headers_stream_->WritePushPromise(stream_id, promised_stream_id,
                                         headers_.Clone());
@@ -963,7 +963,7 @@
               this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
 
       QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
-          id, MakeIOVector(data, &iov), offset, fin, ack_listener.get());
+          id, MakeIOVector(data, &iov), offset, fin, ack_listener);
 
       EXPECT_EQ(consumed_data.bytes_consumed, data_len);
       EXPECT_EQ(consumed_data.fin_consumed, fin);
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc
index 9049c24c..b5a708ac 100644
--- a/net/quic/core/quic_packet_creator.cc
+++ b/net/quic/core/quic_packet_creator.cc
@@ -353,7 +353,7 @@
     QuicStreamOffset iov_offset,
     QuicStreamOffset stream_offset,
     bool fin,
-    QuicAckListenerInterface* listener,
+    scoped_refptr<QuicAckListenerInterface> listener,
     size_t* num_bytes_consumed) {
   DCHECK(queued_frames_.empty());
   // Write out the packet header
@@ -413,7 +413,7 @@
   packet_.encrypted_buffer = encrypted_buffer;
   packet_.encrypted_length = encrypted_length;
   if (listener != nullptr) {
-    packet_.listeners.emplace_back(listener, bytes_consumed);
+    packet_.listeners.emplace_back(std::move(listener), bytes_consumed);
   }
   packet_.retransmittable_frames.push_back(QuicFrame(frame.release()));
   OnSerializedPacket();
@@ -464,10 +464,11 @@
   return false;
 }
 
-void QuicPacketCreator::AddAckListener(QuicAckListenerInterface* listener,
-                                       QuicPacketLength length) {
+void QuicPacketCreator::AddAckListener(
+    scoped_refptr<QuicAckListenerInterface> listener,
+    QuicPacketLength length) {
   DCHECK(!queued_frames_.empty());
-  packet_.listeners.emplace_back(listener, length);
+  packet_.listeners.emplace_back(std::move(listener), length);
 }
 
 void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
diff --git a/net/quic/core/quic_packet_creator.h b/net/quic/core/quic_packet_creator.h
index e02a335..2cd07cf 100644
--- a/net/quic/core/quic_packet_creator.h
+++ b/net/quic/core/quic_packet_creator.h
@@ -119,13 +119,14 @@
   // QuicStreamFrame to the returned SerializedPacket.  Sets
   // |num_bytes_consumed| to the number of bytes consumed to create the
   // QuicStreamFrame.
-  void CreateAndSerializeStreamFrame(QuicStreamId id,
-                                     const QuicIOVector& iov,
-                                     QuicStreamOffset iov_offset,
-                                     QuicStreamOffset stream_offset,
-                                     bool fin,
-                                     QuicAckListenerInterface* listener,
-                                     size_t* num_bytes_consumed);
+  void CreateAndSerializeStreamFrame(
+      QuicStreamId id,
+      const QuicIOVector& iov,
+      QuicStreamOffset iov_offset,
+      QuicStreamOffset stream_offset,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> listener,
+      size_t* num_bytes_consumed);
 
   // Returns true if there are frames pending to be serialized.
   bool HasPendingFrames() const;
@@ -161,7 +162,7 @@
 
   // Adds |listener| to the next serialized packet and notifies the
   // std::listener with |length| as the number of acked bytes.
-  void AddAckListener(QuicAckListenerInterface* listener,
+  void AddAckListener(scoped_refptr<QuicAckListenerInterface> listener,
                       QuicPacketLength length);
 
   // Creates a version negotiation packet which supports |supported_versions|.
diff --git a/net/quic/core/quic_packet_generator.cc b/net/quic/core/quic_packet_generator.cc
index fc7bbbb67..baabe5f4 100644
--- a/net/quic/core/quic_packet_generator.cc
+++ b/net/quic/core/quic_packet_generator.cc
@@ -53,7 +53,7 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* listener) {
+    scoped_refptr<QuicAckListenerInterface> listener) {
   bool has_handshake = (id == kCryptoStreamId);
   QUIC_BUG_IF(has_handshake && fin)
       << "Handshake packets should never send a fin";
@@ -125,7 +125,7 @@
     const QuicIOVector& iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* listener) {
+    scoped_refptr<QuicAckListenerInterface> listener) {
   DCHECK_NE(id, kCryptoStreamId);
   size_t total_bytes_consumed = 0;
   while (total_bytes_consumed < iov.total_length &&
@@ -145,7 +145,7 @@
 
 void QuicPacketGenerator::GenerateMtuDiscoveryPacket(
     QuicByteCount target_mtu,
-    QuicAckListenerInterface* listener) {
+    scoped_refptr<QuicAckListenerInterface> listener) {
   // MTU discovery frames must be sent by themselves.
   if (!packet_creator_.CanSetMaxPacketLength()) {
     QUIC_BUG << "MTU discovery packets should only be sent when no other "
@@ -163,7 +163,7 @@
   SetMaxPacketLength(target_mtu);
   const bool success = packet_creator_.AddPaddedSavedFrame(frame);
   if (listener != nullptr) {
-    packet_creator_.AddAckListener(listener, 0);
+    packet_creator_.AddAckListener(std::move(listener), 0);
   }
   packet_creator_.Flush();
   // The only reason AddFrame can fail is that the packet is too full to fit in
diff --git a/net/quic/core/quic_packet_generator.h b/net/quic/core/quic_packet_generator.h
index 094731eb..ff5c319 100644
--- a/net/quic/core/quic_packet_generator.h
+++ b/net/quic/core/quic_packet_generator.h
@@ -93,24 +93,27 @@
   // mode, these packets will also be sent during this call.
   // |delegate| (if not nullptr) will be informed once all packets sent as a
   // result of this call are ACKed by the peer.
-  QuicConsumedData ConsumeData(QuicStreamId id,
-                               QuicIOVector iov,
-                               QuicStreamOffset offset,
-                               bool fin,
-                               QuicAckListenerInterface* listener);
+  QuicConsumedData ConsumeData(
+      QuicStreamId id,
+      QuicIOVector iov,
+      QuicStreamOffset offset,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> listener);
 
   // Sends as many data only packets as allowed by the send algorithm and the
   // available iov.
   // This path does not support FEC, padding, or bundling pending frames.
-  QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
-                                       const QuicIOVector& iov,
-                                       QuicStreamOffset offset,
-                                       bool fin,
-                                       QuicAckListenerInterface* listener);
+  QuicConsumedData ConsumeDataFastPath(
+      QuicStreamId id,
+      const QuicIOVector& iov,
+      QuicStreamOffset offset,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> listener);
 
   // Generates an MTU discovery packet of specified size.
-  void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu,
-                                  QuicAckListenerInterface* listener);
+  void GenerateMtuDiscoveryPacket(
+      QuicByteCount target_mtu,
+      scoped_refptr<QuicAckListenerInterface> listener);
 
   // Indicates whether batch mode is currently enabled.
   bool InBatchMode();
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc
index 4762222..94be951 100644
--- a/net/quic/core/quic_session.cc
+++ b/net/quic/core/quic_session.cc
@@ -283,7 +283,7 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   // This check is an attempt to deal with potential memory corruption
   // in which |id| ends up set to 1 (the crypto stream id). If this happen
   // it might end up resulting in unencrypted stream data being sent.
@@ -302,8 +302,8 @@
     // up write blocked until OnCanWrite is next called.
     return QuicConsumedData(0, false);
   }
-  QuicConsumedData data =
-      connection_->SendStreamData(id, iov, offset, fin, ack_notifier_delegate);
+  QuicConsumedData data = connection_->SendStreamData(
+      id, iov, offset, fin, std::move(ack_notifier_delegate));
   write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
   return data;
 }
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h
index f3c1522a..a471c56 100644
--- a/net/quic/core/quic_session.h
+++ b/net/quic/core/quic_session.h
@@ -122,7 +122,7 @@
       QuicIOVector iov,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate);
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Called by streams when they want to close the stream in both directions.
   virtual void SendRstStream(QuicStreamId id,
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc
index 84fd78b..fa21afe7 100644
--- a/net/quic/core/quic_session_test.cc
+++ b/net/quic/core/quic_session_test.cc
@@ -168,11 +168,11 @@
       QuicIOVector data,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate) override {
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override {
     QuicConsumedData consumed(data.total_length, fin);
     if (!writev_consumes_all_data_) {
       consumed = QuicSession::WritevData(stream, id, data, offset, fin,
-                                         ack_notifier_delegate);
+                                         std::move(ack_notifier_delegate));
     }
     stream->set_stream_bytes_written(stream->stream_bytes_written() +
                                      consumed.bytes_consumed);
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc
index d081b65..ba6a4192 100644
--- a/net/quic/core/quic_spdy_session.cc
+++ b/net/quic/core/quic_spdy_session.cc
@@ -74,9 +74,9 @@
     SpdyHeaderBlock headers,
     bool fin,
     SpdyPriority priority,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   return headers_stream_->WriteHeaders(id, std::move(headers), fin, priority,
-                                       ack_notifier_delegate);
+                                       std::move(ack_notifier_delegate));
 }
 
 void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) {
diff --git a/net/quic/core/quic_spdy_session.h b/net/quic/core/quic_spdy_session.h
index 4da806a..5eb7fda1 100644
--- a/net/quic/core/quic_spdy_session.h
+++ b/net/quic/core/quic_spdy_session.h
@@ -60,11 +60,12 @@
   // If |fin| is true, then no more data will be sent for the stream |id|.
   // If provided, |ack_notifier_delegate| will be registered to be notified when
   // we have seen ACKs for all packets resulting from this call.
-  virtual size_t WriteHeaders(QuicStreamId id,
-                              SpdyHeaderBlock headers,
-                              bool fin,
-                              SpdyPriority priority,
-                              QuicAckListenerInterface* ack_notifier_delegate);
+  virtual size_t WriteHeaders(
+      QuicStreamId id,
+      SpdyHeaderBlock headers,
+      bool fin,
+      SpdyPriority priority,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
 
diff --git a/net/quic/core/quic_spdy_stream.cc b/net/quic/core/quic_spdy_stream.cc
index 6c9335b76..0bbb982 100644
--- a/net/quic/core/quic_spdy_stream.cc
+++ b/net/quic/core/quic_spdy_stream.cc
@@ -61,9 +61,10 @@
 size_t QuicSpdyStream::WriteHeaders(
     SpdyHeaderBlock header_block,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
-  size_t bytes_written = spdy_session_->WriteHeaders(
-      id(), std::move(header_block), fin, priority_, ack_notifier_delegate);
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
+  size_t bytes_written =
+      spdy_session_->WriteHeaders(id(), std::move(header_block), fin, priority_,
+                                  std::move(ack_notifier_delegate));
   if (fin) {
     // TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
     set_fin_sent(true);
@@ -75,13 +76,13 @@
 void QuicSpdyStream::WriteOrBufferBody(
     const string& data,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
-  WriteOrBufferData(data, fin, ack_notifier_delegate);
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
+  WriteOrBufferData(data, fin, std::move(ack_notifier_delegate));
 }
 
 size_t QuicSpdyStream::WriteTrailers(
     SpdyHeaderBlock trailer_block,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   if (fin_sent()) {
     QUIC_BUG << "Trailers cannot be sent after a FIN.";
     return 0;
@@ -98,8 +99,9 @@
   // Write the trailing headers with a FIN, and close stream for writing:
   // trailers are the last thing to be sent on a stream.
   const bool kFin = true;
-  size_t bytes_written = spdy_session_->WriteHeaders(
-      id(), std::move(trailer_block), kFin, priority_, ack_notifier_delegate);
+  size_t bytes_written =
+      spdy_session_->WriteHeaders(id(), std::move(trailer_block), kFin,
+                                  priority_, std::move(ack_notifier_delegate));
   set_fin_sent(kFin);
 
   // Trailers are the last thing to be sent on a stream, but if there is still
@@ -330,13 +332,14 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   if (spdy_session_->headers_stream() != nullptr &&
       spdy_session_->force_hol_blocking()) {
     return spdy_session_->headers_stream()->WritevStreamData(
-        id(), iov, offset, fin, ack_notifier_delegate);
+        id(), iov, offset, fin, std::move(ack_notifier_delegate));
   }
-  return QuicStream::WritevDataInner(iov, offset, fin, ack_notifier_delegate);
+  return QuicStream::WritevDataInner(iov, offset, fin,
+                                     std::move(ack_notifier_delegate));
 }
 
 }  // namespace net
diff --git a/net/quic/core/quic_spdy_stream.h b/net/quic/core/quic_spdy_stream.h
index 147d85c..783f2b1 100644
--- a/net/quic/core/quic_spdy_stream.h
+++ b/net/quic/core/quic_spdy_stream.h
@@ -102,19 +102,22 @@
 
   // Writes the headers contained in |header_block| to the dedicated
   // headers stream.
-  virtual size_t WriteHeaders(SpdyHeaderBlock header_block,
-                              bool fin,
-                              QuicAckListenerInterface* ack_notifier_delegate);
+  virtual size_t WriteHeaders(
+      SpdyHeaderBlock header_block,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Sends |data| to the peer, or buffers if it can't be sent immediately.
-  void WriteOrBufferBody(const std::string& data,
-                         bool fin,
-                         QuicAckListenerInterface* ack_notifier_delegate);
+  void WriteOrBufferBody(
+      const std::string& data,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Writes the trailers contained in |trailer_block| to the dedicated
   // headers stream. Trailers will always have the FIN set.
-  virtual size_t WriteTrailers(SpdyHeaderBlock trailer_block,
-                               QuicAckListenerInterface* ack_notifier_delegate);
+  virtual size_t WriteTrailers(
+      SpdyHeaderBlock trailer_block,
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Marks the trailers as consumed. This applies to the case where this object
   // receives headers and trailers as QuicHeaderLists via calls to
@@ -198,7 +201,7 @@
       QuicIOVector iov,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate) override;
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override;
 
  private:
   friend class test::QuicSpdyStreamPeer;
diff --git a/net/quic/core/quic_stream.cc b/net/quic/core/quic_stream.cc
index 651a990..403a1b1c 100644
--- a/net/quic/core/quic_stream.cc
+++ b/net/quic/core/quic_stream.cc
@@ -41,9 +41,12 @@
 
 }  // namespace
 
-QuicStream::PendingData::PendingData(string data_in,
-                                     QuicAckListenerInterface* ack_listener_in)
-    : data(std::move(data_in)), offset(0), ack_listener(ack_listener_in) {}
+QuicStream::PendingData::PendingData(
+    string data_in,
+    scoped_refptr<QuicAckListenerInterface> ack_listener_in)
+    : data(std::move(data_in)),
+      offset(0),
+      ack_listener(std::move(ack_listener_in)) {}
 
 QuicStream::PendingData::~PendingData() {}
 
@@ -176,9 +179,10 @@
       error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
 }
 
-void QuicStream::WriteOrBufferData(StringPiece data,
-                                   bool fin,
-                                   QuicAckListenerInterface* ack_listener) {
+void QuicStream::WriteOrBufferData(
+    StringPiece data,
+    bool fin,
+    scoped_refptr<QuicAckListenerInterface> ack_listener) {
   if (data.empty() && !fin) {
     QUIC_BUG << "data.empty() && !fin";
     return;
@@ -215,7 +219,8 @@
   bool fin = false;
   while (!queued_data_.empty()) {
     PendingData* pending_data = &queued_data_.front();
-    QuicAckListenerInterface* ack_listener = pending_data->ack_listener.get();
+    scoped_refptr<QuicAckListenerInterface> ack_listener =
+        pending_data->ack_listener;
     if (queued_data_.size() == 1 && fin_buffered_) {
       fin = true;
     }
@@ -265,7 +270,7 @@
     const struct iovec* iov,
     int iov_count,
     bool fin,
-    QuicAckListenerInterface* ack_listener) {
+    scoped_refptr<QuicAckListenerInterface> ack_listener) {
   if (write_side_closed_) {
     DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
     return QuicConsumedData(0, false);
@@ -312,7 +317,7 @@
 
   QuicConsumedData consumed_data =
       WritevDataInner(QuicIOVector(iov, iov_count, write_length),
-                      stream_bytes_written_, fin, ack_listener);
+                      stream_bytes_written_, fin, std::move(ack_listener));
   stream_bytes_written_ += consumed_data.bytes_consumed;
 
   AddBytesSent(consumed_data.bytes_consumed);
@@ -346,9 +351,9 @@
     QuicIOVector iov,
     QuicStreamOffset offset,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
   return session()->WritevData(this, id(), iov, offset, fin,
-                               ack_notifier_delegate);
+                               std::move(ack_notifier_delegate));
 }
 
 void QuicStream::CloseReadSide() {
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h
index ebfa62d..2ee785e 100644
--- a/net/quic/core/quic_stream.h
+++ b/net/quic/core/quic_stream.h
@@ -186,17 +186,18 @@
   // write_side_closed() becomes true, otherwise fin_buffered_ becomes true.
   void WriteOrBufferData(base::StringPiece data,
                          bool fin,
-                         QuicAckListenerInterface* ack_listener);
+                         scoped_refptr<QuicAckListenerInterface> ack_listener);
 
   // Sends as many bytes in the first |count| buffers of |iov| to the connection
   // as the connection will consume.
   // If |ack_listener| is provided, then it will be notified once all
   // the ACKs for this write have been received.
   // Returns the number of bytes consumed by the connection.
-  QuicConsumedData WritevData(const struct iovec* iov,
-                              int iov_count,
-                              bool fin,
-                              QuicAckListenerInterface* ack_listener);
+  QuicConsumedData WritevData(
+      const struct iovec* iov,
+      int iov_count,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> ack_listener);
 
   // Allows override of the session level writev, for the force HOL
   // blocking experiment.
@@ -204,7 +205,7 @@
       QuicIOVector iov,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate);
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   // Close the write side of the socket.  Further writes will fail.
   // Can be called by the subclass or internally.
@@ -235,7 +236,8 @@
   bool read_side_closed() const { return read_side_closed_; }
 
   struct PendingData {
-    PendingData(std::string data_in, QuicAckListenerInterface* ack_listener_in);
+    PendingData(std::string data_in,
+                scoped_refptr<QuicAckListenerInterface> ack_listener_in);
     ~PendingData();
 
     // Pending data to be written.
diff --git a/net/quic/core/quic_stream_test.cc b/net/quic/core/quic_stream_test.cc
index 85df14c..35de6ce 100644
--- a/net/quic/core/quic_stream_test.cc
+++ b/net/quic/core/quic_stream_test.cc
@@ -143,7 +143,8 @@
       QuicIOVector /*iov*/,
       QuicStreamOffset /*offset*/,
       bool /*fin*/,
-      QuicAckListenerInterface* /*ack_notifier_delegate*/) {
+      const scoped_refptr<
+          QuicAckListenerInterface>& /*ack_notifier_delegate*/) {
     session_->CloseStream(id);
     return QuicConsumedData(1, false);
   }
@@ -387,8 +388,8 @@
 // TODO(ianswett): It's not clear this method is still needed now that
 // ProxyAckNotifierDelegate has been removed.
 void SaveAckListener(scoped_refptr<QuicAckListenerInterface>* listener_out,
-                     QuicAckListenerInterface* listener) {
-  *listener_out = (listener);
+                     scoped_refptr<QuicAckListenerInterface> listener) {
+  *listener_out = std::move(listener);
 }
 
 TEST_F(QuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) {
@@ -413,22 +414,22 @@
       .WillOnce(DoAll(
           WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &ack_listener))),
           Return(QuicConsumedData(kFirstWriteSize, false))));
-  stream_->WriteOrBufferData(kData, false, delegate.get());
+  stream_->WriteOrBufferData(kData, false, delegate);
   EXPECT_TRUE(HasWriteBlockedStreams());
 
   EXPECT_CALL(*session_,
-              WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+              WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
       .WillOnce(Return(QuicConsumedData(kSecondWriteSize, false)));
   stream_->OnCanWrite();
 
   // No ack expected for an empty write.
   EXPECT_CALL(*session_,
-              WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+              WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
       .WillOnce(Return(QuicConsumedData(0, false)));
   stream_->OnCanWrite();
 
   EXPECT_CALL(*session_,
-              WritevData(stream_, kTestStreamId, _, _, _, ack_listener.get()))
+              WritevData(stream_, kTestStreamId, _, _, _, ack_listener))
       .WillOnce(Return(QuicConsumedData(kLastWriteSize, false)));
   stream_->OnCanWrite();
 }
@@ -455,7 +456,7 @@
       .WillOnce(DoAll(
           WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
           Return(QuicConsumedData(kInitialWriteSize, false))));
-  stream_->WriteOrBufferData(kData, false, ack_listener.get());
+  stream_->WriteOrBufferData(kData, false, ack_listener);
   EXPECT_TRUE(HasWriteBlockedStreams());
 
   EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
@@ -477,7 +478,7 @@
       .WillOnce(DoAll(
           WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
           Return(QuicConsumedData(kDataLen, true))));
-  stream_->WriteOrBufferData(kData1, true, delegate.get());
+  stream_->WriteOrBufferData(kData1, true, delegate);
   EXPECT_FALSE(HasWriteBlockedStreams());
 }
 
@@ -491,7 +492,7 @@
 
   EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, false)));
-  stream_->WriteOrBufferData(kData1, true, delegate.get());
+  stream_->WriteOrBufferData(kData1, true, delegate);
   EXPECT_TRUE(HasWriteBlockedStreams());
 
   EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
@@ -514,7 +515,7 @@
       .WillOnce(DoAll(
           WithArgs<5>(Invoke(CreateFunctor(SaveAckListener, &proxy_delegate))),
           Return(QuicConsumedData(kDataLen, false))));
-  stream_->WriteOrBufferData(kData1, true, delegate.get());
+  stream_->WriteOrBufferData(kData1, true, delegate);
   EXPECT_TRUE(HasWriteBlockedStreams());
 
   EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _, _))
diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc
index f817571..fdafe221 100644
--- a/net/quic/quartc/quartc_stream_test.cc
+++ b/net/quic/quartc/quartc_stream_test.cc
@@ -38,7 +38,8 @@
       QuicIOVector iovector,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate) override {
+      scoped_refptr<QuicAckListenerInterface> /*ack_notifier_delegate*/)
+      override {
     if (!writable_) {
       return QuicConsumedData(0, false);
     }
diff --git a/net/quic/test_tools/quic_stream_peer.cc b/net/quic/test_tools/quic_stream_peer.cc
index 6b65a87..8deea1b 100644
--- a/net/quic/test_tools/quic_stream_peer.cc
+++ b/net/quic/test_tools/quic_stream_peer.cc
@@ -88,8 +88,8 @@
     QuicStream* stream,
     StringPiece data,
     bool fin,
-    QuicAckListenerInterface* ack_notifier_delegate) {
-  stream->WriteOrBufferData(data, fin, ack_notifier_delegate);
+    scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) {
+  stream->WriteOrBufferData(data, fin, std::move(ack_notifier_delegate));
 }
 
 // static
diff --git a/net/quic/test_tools/quic_stream_peer.h b/net/quic/test_tools/quic_stream_peer.h
index 3d3f440..e8aeda5e 100644
--- a/net/quic/test_tools/quic_stream_peer.h
+++ b/net/quic/test_tools/quic_stream_peer.h
@@ -42,7 +42,7 @@
       QuicStream* stream,
       base::StringPiece data,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate);
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate);
 
   static net::QuicStreamSequencer* sequencer(QuicStream* stream);
 
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index bf4055d..7cc110c 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -376,7 +376,7 @@
     const QuicIOVector& data,
     QuicStreamOffset /*offset*/,
     bool fin,
-    QuicAckListenerInterface* /*ack_notifier_delegate*/) {
+    const scoped_refptr<QuicAckListenerInterface>& /*ack_notifier_delegate*/) {
   return QuicConsumedData(data.total_length, fin);
 }
 
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 617a686b..0d1c90ac 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -518,7 +518,7 @@
                                 QuicIOVector data,
                                 QuicStreamOffset offset,
                                 bool fin,
-                                QuicAckListenerInterface*));
+                                scoped_refptr<QuicAckListenerInterface>));
 
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
@@ -543,7 +543,7 @@
       const QuicIOVector& data,
       QuicStreamOffset offset,
       bool fin,
-      QuicAckListenerInterface* ack_notifier_delegate);
+      const scoped_refptr<QuicAckListenerInterface>& ack_notifier_delegate);
 
  private:
   std::unique_ptr<QuicCryptoStream> crypto_stream_;
@@ -570,13 +570,14 @@
                QuicSpdyStream*(SpdyPriority priority));
   MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
   MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
-  MOCK_METHOD6(WritevData,
-               QuicConsumedData(QuicStream* stream,
-                                QuicStreamId id,
-                                QuicIOVector data,
-                                QuicStreamOffset offset,
-                                bool fin,
-                                QuicAckListenerInterface*));
+  MOCK_METHOD6(
+      WritevData,
+      QuicConsumedData(QuicStream* stream,
+                       QuicStreamId id,
+                       QuicIOVector data,
+                       QuicStreamOffset offset,
+                       bool fin,
+                       scoped_refptr<QuicAckListenerInterface> ack_listener));
 
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
@@ -613,7 +614,7 @@
       SpdyHeaderBlock headers,
       bool fin,
       SpdyPriority priority,
-      QuicAckListenerInterface* ack_notifier_delegate) override {
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override {
     write_headers_ = std::move(headers);
     return WriteHeadersMock(id, write_headers_, fin, priority,
                             ack_notifier_delegate);
@@ -623,7 +624,8 @@
                       const SpdyHeaderBlock& headers,
                       bool fin,
                       SpdyPriority priority,
-                      QuicAckListenerInterface* ack_notifier_delegate));
+                      const scoped_refptr<QuicAckListenerInterface>&
+                          ack_notifier_delegate));
   MOCK_METHOD1(OnHeadersHeadOfLineBlocking, void(QuicTime::Delta delta));
   MOCK_METHOD4(
       OnStreamFrameData,
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 9d3e6b2..66abfea 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -1982,7 +1982,7 @@
       "a request body bigger than one packet" + string(kMaxPacketSize, '.');
 
   // Send the request, and register the delegate for ACKs.
-  client_->SendData(request_string, true, delegate.get());
+  client_->SendData(request_string, true, delegate);
   client_->WaitForResponse();
   EXPECT_EQ(kFooResponseBody, client_->response_body());
   EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc
index 1bb3add..d857bee9 100644
--- a/net/tools/quic/quic_simple_server_session_test.cc
+++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -79,19 +79,21 @@
                       QuicStreamId promised_stream_id,
                       const SpdyHeaderBlock& headers));
 
-  size_t WriteHeaders(QuicStreamId stream_id,
-                      SpdyHeaderBlock headers,
-                      bool fin,
-                      SpdyPriority priority,
-                      QuicAckListenerInterface* ack_listener) override {
+  size_t WriteHeaders(
+      QuicStreamId stream_id,
+      SpdyHeaderBlock headers,
+      bool fin,
+      SpdyPriority priority,
+      scoped_refptr<QuicAckListenerInterface> ack_listener) override {
     return WriteHeadersMock(stream_id, headers, fin, priority, ack_listener);
   }
-  MOCK_METHOD5(WriteHeadersMock,
-               size_t(QuicStreamId stream_id,
-                      const SpdyHeaderBlock& headers,
-                      bool fin,
-                      SpdyPriority priority,
-                      QuicAckListenerInterface* ack_listener));
+  MOCK_METHOD5(
+      WriteHeadersMock,
+      size_t(QuicStreamId stream_id,
+             const SpdyHeaderBlock& headers,
+             bool fin,
+             SpdyPriority priority,
+             const scoped_refptr<QuicAckListenerInterface>& ack_listener));
 };
 
 class MockQuicCryptoServerStream : public QuicCryptoServerStream {
@@ -131,12 +133,13 @@
                            perspective,
                            supported_versions) {}
 
-  MOCK_METHOD5(SendStreamData,
-               QuicConsumedData(QuicStreamId id,
-                                QuicIOVector iov,
-                                QuicStreamOffset offset,
-                                bool fin,
-                                QuicAckListenerInterface* listern));
+  MOCK_METHOD5(
+      SendStreamData,
+      QuicConsumedData(QuicStreamId id,
+                       QuicIOVector iov,
+                       QuicStreamOffset offset,
+                       bool fin,
+                       scoped_refptr<QuicAckListenerInterface> listern));
 };
 
 class QuicSimpleServerSessionPeer {
@@ -484,14 +487,12 @@
                   WritePushPromiseMock(kClientDataStreamId1, stream_id, _));
       if (i <= kMaxStreamsForTest) {
         // |kMaxStreamsForTest| promised responses should be sent.
-        EXPECT_CALL(
-            *headers_stream_,
-            WriteHeadersMock(stream_id, _, false, kDefaultPriority, nullptr));
+        EXPECT_CALL(*headers_stream_,
+                    WriteHeadersMock(stream_id, _, false, kDefaultPriority, _));
         // Since flow control window is smaller than response body, not the
         // whole body will be sent.
         if (!session_->force_hol_blocking()) {
-          EXPECT_CALL(*connection_,
-                      SendStreamData(stream_id, _, 0, false, nullptr))
+          EXPECT_CALL(*connection_, SendStreamData(stream_id, _, 0, false, _))
               .WillOnce(Return(
                   QuicConsumedData(kStreamFlowControlWindowSize, false)));
           EXPECT_CALL(*connection_, SendBlocked(stream_id));
@@ -500,7 +501,7 @@
           // HTTP/2 DATA frames within the headers stream.  HTTP/2
           // DATA frames are limited to a max size of 16KB, so the
           // 64KB body will be fragemented into four DATA frames.
-          EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, nullptr))
+          EXPECT_CALL(*connection_, SendStreamData(_, _, _, false, _))
               .Times(body_size / 16384)
               .WillOnce(Return(QuicConsumedData(9 + 16394, false)))
               .WillOnce(Return(QuicConsumedData(9 + 16394, false)))
@@ -546,11 +547,10 @@
 
   // After an open stream is marked draining, a new stream is expected to be
   // created and a response sent on the stream.
-  EXPECT_CALL(*headers_stream_,
-              WriteHeadersMock(next_out_going_stream_id, _, false,
-                               kDefaultPriority, nullptr));
+  EXPECT_CALL(*headers_stream_, WriteHeadersMock(next_out_going_stream_id, _,
+                                                 false, kDefaultPriority, _));
   EXPECT_CALL(*connection_,
-              SendStreamData(next_out_going_stream_id, _, 0, false, nullptr))
+              SendStreamData(next_out_going_stream_id, _, 0, false, _))
       .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
   EXPECT_CALL(*connection_, SendBlocked(next_out_going_stream_id));
   session_->StreamDraining(2);
@@ -585,13 +585,12 @@
   QuicStreamId stream_not_reset = (kMaxStreamsForTest + 1) * 2;
   InSequence s;
   EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_not_reset, _, false,
-                                                 kDefaultPriority, nullptr));
-  EXPECT_CALL(*connection_,
-              SendStreamData(stream_not_reset, _, 0, false, nullptr))
+                                                 kDefaultPriority, _));
+  EXPECT_CALL(*connection_, SendStreamData(stream_not_reset, _, 0, false, _))
       .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
   EXPECT_CALL(*connection_, SendBlocked(stream_not_reset));
-  EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_got_reset, _, false,
-                                                 kDefaultPriority, nullptr))
+  EXPECT_CALL(*headers_stream_,
+              WriteHeadersMock(stream_got_reset, _, false, kDefaultPriority, _))
       .Times(0);
 
   session_->StreamDraining(2);
@@ -614,10 +613,9 @@
   QuicStreamId stream_got_reset = 2;
   EXPECT_CALL(*connection_,
               SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, _));
-  EXPECT_CALL(*headers_stream_, WriteHeadersMock(stream_to_open, _, false,
-                                                 kDefaultPriority, nullptr));
-  EXPECT_CALL(*connection_,
-              SendStreamData(stream_to_open, _, 0, false, nullptr))
+  EXPECT_CALL(*headers_stream_,
+              WriteHeadersMock(stream_to_open, _, false, kDefaultPriority, _));
+  EXPECT_CALL(*connection_, SendStreamData(stream_to_open, _, 0, false, _))
       .WillOnce(Return(QuicConsumedData(kStreamFlowControlWindowSize, false)));
 
   EXPECT_CALL(*connection_, SendBlocked(stream_to_open));
diff --git a/net/tools/quic/quic_simple_server_stream_test.cc b/net/tools/quic/quic_simple_server_stream_test.cc
index d0764a2..1e25037 100644
--- a/net/tools/quic/quic_simple_server_stream_test.cc
+++ b/net/tools/quic/quic_simple_server_stream_test.cc
@@ -123,7 +123,7 @@
                                 QuicIOVector data,
                                 QuicStreamOffset offset,
                                 bool fin,
-                                QuicAckListenerInterface*));
+                                scoped_refptr<QuicAckListenerInterface>));
   MOCK_METHOD4(OnStreamHeaderList,
                void(QuicStreamId stream_id,
                     bool fin,
@@ -138,7 +138,7 @@
       SpdyHeaderBlock headers,
       bool fin,
       SpdyPriority priority,
-      QuicAckListenerInterface* ack_notifier_delegate) override {
+      scoped_refptr<QuicAckListenerInterface> ack_notifier_delegate) override {
     return WriteHeadersMock(id, headers, fin, priority, ack_notifier_delegate);
   }
   MOCK_METHOD5(WriteHeadersMock,
@@ -146,7 +146,8 @@
                       const SpdyHeaderBlock& headers,
                       bool fin,
                       SpdyPriority priority,
-                      QuicAckListenerInterface* ack_notifier_delegate));
+                      const scoped_refptr<QuicAckListenerInterface>&
+                          ack_notifier_delegate));
   MOCK_METHOD3(SendRstStream,
                void(QuicStreamId stream_id,
                     QuicRstStreamErrorCode error,
@@ -330,7 +331,7 @@
   stream_->set_fin_received(true);
 
   InSequence s;
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(
@@ -361,7 +362,7 @@
   stream_->set_fin_received(true);
 
   InSequence s;
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(
@@ -418,7 +419,7 @@
   stream_->set_fin_received(true);
 
   InSequence s;
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(body.length(), true)));
@@ -456,7 +457,7 @@
   EXPECT_CALL(session_,
               PromisePushResourcesMock(host + request_path, _,
                                        ::net::test::kClientDataStreamId1, _));
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(body.length(), true)));
@@ -503,7 +504,7 @@
   // and send it back.
   EXPECT_CALL(session_,
               WriteHeadersMock(kServerInitiatedStreamId, _, false,
-                               server_initiated_stream->priority(), nullptr));
+                               server_initiated_stream->priority(), _));
   EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(kBody.size(), true)));
@@ -590,7 +591,7 @@
 
 TEST_P(QuicSimpleServerStreamTest, SendQuicRstStreamNoErrorWithEarlyResponse) {
   InSequence s;
-  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, nullptr));
+  EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
       .Times(1)
       .WillOnce(Return(QuicConsumedData(3, true)));
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 5e06f89e..035df6bc 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -292,7 +292,7 @@
     const SpdyHeaderBlock* headers,
     StringPiece body,
     bool fin,
-    QuicAckListenerInterface* delegate) {
+    scoped_refptr<QuicAckListenerInterface> delegate) {
   if (headers) {
     QuicClientPushPromiseIndex::TryHandle* handle;
     QuicAsyncStatus rv =
@@ -304,7 +304,7 @@
       std::unique_ptr<SpdyHeaderBlock> new_headers(
           new SpdyHeaderBlock(headers->Clone()));
       push_promise_data_to_resend_.reset(new TestClientDataToResend(
-          std::move(new_headers), body, fin, this, delegate));
+          std::move(new_headers), body, fin, this, std::move(delegate)));
       return 1;
     }
   }
@@ -374,11 +374,12 @@
   return SendData(data, last_data, nullptr);
 }
 
-ssize_t QuicTestClient::SendData(const string& data,
-                                 bool last_data,
-                                 QuicAckListenerInterface* delegate) {
+ssize_t QuicTestClient::SendData(
+    const string& data,
+    bool last_data,
+    scoped_refptr<QuicAckListenerInterface> delegate) {
   return GetOrCreateStreamAndSendRequest(nullptr, StringPiece(data), last_data,
-                                         delegate);
+                                         std::move(delegate));
 }
 
 bool QuicTestClient::response_complete() const {
@@ -671,6 +672,18 @@
   }
 }
 
+QuicTestClient::TestClientDataToResend::TestClientDataToResend(
+    std::unique_ptr<SpdyHeaderBlock> headers,
+    base::StringPiece body,
+    bool fin,
+    QuicTestClient* test_client,
+    scoped_refptr<QuicAckListenerInterface> delegate)
+    : QuicClient::QuicDataToResend(std::move(headers), body, fin),
+      test_client_(test_client),
+      delegate_(std::move(delegate)) {}
+
+QuicTestClient::TestClientDataToResend::~TestClientDataToResend() {}
+
 void QuicTestClient::TestClientDataToResend::Resend() {
   test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_,
                                                 delegate_);
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index d2b9c8d0..49991efd 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -115,7 +115,7 @@
   // As above, but |delegate| will be notified when |data| is ACKed.
   ssize_t SendData(const std::string& data,
                    bool last_data,
-                   QuicAckListenerInterface* delegate);
+                   scoped_refptr<QuicAckListenerInterface> delegate);
 
   // Clears any outstanding state and sends a simple GET of 'uri' to the
   // server.  Returns 0 if the request failed and no bytes were written.
@@ -215,10 +215,11 @@
   // Calls GetOrCreateStream(), sends the request on the stream, and
   // stores the request in case it needs to be resent.  If |headers| is
   // null, only the body will be sent on the stream.
-  ssize_t GetOrCreateStreamAndSendRequest(const SpdyHeaderBlock* headers,
-                                          base::StringPiece body,
-                                          bool fin,
-                                          QuicAckListenerInterface* delegate);
+  ssize_t GetOrCreateStreamAndSendRequest(
+      const SpdyHeaderBlock* headers,
+      base::StringPiece body,
+      bool fin,
+      scoped_refptr<QuicAckListenerInterface> delegate);
 
   QuicRstStreamErrorCode stream_error() { return stream_error_; }
   QuicErrorCode connection_error();
@@ -279,18 +280,15 @@
                            base::StringPiece body,
                            bool fin,
                            QuicTestClient* test_client,
-                           QuicAckListenerInterface* delegate)
-        : QuicClient::QuicDataToResend(std::move(headers), body, fin),
-          test_client_(test_client),
-          delegate_(delegate) {}
+                           scoped_refptr<QuicAckListenerInterface> delegate);
 
-    ~TestClientDataToResend() override {}
+    ~TestClientDataToResend() override;
 
     void Resend() override;
 
    protected:
     QuicTestClient* test_client_;
-    QuicAckListenerInterface* delegate_;
+    scoped_refptr<QuicAckListenerInterface> delegate_;
   };
 
   // Given |uri|, populates the fields in |headers| for a simple GET
diff --git a/remoting/host/service_urls.cc b/remoting/host/service_urls.cc
index d3f28761..b4aa3cd6 100644
--- a/remoting/host/service_urls.cc
+++ b/remoting/host/service_urls.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "google_apis/google_api_keys.h"
+#include "remoting/signaling/remoting_bot.h"
 
 // Configurable service data.
 const char kDirectoryBaseUrl[] = "https://www.googleapis.com/chromoting/v1";
@@ -14,7 +15,6 @@
 const char kXmppServerAddress[] = "talk.google.com:443";
 const char kXmppServerAddressForMe2MeHost[] = "talk.google.com:5222";
 const bool kXmppServerUseTls = true;
-const char kDirectoryBotJid[] = "remoting@bot.talk.google.com";
 const char kGcdJid[] = "clouddevices.gserviceaccount.com";
 const char kNetworkTraversalApiUrlBase[] =
     "https://networktraversal.googleapis.com/v1alpha/iceconfig?key=";
@@ -41,7 +41,7 @@
       xmpp_server_address_(kXmppServerAddress),
       xmpp_server_address_for_me2me_host_(kXmppServerAddressForMe2MeHost),
       xmpp_server_use_tls_(kXmppServerUseTls),
-      directory_bot_jid_(kDirectoryBotJid),
+      directory_bot_jid_(kRemotingBotJid),
       gcd_jid_(kGcdJid),
       ice_config_url_(kNetworkTraversalApiUrlBase +
                       google_apis::GetRemotingAPIKey()) {
diff --git a/remoting/protocol/jingle_messages.cc b/remoting/protocol/jingle_messages.cc
index c2402d6..5463dbb2 100644
--- a/remoting/protocol/jingle_messages.cc
+++ b/remoting/protocol/jingle_messages.cc
@@ -9,6 +9,7 @@
 #include "remoting/base/constants.h"
 #include "remoting/protocol/content_description.h"
 #include "remoting/protocol/name_value_map.h"
+#include "remoting/signaling/remoting_bot.h"
 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h"
 
 using buzz::QName;
@@ -201,14 +202,19 @@
     return empty_instance;
   }
 
-  bool isLcs = (channel == SignalingAddress::Channel::LCS);
+  bool is_lcs = (channel == SignalingAddress::Channel::LCS);
 
-  if (isLcs == endpoint_id.empty()) {
-    *error = (isLcs ? "Missing |endpoint-id| for LCS channel"
+  if (is_lcs == endpoint_id.empty()) {
+    *error = (is_lcs ? "Missing |endpoint-id| for LCS channel"
                     : "|endpoint_id| should be empty for XMPP channel");
     return empty_instance;
   }
 
+  if (from && is_lcs && !IsValidBotJid(jid)) {
+    *error = "Reject LCS message from untrusted sender: " + jid;
+    return empty_instance;
+  }
+
   return SignalingAddress(jid, endpoint_id, channel);
 }
 
diff --git a/remoting/protocol/jingle_messages_unittest.cc b/remoting/protocol/jingle_messages_unittest.cc
index 3f3349ba5..e10e935d 100644
--- a/remoting/protocol/jingle_messages_unittest.cc
+++ b/remoting/protocol/jingle_messages_unittest.cc
@@ -406,7 +406,7 @@
 
 TEST(JingleMessageTest, ParseAddress) {
   const char* kTestSessionInfoMessage =
-      "<cli:iq from='remoting@talk.google.com' "
+      "<cli:iq from='remoting@bot.talk.google.com' "
               "to='user@gmail.com/chromiumsy5C6A652D' type='set' "
               "xmlns:cli='jabber:client'>"
         "<jingle action='session-info' "
@@ -419,7 +419,7 @@
 
   JingleMessage message;
   ParseFormatAndCompare(kTestSessionInfoMessage, &message);
-  EXPECT_EQ(message.from.jid, "remoting@talk.google.com");
+  EXPECT_EQ(message.from.jid, "remoting@bot.talk.google.com");
   EXPECT_EQ(message.from.channel, SignalingAddress::Channel::LCS);
   EXPECT_EQ(message.from.endpoint_id, "user@gmail.com/xBrnereror=");
   EXPECT_EQ(message.from.id(), "user@gmail.com/xBrnereror=");
@@ -432,6 +432,29 @@
   EXPECT_EQ(message.action, JingleMessage::SESSION_INFO);
 }
 
+
+TEST(JingleMessageTest, IgnoreInvalidAddress) {
+  const char* kInvalidFromField =
+      "<cli:iq from='evil@gmail.com' "
+              "to='victim@gmail.com/chromiumsy5C6A652D' type='set' "
+              "xmlns:cli='jabber:client'>"
+        "<jingle action='session-info' "
+                "sid='2227053353' xmlns='urn:xmpp:jingle:1' "
+                "from-channel='lcs' "
+                "from-endpoint-id='victim@gmail.com/evilAddress'>"
+          "<test-info>TestMessage</test-info>"
+        "</jingle>"
+      "</cli:iq>";
+
+  std::unique_ptr<XmlElement> xml(XmlElement::ForStr(kInvalidFromField));
+  ASSERT_TRUE(xml.get());
+  EXPECT_TRUE(JingleMessage::IsJingleMessage(xml.get()));
+  JingleMessage message;
+  std::string error;
+  EXPECT_FALSE(message.ParseXml(xml.get(), &error));
+  EXPECT_TRUE(message.from.empty());
+}
+
 TEST(JingleMessageReplyTest, ToXml) {
   const char* kTestIncomingMessage1 =
       "<cli:iq from='user@gmail.com/chromoting016DBB07' id='4' "
@@ -440,7 +463,7 @@
       "sid='2227053353' xmlns='urn:xmpp:jingle:1'><reason><success/>"
       "</reason></jingle></cli:iq>";
   const char* kTestIncomingMessage2 =
-      "<cli:iq from='remoting@talk.google.com' id='4' "
+      "<cli:iq from='remoting@bot.talk.google.com' id='4' "
       "to='user@gmail.com/chromiumsy5C6A652D' type='set' "
       "xmlns:cli='jabber:client'><jingle action='session-terminate' "
       "from-channel='lcs' from-endpoint-id='from@gmail.com/AbCdEf1234=' "
@@ -497,7 +520,7 @@
        kTestIncomingMessage1},
       {JingleMessageReply::INVALID_SID, "ErrorText",
        "<iq xmlns='jabber:client' "
-       "to='remoting@talk.google.com' id='4' "
+       "to='remoting@bot.talk.google.com' id='4' "
        "type='error'><jingle "
        "action='session-terminate' sid='2227053353' xmlns='urn:xmpp:jingle:1' "
        "from-channel='lcs' from-endpoint-id='from@gmail.com/AbCdEf1234='>"
@@ -505,7 +528,7 @@
        "<item-not-found/><text xml:lang='en'>ErrorText</text></error></iq>",
        kTestIncomingMessage2},
       {JingleMessageReply::NONE, "",
-       "<iq xmlns='jabber:client' to='remoting@talk.google.com' id='4' "
+       "<iq xmlns='jabber:client' to='remoting@bot.talk.google.com' id='4' "
        "type='result'><jingle xmlns='urn:xmpp:jingle:1' to-channel='lcs' "
        "to-endpoint-id='from@gmail.com/AbCdEf1234='/></iq>",
        kTestIncomingMessage2},
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn
index 7f0e2c5..7490c7ec 100644
--- a/remoting/signaling/BUILD.gn
+++ b/remoting/signaling/BUILD.gn
@@ -14,6 +14,8 @@
     "log_to_server.h",
     "push_notification_subscriber.cc",
     "push_notification_subscriber.h",
+    "remoting_bot.cc",
+    "remoting_bot.h",
     "server_log_entry.cc",
     "server_log_entry.h",
     "signal_strategy.h",
diff --git a/remoting/signaling/remoting_bot.cc b/remoting/signaling/remoting_bot.cc
new file mode 100644
index 0000000..4a8b25d
--- /dev/null
+++ b/remoting/signaling/remoting_bot.cc
@@ -0,0 +1,21 @@
+// Copyright 2016 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 "remoting/signaling/remoting_bot.h"
+
+namespace remoting {
+
+bool IsValidBotJid(const std::string& input) {
+  if (input == kRemotingBotJid) {
+    return true;
+  }
+#if !defined(NDEBUG)
+  if (input == kRemotingTestBotJid) {
+    return true;
+  }
+#endif  // !defined(NDEBUG)
+  return false;
+}
+
+}  // namespace remoting
diff --git a/remoting/signaling/remoting_bot.h b/remoting/signaling/remoting_bot.h
new file mode 100644
index 0000000..8f06a6ae
--- /dev/null
+++ b/remoting/signaling/remoting_bot.h
@@ -0,0 +1,25 @@
+// Copyright 2016 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 REMOTING_SIGNALING_REMOTING_BOT_H_
+#define REMOTING_SIGNALING_REMOTING_BOT_H_
+
+#include <string>
+
+namespace remoting {
+
+// The JID of the remoting bot.
+const char kRemotingBotJid[] = "remoting@bot.talk.google.com";
+
+#if !defined(NDEBUG)
+// The JID of the remoting bot test instance.
+const char kRemotingTestBotJid[] = "remoting-test@bot.talk.google.com";
+#endif  // !defined(NDEBUG)
+
+// Returns true if |input| is a valid bot JID.
+bool IsValidBotJid(const std::string& input);
+
+}  // namespace remoting
+
+#endif  // REMOTING_BASE_REMOTING_BOT_H_
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 6f4bdb6..0c426cc 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -246,6 +246,10 @@
 #   define SK_USE_LEGACY_DISTANCE_FIELDS
 #endif
 
+#ifndef    SK_SUPPORT_LEGACY_CLIPOP_EXOTIC_NAMES
+#   define SK_SUPPORT_LEGACY_CLIPOP_EXOTIC_NAMES
+#endif
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 71e0517e..569c9459 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -1390,5 +1390,417 @@
         "test": "vr_shell_unittests"
       }
     ]
+  },
+  "Unswarmed N5 Tests Dummy Builder": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "android_webview_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "blimp_unittests"
+      },
+      {
+        "override_compile_targets": [
+          "breakpad_unittests_deps"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "breakpad_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "capture_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "components_unittests"
+      },
+      {
+        "args": [
+          "--shard-timeout",
+          "600"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "device_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gl_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gl_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gpu_ipc_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "args": [
+          "--shard-timeout",
+          "600"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ipc_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "net_unittests"
+      },
+      {
+        "override_compile_targets": [
+          "sandbox_linux_unittests_deps"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "storage_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_android_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "unit_tests"
+      }
+    ],
+    "instrumentation_tests": [
+      {
+        "test": "android_webview_test_apk"
+      },
+      {
+        "override_compile_targets": [
+          "blimp_test_apk"
+        ],
+        "test": "blimp_test_apk"
+      },
+      {
+        "test": "chrome_public_test_apk"
+      },
+      {
+        "test": "chrome_sync_shell_test_apk"
+      },
+      {
+        "test": "content_shell_test_apk"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      }
+    ]
+  },
+  "Unswarmed N5X Tests Dummy Builder": {
+    "gtest_tests": [
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "android_webview_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "blimp_unittests"
+      },
+      {
+        "override_compile_targets": [
+          "breakpad_unittests_deps"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "breakpad_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "capture_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "cc_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "components_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "components_unittests"
+      },
+      {
+        "args": [
+          "--shard-timeout",
+          "600"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "content_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "device_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "events_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gfx_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gl_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gl_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gpu_ipc_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "gpu_unittests"
+      },
+      {
+        "args": [
+          "--shard-timeout",
+          "600"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ipc_tests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "media_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "net_unittests"
+      },
+      {
+        "override_compile_targets": [
+          "sandbox_linux_unittests_deps"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "sandbox_linux_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "sql_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "storage_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_android_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_base_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "ui_touch_selection_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
+        "test": "unit_tests"
+      }
+    ],
+    "instrumentation_tests": [
+      {
+        "test": "android_webview_test_apk"
+      },
+      {
+        "override_compile_targets": [
+          "blimp_test_apk"
+        ],
+        "test": "blimp_test_apk"
+      },
+      {
+        "test": "chrome_public_test_apk"
+      },
+      {
+        "test": "chrome_sync_shell_test_apk"
+      },
+      {
+        "test": "content_shell_test_apk"
+      }
+    ],
+    "scripts": [
+      {
+        "name": "telemetry_perf_unittests",
+        "script": "telemetry_perf_unittests.py"
+      }
+    ]
   }
 }
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 8057a263..56dc913 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -173,6 +173,9 @@
         "test": "gfx_unittests"
       },
       {
+        "args": [
+          "--ozone-platform=x11"
+        ],
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -182,12 +185,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "gl_unittests_ozonex"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "google_apis_unittests"
       },
       {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 1904a63..266f4073 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -20,8 +20,7 @@
 #  "windowed_test_launcher"
 #  : the test is a gtest-based test that uses the "brave-new-test-launcher"
 #    from //base/test:test_support and needs to run under Xvfb if run on
-#    an X11-based platform (use_x11=true or use_ozone=true &&
-#    --ozone_platform=x11).
+#    some platforms (eg. Linux Desktop, X11 CrOS and Ozone CrOS).
 #  "console_test_launcher"
 #  : the test is a gtest-based test that uses the "brave-new-test-launcher"
 #    from //base/test:test_support but does not need Xvfb.
@@ -450,15 +449,8 @@
   },
   "gl_unittests": {
     "label": "//ui/gl:gl_unittests",
-    "type": "raw",
-    "args": [],
-  },
-  "gl_unittests_ozonex": {
-    "label": "//ui/gl:gl_unittests_ozonex",
-    "label_type": "group",
     "type": "windowed_test_launcher",
-    "executable": "gl_unittests",
-    "args": ["--ozone-platform=x11"],
+    "args": [],
   },
   "gn_all": {
     "label": "//:gn_all",
@@ -517,6 +509,10 @@
     "label": "//chrome/test:interactive_ui_tests",
     "type": "windowed_test_launcher",
   },
+  "ios:all": {
+    "label": "//ios:all",
+    "type": "additional_compile_target",
+  },
   "ios_chrome_unittests": {
     "label": "//ios/chrome/test:ios_chrome_unittests",
     "type": "raw",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index c3e2a95..4a35600 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -157,6 +157,7 @@
 
   # this is used at least on iOS
   'gn_all',
+  'ios:all',
   'cronet_test',
 
   # These are listed in Builders that are skipped for other reasons.
diff --git a/testing/coverage_util_ios.cc b/testing/coverage_util_ios.cc
index 15ac1b4..d888a20 100644
--- a/testing/coverage_util_ios.cc
+++ b/testing/coverage_util_ios.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-extern "C" void __gcov_flush();
+extern "C" void __gcov_flush(void);
 
 namespace coverage_util {
 
 void FlushCoverageDataIfNecessary() {
-#if defined(ENABLE_TEST_CODE_COVERAGE)
+#if !defined(NDEBUG) && defined(ENABLE_TEST_CODE_COVERAGE)
   __gcov_flush();
 #endif
 }
diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md
index a22e7c5d..1269bfbd 100644
--- a/testing/libfuzzer/getting_started.md
+++ b/testing/libfuzzer/getting_started.md
@@ -29,8 +29,8 @@
 | GN Argument | Description |
 |--------------|----|
 | `is_asan=true` | enables [Address Sanitizer] to catch problems like buffer overruns. |
-| `is_msan=true` | enables [Memory Sanitizer] to catch problems like uninitialed reads. |
-| `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[1](#Notes)\]</sup> undefined behavior like integer overflow. |
+| `is_msan=true` | enables [Memory Sanitizer] to catch problems like uninitialed reads<sup>\[[1](#note1)\]</sup>. |
+| `is_ubsan_security=true` | enables [Undefined Behavior Sanitizer] to catch<sup>\[[2](#note2)\]</sup> undefined behavior like integer overflow. |
 | | it is possible to run libfuzzer without any sanitizers; *probably not what you want*.|
 
 
@@ -137,19 +137,25 @@
 
 
 ## Notes
-[1] By default UBSan doesn't crash once undefined behavior has been detected.
-To make it crash the following additional option should be provided:
 
+*[1]* {#note1}You need to [download prebuilt instrumented libraries](https://www.chromium.org/developers/testing/memorysanitizer#TOC-How-to-build-and-run)
+to use msan ([crbug/653712](https://bugs.chromium.org/p/chromium/issues/detail?id=653712)):
+```bash
+GYP_DEFINES='use_goma=1 msan=1 use_prebuilt_instrumented_libraries=1' gclient runhooks
+```
+
+*[2]* {#note2}By default UBSan doesn't crash once undefined behavior has been detected.
+To make it crash the following additional option should be provided:
 ```bash
 UBSAN_OPTIONS=halt_on_error=1 ./fuzzer <corpus_directory_or_single_testcase_path>
 ```
-
 Other useful options (used by ClusterFuzz) are:
 ```bash
 UBSAN_OPTIONS=symbolize=1:halt_on_error=1:print_stacktrace=1 ./fuzzer <corpus_directory_or_single_testcase_path>
 ```
 
 
+
 [Address Sanitizer]: http://clang.llvm.org/docs/AddressSanitizer.html
 [ClusterFuzz status]: clusterfuzz.md#Status-Links
 [Efficient Fuzzer Guide]: efficient_fuzzer.md
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 50ffd6e..fb1ef61 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -472,6 +472,21 @@
             ]
         }
     ],
+    "DisableFirstRunAutoImport": [
+        {
+            "platforms": [
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "DisableFirstRunAutoImport",
+                    "enable_features": [
+                        "DisableFirstRunAutoImport"
+                    ]
+                }
+            ]
+        }
+    ],
     "DisallowFetchForDocWrittenScriptsInMainFrame": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index d8092bb..9af7aaa 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1320,7 +1320,7 @@
 # Temporary until we start generating Trusty baselines.
 crbug.com/498021 [ Linux ] fast/text/unicode-fallback-font.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/forms/month/month-appearance-l10n.html [ Failure ]
-crbug.com/498021 [ Linux ] fast/text/ellipsis-stroked.html [ Failure ]
+crbug.com/498021 [ Linux Win ] fast/text/ellipsis-stroked.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/emphasis-complex.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/international/danda-space.html [ Failure ]
 crbug.com/498021 [ Linux ] fast/text/international/hindi-whitespace.html [ Failure ]
@@ -2225,7 +2225,7 @@
 crbug.com/610835 virtual/mojo-loading/http/tests/security/XFrameOptions/x-frame-options-deny-multiple-clients.html [ Failure Pass ]
 
 # Added 2016-12-12
-crbug.com/673539 [ Linux ] css3/filters/effect-contrast-hw.html [ Pass Failure ]
+crbug.com/673539 [ Linux Win ] css3/filters/effect-contrast-hw.html [ Pass Failure ]
 
 # Added 2016-12-14
 crbug.com/674048 [ Linux ] virtual/mojo-loading/http/tests/navigation/image-load-in-unload-handler.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-image-repeat-round-expected.png b/third_party/WebKit/LayoutTests/fast/borders/border-image-repeat-round-expected.png
index 4b83eff..2418af8 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-image-repeat-round-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-image-repeat-round-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-image-rotate-transform-expected.png b/third_party/WebKit/LayoutTests/fast/borders/border-image-rotate-transform-expected.png
index 3f31fe8..f5af5ab 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-image-rotate-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-image-rotate-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-image-side-reduction-expected.png b/third_party/WebKit/LayoutTests/fast/borders/border-image-side-reduction-expected.png
index 529cc9ac..d3ef3753 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed-expected.html b/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed-expected.html
new file mode 100644
index 0000000..1abd3774
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<style>
+#div-horizontal {
+  width: 200px;
+  height: 100px;
+  background-color: green;
+}
+
+#div-vertical {
+  width: 100px;
+  height: 200px;
+  background-color: green;
+}
+</style>
+
+<script src="resources/srcset-helper.js"></script>
+
+<div id="div-horizontal"></div>
+<br>
+<div id="div-vertical"></div>
+
diff --git a/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed.html b/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed.html
new file mode 100644
index 0000000..d9156dd1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/hidpi/background-tile-bleed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<style>
+#div-horizontal {
+  width: 200px;
+  height: 100px;
+  /* red band at the bottom */
+  background-image: url("data:image/svg+xml,\
+  <svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'>\
+    <rect width='100%' height='100%' fill='red'/>\
+    <rect width='100%' height='100' fill='green'/>\
+  </svg>");
+}
+
+#div-vertical {
+  width: 100px;
+  height: 200px;
+  /* red band on the right */
+  background-image: url("data:image/svg+xml,\
+  <svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'>\
+    <rect width='100%' height='100%' fill='red'/>\
+    <rect width='100' height='100%' fill='green'/>\
+  </svg>");
+}
+</style>
+
+<script src="resources/srcset-helper.js"></script>
+
+<!-- There should be no bleeding due to repeat edge wrapping in the dimension
+     fully covered by the tile -->
+<div id="div-horizontal"></div>
+<br>
+<div id="div-vertical"></div>
+
diff --git a/third_party/WebKit/LayoutTests/fast/table/colspan-with-all-percent-cells.html b/third_party/WebKit/LayoutTests/fast/table/colspan-with-all-percent-cells.html
index a035fb3..679118e4 100644
--- a/third_party/WebKit/LayoutTests/fast/table/colspan-with-all-percent-cells.html
+++ b/third_party/WebKit/LayoutTests/fast/table/colspan-with-all-percent-cells.html
@@ -20,7 +20,7 @@
 </style>
 </head>
 <body>
-<!-- bug 34758: TD width in precentage doesn't work. -->
+<!-- bug 34758: TD width in percentage doesn't work. -->
 <!-- The 2 green rectangles should have the same width. -->
 <table id="table" width="50%" height="100%">
     <tr>
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt b/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
index 9a0f08d2..bf4870a 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
@@ -44,7 +44,7 @@
 PASS
 row6 col0
 PASS
-Test 3 - 2 same row spanning cells with diffrent heights.
+Test 3 - 2 same row spanning cells with different heights.
 
 row0 col0 rowspan=6 height=300px	row0 col1 rowspan=6 height=500px
 PASS
@@ -78,7 +78,7 @@
 PASS
 row7 col0
 PASS
-Test 5 - 2 spanning cells starts at diffrent row index but end at same row index.
+Test 5 - 2 spanning cells starts at different row index but end at same row index.
 
 row0 col0 rowspan=6 height=400px	row0 col1
 PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows.html b/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows.html
index f0f5253..89b0ea63 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-all-rowspans-height-distribution-in-rows.html
@@ -68,7 +68,7 @@
     </tr>
   </tbody>
 </table>
-<h5>Test 3 - 2 same row spanning cells with diffrent heights.</h5>
+<h5>Test 3 - 2 same row spanning cells with different heights.</h5>
 <table border="1">
   <tbody>
     <tr  data-expected-height="0">
@@ -125,7 +125,7 @@
     </tr>
   </tbody>
 </table>
-<h5>Test 5 - 2 spanning cells starts at diffrent row index but end at same row index.</h5>
+<h5>Test 5 - 2 spanning cells starts at different row index but end at same row index.</h5>
 <table border="1">
   <tbody>
     <tr data-expected-height="35">
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-block.html b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-block.html
index 85472b87..f4ce917 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-block.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-block.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Test passes if you see three blue boxes in three seperate rows. -->
+<!-- Test passes if you see three blue boxes in three separate rows. -->
 <html style="font: 1em/1 Ahem, sans-serif;">
 <style type="text/css">
 .container:before {
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-row.html b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-row.html
index dbdf0db..95647c1 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table-row.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Test passes if you see three blue boxes in three seperate rows. -->
+<!-- Test passes if you see three blue boxes in three separate rows. -->
 <html style="font: 1em/1 Ahem, sans-serif;">
 <style type="text/css">
 .container:before {
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table.html b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table.html
index 0e5ba60..a7edcdc 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-cell-before-after-content-around-table.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Test passes if you see three blue boxes in three seperate rows. -->
+<!-- Test passes if you see three blue boxes in three separate rows. -->
 <html style="font: 1em/1 Ahem, sans-serif;">
 <style type="text/css">
 .container:before {
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row-expected.txt b/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row-expected.txt
index 232ccec6..d4bb4a1 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row-expected.txt
@@ -1,6 +1,6 @@
 Test for chromium bug : 305169. <colgroup> is ignored if seen after <tr>.
 
-Columns width are not based on width specified in colGroup becuase colGroup is present after table row and we was supporting it only when colGroup is present at the start in table.
+Columns width are not based on width specified in colGroup because colGroup is present after table row and we was supporting it only when colGroup is present at the start in table.
 
 First
 PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row.html b/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row.html
index 279ddb3c..c591955 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-colgroup-present-after-table-row.html
@@ -8,7 +8,7 @@
 </head>
 <body onload="checkLayout('td')">
 <h3>Test for chromium bug : <a href="https://code.google.com/p/chromium/issues/detail?id=305169">305169</a>. &lt;colgroup&gt; is ignored if seen after &lt;tr&gt;.</h3>
-<h4>Columns width are not based on width specified in colGroup becuase colGroup is present after table row and we was supporting it only when colGroup is present at the start in table.</h4>
+<h4>Columns width are not based on width specified in colGroup because colGroup is present after table row and we was supporting it only when colGroup is present at the start in table.</h4>
   <table style="width: 100%;" border=1px>
     <tbody>
       <tr>
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border-quirks-mode.html b/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border-quirks-mode.html
index 8df1cde..c2628969 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border-quirks-mode.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border-quirks-mode.html
@@ -1,7 +1,7 @@
 <html>
 <body>
 <!-- https://bugs.webkit.org/show_bug.cgi?id=72180 : CSS table with 100% width overflow their container block -->
-<!-- The test passes if the inner table has 2 seperate borders in all corners. -->
+<!-- The test passes if the inner table has 2 separate borders in all corners. -->
 <div style='display:table; border: 1px solid black; width: 500px; height: 500px; padding: 10px;'>
   <div style='display:table-row; border: 1px solid red;'>
     <div style='display:table-cell; border: 1px solid blue;'>
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border.html b/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border.html
index b07f3ce..1f6a8ee 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-in-table-percent-width-collapsing-border.html
@@ -2,7 +2,7 @@
 <html>
 <body>
 <!-- https://bugs.webkit.org/show_bug.cgi?id=72180 : CSS table with 100% width overflow their container block -->
-<!-- The test passes if the inner table has 2 seperate borders in all corners. -->
+<!-- The test passes if the inner table has 2 separate borders in all corners. -->
 <div style='display:table; border: 1px solid black; width: 500px; height: 500px; padding: 10px;'>
   <div style='display:table-row; border: 1px solid red;'>
     <div style='display:table-cell; border: 1px solid blue;'>
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-block.html b/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-block.html
index 0cf4639..bdc534fe 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-block.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-block.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Test passes if you see three blue boxes in three seperate rows. -->
+<!-- Test passes if you see three blue boxes in three separate rows. -->
 <html style="font: 1em/1 Ahem, sans-serif;">
 <style type="text/css">
 .container:before 
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-table.html b/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-table.html
index 761ccba..b32087e 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-table.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-row-before-after-content-around-table.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Test passes if you see three blue boxes in three seperate rows. -->
+<!-- Test passes if you see three blue boxes in three separate rows. -->
 <html style="font: 1em/1 Ahem, sans-serif;">
 <style type="text/css">
 .container:before 
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells-expected.txt b/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells-expected.txt
index c47de37..321cf33 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells-expected.txt
@@ -422,5 +422,5 @@
 04:38:02	4 failures6 new passes11 flakes13 missing results
 triggeredgtk-linux-64-release-tests-wk2
 04:30:45	uploadingrelease.zip
-04:28:43	Failure: timeout occured during testing
+04:28:43	Failure: timeout occurred during testing
 uploaded results ]
diff --git a/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells.html b/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells.html
index 7ee7d545..4c0cc97 100644
--- a/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells.html
+++ b/third_party/WebKit/LayoutTests/fast/table/table-rowspan-crash-with-huge-rowspan-cells.html
@@ -1949,7 +1949,7 @@
 </tr>
 <tr>
   <td rowspan="2">04:28:43</td>
-  <td rowspan="1">Failure: timeout occured during testing</td>
+  <td rowspan="1">Failure: timeout occurred during testing</td>
 </tr>
 <tr>
   <td rowspan="1"></td>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
index e293c62..a1ded28 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -443,9 +443,23 @@
     return UI.viewManager.showView("elements.eventListeners");
 }
 
-InspectorTest.expandAndDumpSelectedElementEventListeners = function(callback)
+InspectorTest.expandAndDumpSelectedElementEventListeners = function(callback, force)
 {
-    InspectorTest.expandAndDumpEventListeners(InspectorTest.eventListenersWidget()._eventListenersView, callback);
+    InspectorTest.expandAndDumpEventListeners(InspectorTest.eventListenersWidget()._eventListenersView, callback, force);
+}
+
+InspectorTest.removeFirstEventListener = function()
+{
+    var treeOutline = InspectorTest.eventListenersWidget()._eventListenersView._treeOutline;
+    var listenerTypes = treeOutline.rootElement().children();
+    for (var i = 0; i < listenerTypes.length; i++) {
+        var listeners = listenerTypes[i].children();
+        if (listeners.length && !listenerTypes[i].hidden) {
+            listeners[0].eventListener().remove();
+            listeners[0]._removeListenerBar();
+            break;
+        }
+    }
 }
 
 InspectorTest.dumpObjectPropertySectionDeep = function(section)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
index e5f92c9..1a20d3f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -319,10 +319,8 @@
     }
 }
 
-InspectorTest.expandAndDumpEventListeners = function(eventListenersView, callback)
+InspectorTest.expandAndDumpEventListeners = function(eventListenersView, callback, force)
 {
-    InspectorTest.addSniffer(Components.EventListenersView.prototype, "_eventListenersArrivedForTest", listenersArrived);
-
     function listenersArrived()
     {
         var listenerTypes = eventListenersView._treeOutline.rootElement().children();
@@ -352,6 +350,11 @@
         }
         callback();
     }
+
+    if (force)
+        listenersArrived();
+    else
+        InspectorTest.addSniffer(Components.EventListenersView.prototype, "_eventListenersArrivedForTest", listenersArrived);
 }
 
 InspectorTest.dumpNavigatorView = function(navigatorView)
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove-expected.txt
new file mode 100644
index 0000000..44291c0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove-expected.txt
@@ -0,0 +1,46 @@
+Tests removing event listeners in the Elements sidebar panel.
+
+Inspect Me Inspect Sibling
+
+======== click ========
+== normal
+[expanded] button#nodeRemoveevent-listener-sidebar-remove.html:9
+    useCapture: false
+    passive: false
+    once: false
+    handler: function f() {}
+
+======== mouseover ========
+== normal
+[expanded] button#nodeRemoveevent-listener-sidebar-remove.html:9
+    useCapture: false
+    passive: false
+    once: false
+    handler: function f() {}
+Listeners after removal:
+
+======== mouseover ========
+== normal
+[expanded] button#nodeRemoveevent-listener-sidebar-remove.html:9
+    useCapture: false
+    passive: false
+    once: false
+    handler: function f() {}
+Listeners for sibling node:
+
+======== click ========
+== normal
+[expanded] button#node-siblingRemoveevent-listener-sidebar-remove.html:10
+    useCapture: false
+    passive: false
+    once: false
+    handler: function g() {}
+
+======== mouseover ========
+== normal
+[expanded] button#node-siblingRemoveevent-listener-sidebar-remove.html:10
+    useCapture: false
+    passive: false
+    once: false
+    handler: function g() {}
+
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove.html b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove.html
new file mode 100644
index 0000000..9deabf4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-remove.html
@@ -0,0 +1,73 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script>
+
+function setupEventListeners()
+{
+    function f() {}
+    function g() {}
+    var button = document.getElementById("node");
+    button.addEventListener("click", f, false);
+    button.addEventListener("mouseover", f, false);
+    var sibling = document.getElementById("node-sibling");
+    sibling.addEventListener("click", g, false);
+    sibling.addEventListener("mouseover", g, false);
+}
+
+function test()
+{
+    Common.settingForTest("showEventListenersForAncestors").set(false);
+
+
+    function step1()
+    {
+        InspectorTest.selectNodeWithId("node", function () {
+            InspectorTest.expandAndDumpSelectedElementEventListeners(step2);
+        });
+    }
+
+    function step2()
+    {
+        InspectorTest.removeFirstEventListener();
+        InspectorTest.addResult("Listeners after removal:");
+        InspectorTest.expandAndDumpSelectedElementEventListeners(step3, true);
+    }
+
+    function step3()
+    {
+        InspectorTest.selectNodeWithId("node-sibling", function () {
+            InspectorTest.addResult("Listeners for sibling node:");
+            InspectorTest.expandAndDumpSelectedElementEventListeners(step4);
+        });
+    }
+
+    function step4()
+    {
+        InspectorTest.completeTest();
+    }
+
+    step1();
+}
+
+function onloadHandler()
+{
+    setupEventListeners();
+    runTest();
+}
+</script>
+</head>
+
+
+
+<body onload="onloadHandler()">
+<p>
+Tests removing event listeners in the Elements sidebar panel.
+</p>
+
+<button id="node">Inspect Me</button>
+<button id="node-sibling">Inspect Sibling</button>
+
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
index d838f53..afa7292 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-repeat-round-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-repeat-round-expected.png
index 102ecd8..881a1de 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-repeat-round-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-repeat-round-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-rotate-transform-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-rotate-transform-expected.png
index bd65662..4132a084 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-rotate-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-rotate-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-side-reduction-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-side-reduction-expected.png
index 77e52df1..bda0ada 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
index 6612a57..94cb1a3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
index 21aa797..b5ca6cb 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
index 746f5e1a..6a61594 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/table/table-all-rowspans-height-distribution-in-rows-expected.txt
@@ -60,7 +60,7 @@
 PASS
 row6 col0
 PASS
-Test 3 - 2 same row spanning cells with diffrent heights.
+Test 3 - 2 same row spanning cells with different heights.
 
 row0 col0 rowspan=6 height=300px	row0 col1 rowspan=6 height=500px
 PASS
@@ -125,7 +125,7 @@
 PASS
 row7 col0
 PASS
-Test 5 - 2 spanning cells starts at diffrent row index but end at same row index.
+Test 5 - 2 spanning cells starts at different row index but end at same row index.
 
 row0 col0 rowspan=6 height=400px	row0 col1
 PASS
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
index 17ffaa2..63f81584 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
index 2a858cc..c03f6ecc 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/repeat/negative-offset-repeat-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
index 72ff7d54..14b1190 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/color-profile-border-image-source-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index 0d405733..35f81618 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -111,6 +111,7 @@
     attribute @@toStringTag
     method close
     method constructor
+    method getOutputTimestamp
     method suspend
 interface AudioDestinationNode : AudioNode
     attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/svg/dom/integer-optional-integer-value-range.html b/third_party/WebKit/LayoutTests/svg/dom/integer-optional-integer-value-range.html
new file mode 100644
index 0000000..50e408e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/dom/integer-optional-integer-value-range.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>SVGIntegerOptionalInteger value range</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(function() {
+  var element = document.createElementNS('http://www.w3.org/2000/svg', 'feConvolveMatrix');
+  element.setAttribute('order', '2147483648');
+  assert_equals(element.orderX.baseVal, 2147483647);
+
+  element.setAttribute('order', '-2147483649');
+  assert_equals(element.orderX.baseVal, -2147483648);
+}, document.title+', outside range of int.');
+
+test(function() {
+  var element = document.createElementNS('http://www.w3.org/2000/svg', 'feConvolveMatrix');
+  element.setAttribute('order', '2147483578');
+  assert_equals(element.orderX.baseVal, 2147483647);
+}, document.title+', not exactly representable as int.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 9f7159e..9a5659e 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -111,6 +111,7 @@
     attribute @@toStringTag
     method close
     method constructor
+    method getOutputTimestamp
     method suspend
 interface AudioDestinationNode : AudioNode
     attribute @@toStringTag
diff --git a/third_party/WebKit/LayoutTests/webaudio/audiocontext-getoutputtimestamp.html b/third_party/WebKit/LayoutTests/webaudio/audiocontext-getoutputtimestamp.html
new file mode 100644
index 0000000..905d74b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/audiocontext-getoutputtimestamp.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Testing AudioContext.getOutputTimestamp() method</title>
+  <script src="../resources/testharness.js"></script>
+  <script src="../resources/testharnessreport.js"></script>
+  <script src="resources/audio-testing.js"></script>
+</head>
+<body>
+  <script>
+    var audit = Audit.createTaskRunner();
+
+    audit.defineTask('getoutputtimestamp-initial-values', function (taskDone) {
+      let context = new AudioContext;
+      let timestamp = context.getOutputTimestamp();
+
+      Should('timestamp.contextTime', timestamp.contextTime).exist();
+      Should('timestamp.performanceTime', timestamp.performanceTime).exist();
+
+      Should('timestamp.contextTime', timestamp.contextTime).beEqualTo(0);
+      Should('timestamp.performanceTime', timestamp.performanceTime).beEqualTo(0);
+
+      taskDone();
+    });
+
+    audit.runTasks();
+  </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js b/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js
index 1ee34bd..4272fad7 100644
--- a/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js
+++ b/third_party/WebKit/LayoutTests/webaudio/resources/context-properties.js
@@ -49,10 +49,10 @@
   'close',
   'constructor',
   'suspend',
+  'getOutputTimestamp'
 
   // TODO(hongchan): Not implemented yet.
   // 'outputLatency',
-  // 'getOutputTimestamp'
 ];
 
 
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index e1fbb83e..475006f 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -176,6 +176,7 @@
     attribute @@toStringTag
     method close
     method constructor
+    method getOutputTimestamp
     method suspend
 interface AudioDestinationNode : AudioNode
     attribute @@toStringTag
diff --git a/third_party/WebKit/ManualTests/webaudio/audiooutputtimestamp.html b/third_party/WebKit/ManualTests/webaudio/audiooutputtimestamp.html
new file mode 100644
index 0000000..4bd5d6e0
--- /dev/null
+++ b/third_party/WebKit/ManualTests/webaudio/audiooutputtimestamp.html
@@ -0,0 +1,133 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test AudioContext.getOutputTimestamp() method</title>
+    <style type="text/css">
+      body {
+        margin: 2em;
+      }
+      .manual-test-ui {
+        font-family: Arial;
+        padding: 1em;
+        border: 1px solid #999;
+      }
+      .manual-test-ui button {
+        padding: 1em;
+        font-size: 1em;
+      }
+      .manual-test-ui div {
+        padding: 10px;
+        font-size: 1.5em;
+      }
+      .manual-test-ui-beep-indicator {
+         padding: 10px;
+         display: inline-block;
+         border-radius: 50%;
+         width: 10px;
+         height: 10px;
+         background: gray;
+      }
+    </style>
+  </head>
+
+  <body>
+    <h1>Test AudioContext.getOutputTimestamp() method</h1>
+
+    <p>Tests the values returned from AudioContext.getOutputTimestamp()</p>
+
+    <p>Press "Start testing" to run the test. You should hear a sine tone (beeping) in 2 seconds.
+       During the delay the color of "beeping indicator" is red.</p>
+
+    <p>The color of "beeping indicator" is yellow when 'context.currentTime' is at beeping
+       interval but the estimated output position is not there yet and thus beeping is not audible.</p>
+
+    <p><b>Note: </b> the "beeping indicator" might never be seen yellow if the test is run in the
+       environment with low latency audio (i.e. if the output latency is smaller than frame update
+       period).</p>
+
+    <p>The color of "beeping indicator" is green when the estimated output position is at beeping
+       interval, this should happen exactly when beeping is audible.</p>
+
+    <p>Press "Refresh values" to fetch the fresh output audio timestamp values
+      and compare them to 'AudioContext.currentTime' and 'Performance.now()'. </p>
+
+    <p>When context is running the obtained audio timestamp and performance timestamp values must be always
+       slightly behind of 'AudioContext.currentTime' and 'Performance.now()' correspondingly.</p>
+    
+    <p>Please see <a href="https://webaudio.github.io/web-audio-api/#audiotimestamp">Web Audio
+      API</a> for more details.</p>
+
+    <div class="manual-test-ui">
+      <div id="audioTime"></div>
+      <div id="performanceTime"></div>
+      <div id="timestampContextTime"></div>
+      <div id="timestampPerformanceTime"></div>
+      <div class="manual-test-ui-beep-indicator" id="beepIndicator"></div>
+
+      <button id="startButton" onclick="startTesting()">Start testing</button>
+      <button id="valuesButton" onclick="refreshValues()">Refresh values</button>
+      <button onclick="context.suspend()">Suspend context</button>
+      <button onclick="context.resume()">Resume context</button>
+    </div>
+
+    <script type="text/javascript">
+      var context = new AudioContext();
+
+      refreshValues();
+
+      let startBeepingTime;
+      let endBeepingTime;
+      let indicator = document.querySelector('#beepIndicator');
+
+      function inBeepingInterval(audioPosition) {
+        return audioPosition >= startBeepingTime && audioPosition <= endBeepingTime;
+      }
+
+      function checkAudioOutputPosition() {
+        if (!document.querySelector('#startButton').disabled)
+           return;
+        window.requestAnimationFrame(checkAudioOutputPosition);
+
+        if (context.state == "suspended") {
+          indicator.style.background = "green";
+          return;
+        }
+
+        let timestamp = context.getOutputTimestamp();
+        let audioOutputPosition = (performance.now() - timestamp.performanceTime) * 0.001 + timestamp.contextTime;
+
+        if (inBeepingInterval(audioOutputPosition))
+           indicator.style.background = "green";
+        else if (inBeepingInterval(context.currentTime))
+           indicator.style.background = "yellow";
+      }
+
+      function startTesting() {
+        document.querySelector('#startButton').disabled = true;
+        let oscillator = context.createOscillator();
+        oscillator.connect(context.destination);
+        startBeepingTime = context.currentTime + 2.0;
+        endBeepingTime = startBeepingTime + 3.0;
+
+        oscillator.start(startBeepingTime);
+        oscillator.stop(endBeepingTime);
+        indicator.style.background = "red";
+        window.requestAnimationFrame(checkAudioOutputPosition);
+
+        oscillator.onended = () => {
+            document.querySelector('#startButton').disabled = false;
+            indicator.style.background = "gray";
+        }
+      }
+
+      function refreshValues() {
+        document.querySelector("#audioTime").innerHTML = "context.currentTime: " + context.currentTime;
+        document.querySelector("#performanceTime").innerHTML = "performance.now(): " + performance.now();
+
+        let timestamp = context.getOutputTimestamp();
+        document.querySelector("#timestampContextTime").innerHTML = "timestamp audio: " + timestamp.contextTime;
+        document.querySelector("#timestampPerformanceTime").innerHTML = "timestamp performance: " + timestamp.performanceTime;
+      }
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h
index 1cdd16f..9e1f448 100644
--- a/third_party/WebKit/Source/core/frame/FrameView.h
+++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -332,7 +332,7 @@
   };
 
   ScrollingReasons getScrollingReasons();
-  bool isScrollable() override;
+  bool isScrollable();
   bool isProgrammaticallyScrollable() override;
 
   enum ScrollbarModesCalculationStrategy { RulesFromWebContentOnly, AnyRule };
diff --git a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
index cd50a3b..23c2a4e0 100644
--- a/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp
@@ -548,8 +548,11 @@
     if (oldValue != value) {
       if (m_webMediaPlayer)
         m_webMediaPlayer->requestRemotePlaybackDisabled(!value.isNull());
+      // TODO(mlamouri): there is no direct API to expose if
+      // disableRemotePLayback attribute has changed. It will require a direct
+      // access to MediaControls for the moment.
       if (mediaControls())
-        mediaControls()->refreshCastButtonVisibility();
+        mediaControls()->onDisableRemotePlaybackAttributeChanged();
     }
   } else {
     HTMLElement::parseAttribute(name, oldValue, value);
@@ -3087,29 +3090,44 @@
     WebRemotePlaybackAvailability availability) {
   if (remotePlaybackClient())
     remotePlaybackClient()->availabilityChanged(availability);
+
+  // TODO(mlamouri): the RemotePlayback object should be used in order to
+  // register to watch availability but the object is in modules/ and core/ has
+  // no access to it. It will have to be done when the media controls move to
+  // modules/.
   if (mediaControls())
-    mediaControls()->refreshCastButtonVisibility();
+    mediaControls()->onRemotePlaybackAvailabilityChanged();
 }
 
 bool HTMLMediaElement::hasRemoteRoutes() const {
+  // TODO(mlamouri): this is only used for controls related code. It shouldn't
+  // live in HTMLMediaElement.
   return remotePlaybackClient() &&
          remotePlaybackClient()->remotePlaybackAvailable();
 }
 
 void HTMLMediaElement::connectedToRemoteDevice() {
   m_playingRemotely = true;
-  if (mediaControls())
-    mediaControls()->startedCasting();
   if (remotePlaybackClient())
     remotePlaybackClient()->stateChanged(WebRemotePlaybackState::Connecting);
+
+  // TODO(mlamouri): the RemotePlayback object should be used in order to listen
+  // for events but the object is in modules/ and core/ has no access to it. It
+  // will have to be done when the media controls move to modules/.
+  if (mediaControls())
+    mediaControls()->onRemotePlaybackConnecting();
 }
 
 void HTMLMediaElement::disconnectedFromRemoteDevice() {
   m_playingRemotely = false;
-  if (mediaControls())
-    mediaControls()->stoppedCasting();
   if (remotePlaybackClient())
     remotePlaybackClient()->stateChanged(WebRemotePlaybackState::Disconnected);
+
+  // TODO(mlamouri): the RemotePlayback object should be used in order to listen
+  // for events but the object is in modules/ and core/ has no access to it. It
+  // will have to be done when the media controls move to modules/.
+  if (mediaControls())
+    mediaControls()->onRemotePlaybackDisconnected();
 }
 
 void HTMLMediaElement::cancelledRemotePlaybackRequest() {
diff --git a/third_party/WebKit/Source/core/html/shadow/MediaControls.h b/third_party/WebKit/Source/core/html/shadow/MediaControls.h
index 5112210..2b520c58 100644
--- a/third_party/WebKit/Source/core/html/shadow/MediaControls.h
+++ b/third_party/WebKit/Source/core/html/shadow/MediaControls.h
@@ -65,9 +65,6 @@
   void enteredFullscreen();
   void exitedFullscreen();
 
-  void startedCasting();
-  void stoppedCasting();
-  void refreshCastButtonVisibility();
   void showOverlayCastButtonIfNeeded();
   // Update cast button visibility, but don't try to update our panel
   // button visibility for space.
@@ -103,6 +100,18 @@
   // be notified on the TextTrack object. See https://crbug.com/669977
   void onTrackElementFailedToLoad() { onTextTracksAddedOrRemoved(); }
 
+  // TODO(mlamouri): the following methods will be able to become private when
+  // the controls have moved to modules/ and have access to RemotePlayback.
+  void onRemotePlaybackAvailabilityChanged() { refreshCastButtonVisibility(); }
+  void onRemotePlaybackConnecting() { startedCasting(); }
+  void onRemotePlaybackDisconnected() { stoppedCasting(); }
+
+  // TODO(mlamouri): this method is needed in order to notify the controls that
+  // the attribute have changed.
+  void onDisableRemotePlaybackAttributeChanged() {
+    refreshCastButtonVisibility();
+  }
+
   DECLARE_VIRTUAL_TRACE();
 
  private:
@@ -163,6 +172,11 @@
   void onError();
   void onLoadedMetadata();
 
+  // Internal cast related methods.
+  void startedCasting();
+  void stoppedCasting();
+  void refreshCastButtonVisibility();
+
   Member<HTMLMediaElement> m_mediaElement;
 
   // Media control elements.
diff --git a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.cpp b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.cpp
index fba370ea..85ccecc00 100644
--- a/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGIntegerOptionalInteger.cpp
@@ -52,17 +52,10 @@
 
 SVGPropertyBase* SVGIntegerOptionalInteger::cloneForAnimation(
     const String& value) const {
-  float floatX, floatY;
-  if (!parseNumberOptionalNumber(value, floatX, floatY)) {
-    return SVGIntegerOptionalInteger::create(SVGInteger::create(0),
-                                             SVGInteger::create(0));
-  }
-
-  int x = static_cast<int>(roundf(floatX));
-  int y = static_cast<int>(roundf(floatY));
-
-  return SVGIntegerOptionalInteger::create(SVGInteger::create(x),
-                                           SVGInteger::create(y));
+  SVGIntegerOptionalInteger* clone =
+      create(SVGInteger::create(0), SVGInteger::create(0));
+  clone->setValueAsString(value);
+  return clone;
 }
 
 String SVGIntegerOptionalInteger::valueAsString() const {
@@ -83,8 +76,8 @@
     x = y = 0;
   }
 
-  m_firstInteger->setValue(x);
-  m_secondInteger->setValue(y);
+  m_firstInteger->setValue(clampTo<int>(x));
+  m_secondInteger->setValue(clampTo<int>(y));
   return parseStatus;
 }
 
@@ -125,8 +118,8 @@
       percentage, repeatCount, fromInteger->secondInteger()->value(),
       toInteger->secondInteger()->value(),
       toAtEndOfDurationInteger->secondInteger()->value(), y);
-  m_firstInteger->setValue(static_cast<int>(roundf(x)));
-  m_secondInteger->setValue(static_cast<int>(roundf(y)));
+  m_firstInteger->setValue(clampTo<int>(roundf(x)));
+  m_secondInteger->setValue(clampTo<int>(roundf(y)));
 }
 
 float SVGIntegerOptionalInteger::calculateDistance(SVGPropertyBase* other,
diff --git a/third_party/WebKit/Source/core/svg/SVGParserUtilities.cpp b/third_party/WebKit/Source/core/svg/SVGParserUtilities.cpp
index f0ca3ea..247afd83 100644
--- a/third_party/WebKit/Source/core/svg/SVGParserUtilities.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGParserUtilities.cpp
@@ -28,11 +28,17 @@
 namespace blink {
 
 template <typename FloatType>
-static inline bool isValidRange(const FloatType& x) {
+static inline bool isValidRange(const FloatType x) {
   static const FloatType max = std::numeric_limits<FloatType>::max();
   return x >= -max && x <= max;
 }
 
+template <typename FloatType>
+static inline bool isValidExponent(const FloatType x) {
+  return x >= std::numeric_limits<FloatType>::min_exponent10 &&
+         x <= std::numeric_limits<FloatType>::max_exponent10;
+}
+
 // We use this generic parseNumber function to allow the Path parsing code to
 // work at a higher precision internally, without any unnecessary runtime cost
 // or code complexity.
@@ -41,21 +47,12 @@
                                const CharType* end,
                                FloatType& number,
                                WhitespaceMode mode) {
-  FloatType integer, decimal, frac, exponent;
-  int sign, expsign;
-
-  exponent = 0;
-  integer = 0;
-  frac = 1;
-  decimal = 0;
-  sign = 1;
-  expsign = 1;
-
   if (mode & AllowLeadingWhitespace)
     skipOptionalSVGSpaces(cursor, end);
 
   const CharType* ptr = cursor;
   // read the sign
+  int sign = 1;
   if (ptr < end && *ptr == '+')
     ptr++;
   else if (ptr < end && *ptr == '-') {
@@ -72,6 +69,7 @@
   while (ptr < end && *ptr >= '0' && *ptr <= '9')
     ++ptr;  // Advance to first non-digit.
 
+  FloatType integer = 0;
   if (ptr != digitsStart) {
     const CharType* ptrScanIntPart = ptr - 1;
     FloatType multiplier = 1;
@@ -84,6 +82,7 @@
       return false;
   }
 
+  FloatType decimal = 0;
   if (ptr < end && *ptr == '.') {  // read the decimals
     ptr++;
 
@@ -91,13 +90,19 @@
     if (ptr >= end || *ptr < '0' || *ptr > '9')
       return false;
 
-    while (ptr < end && *ptr >= '0' && *ptr <= '9')
-      decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1));
+    FloatType frac = 1;
+    while (ptr < end && *ptr >= '0' && *ptr <= '9') {
+      frac *= static_cast<FloatType>(0.1);
+      decimal += (*(ptr++) - '0') * frac;
+    }
   }
 
   // When we get here we should have consumed either a digit for the integer
   // part or a fractional part (with at least one digit after the '.'.)
-  ASSERT(digitsStart != ptr);
+  DCHECK_NE(digitsStart, ptr);
+
+  number = integer + decimal;
+  number *= sign;
 
   // read the exponent part
   if (ptr + 1 < end && (*ptr == 'e' || *ptr == 'E') &&
@@ -105,35 +110,33 @@
     ptr++;
 
     // read the sign of the exponent
+    bool exponentIsNegative = false;
     if (*ptr == '+')
       ptr++;
     else if (*ptr == '-') {
       ptr++;
-      expsign = -1;
+      exponentIsNegative = true;
     }
 
     // There must be an exponent
     if (ptr >= end || *ptr < '0' || *ptr > '9')
       return false;
 
+    FloatType exponent = 0;
     while (ptr < end && *ptr >= '0' && *ptr <= '9') {
       exponent *= static_cast<FloatType>(10);
       exponent += *ptr - '0';
       ptr++;
     }
+    if (exponentIsNegative)
+      exponent = -exponent;
     // Make sure exponent is valid.
-    if (!isValidRange(exponent) ||
-        exponent > std::numeric_limits<FloatType>::max_exponent)
+    if (!isValidExponent(exponent))
       return false;
+    if (exponent)
+      number *= static_cast<FloatType>(pow(10.0, static_cast<int>(exponent)));
   }
 
-  number = integer + decimal;
-  number *= sign;
-
-  if (exponent)
-    number *=
-        static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent)));
-
   // Don't return Infinity() or NaN().
   if (!isValidRange(number))
     return false;
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.h b/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.h
index 61d4e729..6df60d1e 100644
--- a/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.h
+++ b/third_party/WebKit/Source/core/svg/graphics/SVGImageForContainer.h
@@ -84,6 +84,14 @@
             ImageClampingMode,
             const ColorBehavior&) override;
 
+  // FIXME: Implement this to be less conservative.
+  bool currentFrameKnownToBeOpaque(MetadataMode = UseCurrentMetadata) override {
+    return false;
+  }
+
+  sk_sp<SkImage> imageForCurrentFrame(const ColorBehavior&) override;
+
+ protected:
   void drawPattern(GraphicsContext&,
                    const FloatRect&,
                    const FloatSize&,
@@ -92,13 +100,6 @@
                    const FloatRect&,
                    const FloatSize& repeatSpacing) override;
 
-  // FIXME: Implement this to be less conservative.
-  bool currentFrameKnownToBeOpaque(MetadataMode = UseCurrentMetadata) override {
-    return false;
-  }
-
-  sk_sp<SkImage> imageForCurrentFrame(const ColorBehavior&) override;
-
  private:
   SVGImageForContainer(SVGImage* image,
                        const FloatSize& containerSize,
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
index ac68183..3ce8d2f 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersView.js
@@ -326,10 +326,8 @@
   _removeListenerBar() {
     var parent = this.parent;
     parent.removeChild(this);
-    if (!parent.childCount()) {
-      parent.parent.removeChild(parent);
-      return;
-    }
+    if (!parent.childCount())
+      parent.collapse();
     var allHidden = true;
     for (var i = 0; i < parent.childCount(); ++i) {
       if (!parent.childAt(i).hidden)
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index 4f469835..6aee552 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -503,6 +503,7 @@
                     "webaudio/AudioBufferSourceOptions.idl",
                     "webaudio/AudioNodeOptions.idl",
                     "webaudio/AudioProcessingEventInit.idl",
+                    "webaudio/AudioTimestamp.idl",
                     "webaudio/BiquadFilterOptions.idl",
                     "webaudio/ChannelMergerOptions.idl",
                     "webaudio/ChannelSplitterOptions.idl",
@@ -893,6 +894,8 @@
   "$blink_modules_output_dir/webaudio/AudioNodeOptions.h",
   "$blink_modules_output_dir/webaudio/AudioProcessingEventInit.cpp",
   "$blink_modules_output_dir/webaudio/AudioProcessingEventInit.h",
+  "$blink_modules_output_dir/webaudio/AudioTimestamp.cpp",
+  "$blink_modules_output_dir/webaudio/AudioTimestamp.h",
   "$blink_modules_output_dir/webaudio/BiquadFilterOptions.cpp",
   "$blink_modules_output_dir/webaudio/BiquadFilterOptions.h",
   "$blink_modules_output_dir/webaudio/ChannelMergerOptions.cpp",
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
index 9206782..4d7fa832 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.cpp
@@ -9,8 +9,12 @@
 #include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/ExceptionCode.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/frame/UseCounter.h"
+#include "core/timing/DOMWindowPerformance.h"
+#include "core/timing/Performance.h"
 #include "modules/webaudio/AudioBufferCallback.h"
+#include "modules/webaudio/AudioTimestamp.h"
 #include "platform/Histogram.h"
 #include "platform/audio/AudioUtilities.h"
 
@@ -151,6 +155,33 @@
   return promise;
 }
 
+void AudioContext::getOutputTimestamp(ScriptState* scriptState,
+                                      AudioTimestamp& result) {
+  DCHECK(isMainThread());
+  LocalDOMWindow* window = scriptState->domWindow();
+  if (!window)
+    return;
+
+  if (!destination()) {
+    result.setContextTime(0.0);
+    result.setPerformanceTime(0.0);
+    return;
+  }
+
+  Performance* performance = DOMWindowPerformance::performance(*window);
+  DCHECK(performance);
+
+  AudioIOPosition position = outputPosition();
+
+  double performanceTime =
+      performance->monotonicTimeToDOMHighResTimeStamp(position.timestamp);
+  if (performanceTime < 0.0)
+    performanceTime = 0.0;
+
+  result.setContextTime(position.position);
+  result.setPerformanceTime(performanceTime);
+}
+
 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) {
   if (isContextClosed()) {
     // We've already closed the context previously, but it hasn't yet been
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.h b/third_party/WebKit/Source/modules/webaudio/AudioContext.h
index 9187b569..7690ada 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.h
@@ -12,6 +12,7 @@
 
 namespace blink {
 
+class AudioTimestamp;
 class Document;
 class ExceptionState;
 class ScriptState;
@@ -35,6 +36,8 @@
 
   bool hasRealtimeConstraint() final { return true; }
 
+  void getOutputTimestamp(ScriptState*, AudioTimestamp&);
+
  protected:
   AudioContext(Document&);
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioContext.idl b/third_party/WebKit/Source/modules/webaudio/AudioContext.idl
index a67f529..55ceb77 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioContext.idl
+++ b/third_party/WebKit/Source/modules/webaudio/AudioContext.idl
@@ -36,6 +36,9 @@
     [MeasureAs=AudioContextSuspend, CallWith=ScriptState, ImplementedAs=suspendContext] Promise<void> suspend();
     [MeasureAs=AudioContextClose, CallWith=ScriptState, ImplementedAs=closeContext] Promise<void> close();
 
+    // Output timestamp
+    [CallWith=ScriptState] AudioTimestamp getOutputTimestamp();
+
     // Sources
     // TODO(rtoy): The following methods should be here instead of in BaseAudioContext:
     //
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp
index 78eeb8ce..dba1616 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.cpp
@@ -46,7 +46,8 @@
 
 void AudioDestinationHandler::render(AudioBus* sourceBus,
                                      AudioBus* destinationBus,
-                                     size_t numberOfFrames) {
+                                     size_t numberOfFrames,
+                                     const AudioIOPosition& outputPosition) {
   // We don't want denormals slowing down any of the audio processing
   // since they can very seriously hurt performance.  This will take care of all
   // AudioNodes because they all process within this scope.
@@ -74,7 +75,7 @@
 
   // Let the context take care of any business at the start of each render
   // quantum.
-  context()->handlePreRenderTasks();
+  context()->handlePreRenderTasks(outputPosition);
 
   // Prepare the local audio input provider for this render quantum.
   if (sourceBus)
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h
index dc7fe45b..65a6743a 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioDestinationNode.h
@@ -51,7 +51,8 @@
   // sourceBus (if it's not 0).
   void render(AudioBus* sourceBus,
               AudioBus* destinationBus,
-              size_t numberOfFrames) final;
+              size_t numberOfFrames,
+              const AudioIOPosition& outputPosition) final;
 
   size_t currentSampleFrame() const {
     return acquireLoad(&m_currentSampleFrame);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioTimestamp.idl b/third_party/WebKit/Source/modules/webaudio/AudioTimestamp.idl
new file mode 100644
index 0000000..e1b738e
--- /dev/null
+++ b/third_party/WebKit/Source/modules/webaudio/AudioTimestamp.idl
@@ -0,0 +1,9 @@
+// Copyright 2016 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.
+
+// See https://webaudio.github.io/web-audio-api/#audiotimestamp
+dictionary AudioTimestamp {
+    double contextTime;
+    DOMHighResTimeStamp performanceTime;
+};
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
index d026540..ce29dc4 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -102,7 +102,8 @@
       m_periodicWaveSine(nullptr),
       m_periodicWaveSquare(nullptr),
       m_periodicWaveSawtooth(nullptr),
-      m_periodicWaveTriangle(nullptr) {
+      m_periodicWaveTriangle(nullptr),
+      m_outputPosition() {
   // If mediaPlaybackRequiresUserGesture is enabled, cross origin iframes will
   // require user gesture for the AudioContext to produce sound.
   if (document->settings() &&
@@ -134,7 +135,8 @@
       m_periodicWaveSine(nullptr),
       m_periodicWaveSquare(nullptr),
       m_periodicWaveSawtooth(nullptr),
-      m_periodicWaveTriangle(nullptr) {}
+      m_periodicWaveTriangle(nullptr),
+      m_outputPosition() {}
 
 BaseAudioContext::~BaseAudioContext() {
   deferredTaskHandler().contextWillBeDestroyed();
@@ -705,7 +707,8 @@
   }
 }
 
-void BaseAudioContext::handlePreRenderTasks() {
+void BaseAudioContext::handlePreRenderTasks(
+    const AudioIOPosition& outputPosition) {
   DCHECK(isAudioThread());
 
   // At the beginning of every render quantum, try to update the internal
@@ -723,6 +726,9 @@
     // Update the dirty state of the listener.
     listener()->updateState();
 
+    // Update output timestamp.
+    m_outputPosition = outputPosition;
+
     unlock();
   }
 }
@@ -816,6 +822,12 @@
   return false;
 }
 
+AudioIOPosition BaseAudioContext::outputPosition() {
+  DCHECK(isMainThread());
+  AutoLocker locker(this);
+  return m_outputPosition;
+}
+
 void BaseAudioContext::rejectPendingResolvers() {
   DCHECK(isMainThread());
 
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
index b38cd9a..74164a74 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -239,7 +239,7 @@
   void notifySourceNodeFinishedProcessing(AudioHandler*);
 
   // Called at the start of each render quantum.
-  void handlePreRenderTasks();
+  void handlePreRenderTasks(const AudioIOPosition& outputPosition);
 
   // Called at the end of each render quantum.
   void handlePostRenderTasks();
@@ -347,6 +347,8 @@
   // Returns whether the AudioContext is allowed to start rendering.
   bool isAllowedToStart() const;
 
+  AudioIOPosition outputPosition();
+
  private:
   friend class BaseAudioContextTest;
 
@@ -450,6 +452,7 @@
   enum { MaxNumberOfChannels = 32 };
 
   Optional<AutoplayStatus> m_autoplayStatus;
+  AudioIOPosition m_outputPosition;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
index 381ed49..448ef74 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -70,7 +70,9 @@
                                    AudioUtilities::kRenderQuantumFrames,
                                    false)),
       m_sampleRate(sampleRate),
-      m_isPlaying(false) {
+      m_isPlaying(false),
+      m_framesElapsed(0),
+      m_outputPosition() {
   // Histogram for audioHardwareBufferSize
   DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram,
                       ("WebAudio.AudioDestination.HardwareBufferSize"));
@@ -100,6 +102,9 @@
 
   if (m_callbackBufferSize <= kSmallBufferSize)
     m_callbackBufferSize = kDefaultCallbackBufferSize;
+
+  LOG(INFO) << "audioHardwareBufferSize = " << recommendedHardwareBufferSize;
+  LOG(INFO) << "callbackBufferSize      = " << m_callbackBufferSize;
 #endif
 
   // Quick exit if the requested size is too large.
@@ -168,7 +173,10 @@
 
 void AudioDestination::render(const WebVector<float*>& sourceData,
                               const WebVector<float*>& audioData,
-                              size_t numberOfFrames) {
+                              size_t numberOfFrames,
+                              double delay,
+                              double delayTimestamp,
+                              size_t priorFramesSkipped) {
   bool isNumberOfChannelsGood = audioData.size() == m_numberOfOutputChannels;
   if (!isNumberOfChannelsGood) {
     ASSERT_NOT_REACHED();
@@ -181,6 +189,13 @@
     return;
   }
 
+  m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped);
+  double outputPosition =
+      m_framesElapsed / static_cast<double>(m_sampleRate) - delay;
+  m_outputPosition.position = outputPosition;
+  m_outputPosition.timestamp = delayTimestamp;
+  m_outputPositionReceivedTimestamp = base::TimeTicks::Now();
+
   // Buffer optional live input.
   if (sourceData.size() >= 2) {
     // FIXME: handle multi-channel input and don't hard-code to stereo.
@@ -194,6 +209,8 @@
     m_renderBus->setChannelMemory(i, audioData[i], numberOfFrames);
 
   m_fifo->consume(m_renderBus.get(), numberOfFrames);
+
+  m_framesElapsed += numberOfFrames;
 }
 
 void AudioDestination::provideInput(AudioBus* bus, size_t framesToProcess) {
@@ -203,7 +220,24 @@
     sourceBus = m_inputBus.get();
   }
 
-  m_callback.render(sourceBus, bus, framesToProcess);
+  AudioIOPosition outputPosition = m_outputPosition;
+
+  // If platfrom buffer is more than two times longer than |framesToProcess|
+  // we do not want output position to get stuck so we promote it
+  // using the elapsed time from the moment it was initially obtained.
+  if (m_callbackBufferSize > framesToProcess * 2) {
+    double delta = (base::TimeTicks::Now() - m_outputPositionReceivedTimestamp)
+                       .InSecondsF();
+    outputPosition.position += delta;
+    outputPosition.timestamp += delta;
+  }
+
+  // Some implementations give only rough estimation of |delay| so
+  // we might have negative estimation |outputPosition| value.
+  if (outputPosition.position < 0.0)
+    outputPosition.position = 0.0;
+
+  m_callback.render(sourceBus, bus, framesToProcess, outputPosition);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.h b/third_party/WebKit/Source/platform/audio/AudioDestination.h
index dda3527..a62c38a 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.h
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.h
@@ -82,7 +82,10 @@
   // WebAudioDevice::RenderCallback
   void render(const WebVector<float*>& sourceData,
               const WebVector<float*>& audioData,
-              size_t numberOfFrames) override;
+              size_t numberOfFrames,
+              double delay,
+              double delayTimestamp,
+              size_t priorFramesSkipped) override;
 
   // AudioSourceProvider
   void provideInput(AudioBus*, size_t framesToProcess) override;
@@ -109,6 +112,10 @@
 
   std::unique_ptr<AudioFIFO> m_inputFifo;
   std::unique_ptr<AudioPullFIFO> m_fifo;
+
+  size_t m_framesElapsed;
+  AudioIOPosition m_outputPosition;
+  base::TimeTicks m_outputPositionReceivedTimestamp;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/AudioIOCallback.h b/third_party/WebKit/Source/platform/audio/AudioIOCallback.h
index ae1537d..1d3b0c4 100644
--- a/third_party/WebKit/Source/platform/audio/AudioIOCallback.h
+++ b/third_party/WebKit/Source/platform/audio/AudioIOCallback.h
@@ -29,10 +29,20 @@
 #ifndef AudioIOCallback_h
 #define AudioIOCallback_h
 
+#include "base/time/time.h"
+
 namespace blink {
 
 class AudioBus;
 
+struct AudioIOPosition {
+  // Audio stream position in seconds.
+  double position;
+  // System timestamp in seconds corresponding to the contained |position|
+  // value.
+  double timestamp;
+};
+
 // Abstract base-class for isochronous audio I/O client.
 class AudioIOCallback {
  public:
@@ -41,7 +51,8 @@
   // not 0).
   virtual void render(AudioBus* sourceBus,
                       AudioBus* destinationBus,
-                      size_t framesToProcess) = 0;
+                      size_t framesToProcess,
+                      const AudioIOPosition& outputPosition) = 0;
 
   virtual ~AudioIOCallback() {}
 };
diff --git a/third_party/WebKit/Source/platform/exported/WebAudioDevice.cpp b/third_party/WebKit/Source/platform/exported/WebAudioDevice.cpp
index 405302b..7b5aa7c 100644
--- a/third_party/WebKit/Source/platform/exported/WebAudioDevice.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebAudioDevice.cpp
@@ -29,7 +29,10 @@
 void WebAudioDevice::RenderCallback::render(
     const WebVector<float*>& sourceData,
     const WebVector<float*>& destinationData,
-    size_t numberOfFrames) {}
+    size_t numberOfFrames,
+    double delay,
+    double delayTimestamp,
+    size_t priorFramesSkipped) {}
 
 WebAudioDevice::RenderCallback::~RenderCallback() {}
 
diff --git a/third_party/WebKit/Source/platform/graphics/Image.cpp b/third_party/WebKit/Source/platform/graphics/Image.cpp
index 5e5a236..0531c450 100644
--- a/third_party/WebKit/Source/platform/graphics/Image.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Image.cpp
@@ -225,10 +225,11 @@
 sk_sp<SkShader> createPatternShader(const SkImage* image,
                                     const SkMatrix& shaderMatrix,
                                     const SkPaint& paint,
-                                    const FloatSize& spacing) {
+                                    const FloatSize& spacing,
+                                    SkShader::TileMode tmx,
+                                    SkShader::TileMode tmy) {
   if (spacing.isZero())
-    return image->makeShader(SkShader::kRepeat_TileMode,
-                             SkShader::kRepeat_TileMode, &shaderMatrix);
+    return image->makeShader(tmx, tmy, &shaderMatrix);
 
   // Arbitrary tiling is currently only supported for SkPictureShader, so we use
   // that instead of a plain bitmap shader to implement spacing.
@@ -239,9 +240,17 @@
   SkCanvas* canvas = recorder.beginRecording(tileRect);
   canvas->drawImage(image, 0, 0, &paint);
 
-  return SkShader::MakePictureShader(
-      recorder.finishRecordingAsPicture(), SkShader::kRepeat_TileMode,
-      SkShader::kRepeat_TileMode, &shaderMatrix, nullptr);
+  return SkShader::MakePictureShader(recorder.finishRecordingAsPicture(), tmx,
+                                     tmy, &shaderMatrix, nullptr);
+}
+
+SkShader::TileMode computeTileMode(float left,
+                                   float right,
+                                   float min,
+                                   float max) {
+  DCHECK(left < right);
+  return left >= min && right <= max ? SkShader::kClamp_TileMode
+                                     : SkShader::kRepeat_TileMode;
 }
 
 }  // anonymous namespace
@@ -286,6 +295,14 @@
   if (!image)
     return;
 
+  const FloatSize tileSize(
+      image->width() * scale.width() + repeatSpacing.width(),
+      image->height() * scale.height() + repeatSpacing.height());
+  const auto tmx = computeTileMode(destRect.x(), destRect.maxX(), adjustedX,
+                                   adjustedX + tileSize.width());
+  const auto tmy = computeTileMode(destRect.y(), destRect.maxY(), adjustedY,
+                                   adjustedY + tileSize.height());
+
   {
     SkPaint paint = context.fillPaint();
     paint.setColor(SK_ColorBLACK);
@@ -293,10 +310,11 @@
     paint.setFilterQuality(
         context.computeFilterQuality(this, destRect, normSrcRect));
     paint.setAntiAlias(context.shouldAntialias());
-    paint.setShader(createPatternShader(
-        image.get(), localMatrix, paint,
-        FloatSize(repeatSpacing.width() / scale.width(),
-                  repeatSpacing.height() / scale.height())));
+    paint.setShader(
+        createPatternShader(image.get(), localMatrix, paint,
+                            FloatSize(repeatSpacing.width() / scale.width(),
+                                      repeatSpacing.height() / scale.height()),
+                            tmx, tmy));
     context.drawRect(destRect, paint);
   }
 
diff --git a/third_party/WebKit/Source/platform/graphics/Image.h b/third_party/WebKit/Source/platform/graphics/Image.h
index e238844..28cbb409 100644
--- a/third_party/WebKit/Source/platform/graphics/Image.h
+++ b/third_party/WebKit/Source/platform/graphics/Image.h
@@ -156,14 +156,6 @@
   virtual sk_sp<SkImage> imageForCurrentFrame(const ColorBehavior&) = 0;
   virtual PassRefPtr<Image> imageForDefaultFrame();
 
-  virtual void drawPattern(GraphicsContext&,
-                           const FloatRect&,
-                           const FloatSize&,
-                           const FloatPoint& phase,
-                           SkBlendMode,
-                           const FloatRect&,
-                           const FloatSize& repeatSpacing = FloatSize());
-
   enum ImageClampingMode {
     ClampImageToSourceRect,
     DoNotClampImageToSourceRect
@@ -213,6 +205,14 @@
                        TileRule vRule,
                        SkBlendMode);
 
+  virtual void drawPattern(GraphicsContext&,
+                           const FloatRect&,
+                           const FloatSize&,
+                           const FloatPoint& phase,
+                           SkBlendMode,
+                           const FloatRect&,
+                           const FloatSize& repeatSpacing = FloatSize());
+
  private:
   RefPtr<SharedBuffer> m_encodedImageData;
   // TODO(Oilpan): consider having Image on the Oilpan heap and
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index bdb723f..a73aa82 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -319,12 +319,6 @@
     return ScrollBehaviorInstant;
   }
 
-  // TODO(bokan): This is only used in FrameView to check scrollability but is
-  // needed here to allow RootFrameViewport to preserve wheelHandler
-  // semantics. Not sure why it's FrameView specific, it could probably be
-  // generalized to other types of ScrollableAreas.
-  virtual bool isScrollable() { return true; }
-
   // TODO(bokan): FrameView::setScrollOffset uses updateScrollbars to scroll
   // which bails out early if its already in updateScrollbars, the effect being
   // that programmatic scrolls (i.e. setScrollOffset) are disabled when in
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index fdc093e..5c4b237 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -91,6 +91,7 @@
 #include "public/platform/WebMediaPlayerClient.h"
 #include "public/platform/WebMediaSource.h"
 #include "public/platform/WebMediaStreamSource.h"
+#include "public/platform/WebMouseWheelEvent.h"
 #include "public/platform/WebPageVisibilityState.h"
 #include "public/platform/WebReferrerPolicy.h"
 #include "public/platform/WebScrollbar.h"
diff --git a/third_party/WebKit/Source/web/WebInputEvent.cpp b/third_party/WebKit/Source/web/WebInputEvent.cpp
index 0f5eb2f6..ac01696 100644
--- a/third_party/WebKit/Source/web/WebInputEvent.cpp
+++ b/third_party/WebKit/Source/web/WebInputEvent.cpp
@@ -32,6 +32,7 @@
 
 #include "platform/KeyboardCodes.h"
 #include "public/platform/WebGestureEvent.h"
+#include "public/platform/WebMouseWheelEvent.h"
 #include "wtf/ASCIICType.h"
 #include "wtf/Assertions.h"
 #include "wtf/StringExtras.h"
diff --git a/third_party/WebKit/Source/web/WebInputEventConversion.h b/third_party/WebKit/Source/web/WebInputEventConversion.h
index 6286f64..495f6ed 100644
--- a/third_party/WebKit/Source/web/WebInputEventConversion.h
+++ b/third_party/WebKit/Source/web/WebInputEventConversion.h
@@ -36,6 +36,7 @@
 #include "platform/PlatformWheelEvent.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "public/platform/WebInputEvent.h"
+#include "public/platform/WebMouseWheelEvent.h"
 #include "web/WebExport.h"
 #include "wtf/Compiler.h"
 #include <vector>
@@ -48,7 +49,6 @@
 class TouchEvent;
 class WebGestureEvent;
 class WebMouseEvent;
-class WebMouseWheelEvent;
 class WebKeyboardEvent;
 class WebTouchEvent;
 class WheelEvent;
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py
similarity index 93%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py
index 14e56778..ee18001 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py
@@ -28,9 +28,9 @@
 
 import copy
 import logging
+import functools
 
 from webkitpy.common.memoized import memoized
-from functools import reduce
 
 _log = logging.getLogger(__name__)
 
@@ -101,7 +101,7 @@
 
     def read_results_by_directory(self, baseline_name):
         results_by_directory = {}
-        directories = reduce(set.union, map(set, [self._relative_baseline_search_paths(
+        directories = functools.reduce(set.union, map(set, [self._relative_baseline_search_paths(
             port, baseline_name) for port in self._ports.values()]))
 
         for directory in directories:
@@ -134,11 +134,11 @@
         # have the same baseline, then it can be promoted up to be the LayoutTests baseline.
         # All other baselines can only be removed if they're redundant with a baseline earlier
         # in the fallback order. They can never promoted up.
-        directories_immediately_preceding_root = self._directories_immediately_preceding_root(baseline_name)
+        immediately_preceding_root = self._directories_immediately_preceding_root(baseline_name)
 
         shared_result = None
         root_baseline_unused = False
-        for directory in directories_immediately_preceding_root:
+        for directory in immediately_preceding_root:
             this_result = new_results_by_directory.get(directory)
 
             # If any of these directories don't have a baseline, there's no optimization we can do.
@@ -160,21 +160,20 @@
             return
 
         new_results_by_directory[baseline_root] = shared_result
-        for directory in directories_immediately_preceding_root:
+        for directory in immediately_preceding_root:
             del new_results_by_directory[directory]
 
     def _find_optimal_result_placement(self, baseline_name):
         results_by_directory = self.read_results_by_directory(baseline_name)
         results_by_port_name = self._results_by_port_name(results_by_directory, baseline_name)
-        port_names_by_result = _invert_dictionary(results_by_port_name)
 
         new_results_by_directory = self._remove_redundant_results(
-            results_by_directory, results_by_port_name, port_names_by_result, baseline_name)
+            results_by_directory, results_by_port_name, baseline_name)
         self._optimize_result_for_root(new_results_by_directory, baseline_name)
 
         return results_by_directory, new_results_by_directory
 
-    def _remove_redundant_results(self, results_by_directory, results_by_port_name, port_names_by_result, baseline_name):
+    def _remove_redundant_results(self, results_by_directory, results_by_port_name, baseline_name):
         new_results_by_directory = copy.copy(results_by_directory)
         for port_name, port in self._ports.items():
             current_result = results_by_port_name.get(port_name)
@@ -187,7 +186,7 @@
             current_index, current_directory = self._find_in_fallbackpath(fallback_path, current_result, new_results_by_directory)
             for index in range(current_index + 1, len(fallback_path)):
                 new_directory = fallback_path[index]
-                if not new_directory in new_results_by_directory:
+                if new_directory not in new_results_by_directory:
                     # No result for this baseline in this directory.
                     continue
                 elif new_results_by_directory[new_directory] == current_result:
@@ -218,7 +217,7 @@
     def _move_baselines(self, baseline_name, results_by_directory, new_results_by_directory):
         data_for_result = {}
         for directory, result in results_by_directory.items():
-            if not result in data_for_result:
+            if result not in data_for_result:
                 source = self._join_directory(directory, baseline_name)
                 data_for_result[result] = self._filesystem.read_binary_file(source)
 
@@ -289,10 +288,10 @@
         return True
 
     def _optimize_virtual_root(self, baseline_name, non_virtual_baseline_name):
-        virtual_root_expected_baseline_path = self._filesystem.join(self._layout_tests_dir, baseline_name)
-        if not self._filesystem.exists(virtual_root_expected_baseline_path):
+        virtual_root_baseline_path = self._filesystem.join(self._layout_tests_dir, baseline_name)
+        if not self._filesystem.exists(virtual_root_baseline_path):
             return
-        root_sha1 = self._filesystem.sha1(virtual_root_expected_baseline_path)
+        root_sha1 = self._filesystem.sha1(virtual_root_baseline_path)
 
         results_by_directory = self.read_results_by_directory(non_virtual_baseline_name)
         # See if all the immediate predecessors of the virtual root have the same expected result.
@@ -306,8 +305,8 @@
                 break
 
         _log.debug("Deleting redundant virtual root expected result.")
-        _log.debug("    Deleting (file system): " + virtual_root_expected_baseline_path)
-        self._filesystem.remove(virtual_root_expected_baseline_path)
+        _log.debug("    Deleting (file system): " + virtual_root_baseline_path)
+        self._filesystem.remove(virtual_root_baseline_path)
 
     def optimize(self, baseline_name):
         # The virtual fallback path is the same as the non-virtual one tacked on to the bottom of the non-virtual path.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py
similarity index 84%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py
index 01dccec..1104f0d3 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baselineoptimizer_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer_unittest.py
@@ -28,7 +28,7 @@
 
 import unittest
 
-from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer
+from webkitpy.common.checkout.baseline_optimizer import BaselineOptimizer
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.webkit_finder import WebKitFinder
 
@@ -85,8 +85,11 @@
                 '/mock-checkout/third_party/WebKit/LayoutTests/another/test-expected.txt'),
             'result A')
 
-    def _assertOptimization(self, results_by_directory, expected_new_results_by_directory,
-                            baseline_dirname='', host=None):
+    def _assert_optimization(
+            self,
+            results_by_directory,
+            directory_to_new_results,
+            baseline_dirname='', host=None):
         if not host:
             host = MockHost()
         fs = host.filesystem
@@ -103,13 +106,13 @@
         ), host.port_factory.all_port_names())
         self.assertTrue(baseline_optimizer.optimize(fs.join(baseline_dirname, baseline_name)))
 
-        for dirname, contents in expected_new_results_by_directory.items():
+        for dirname, contents in directory_to_new_results.items():
             path = fs.join(webkit_base, 'LayoutTests', dirname, baseline_name)
             if contents is not None:
                 self.assertEqual(fs.read_binary_file(path), contents)
 
     def test_linux_redundant_with_win(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/win': '1',
                 'platform/linux': '1',
@@ -119,7 +122,7 @@
             })
 
     def test_covers_mac_win_linux(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/win': '1',
@@ -131,7 +134,7 @@
             })
 
     def test_overwrites_root(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/win': '1',
@@ -143,7 +146,7 @@
             })
 
     def test_no_new_common_directory(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/linux': '1',
@@ -156,7 +159,7 @@
             })
 
     def test_local_optimization(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/linux': '1',
@@ -168,7 +171,7 @@
             })
 
     def test_local_optimization_skipping_a_port_in_the_middle(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac-snowleopard': '1',
                 'platform/win': '1',
@@ -181,7 +184,7 @@
             })
 
     def test_baseline_redundant_with_root(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/win': '2',
@@ -193,7 +196,7 @@
             })
 
     def test_root_baseline_unused(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/win': '2',
@@ -205,7 +208,7 @@
             })
 
     def test_root_baseline_unused_and_non_existant(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'platform/mac': '1',
                 'platform/win': '2',
@@ -216,7 +219,7 @@
             })
 
     def test_virtual_root_redundant_with_actual_root(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'virtual/gpu/fast/canvas': '2',
                 'fast/canvas': '2',
@@ -228,7 +231,7 @@
             baseline_dirname='virtual/gpu/fast/canvas')
 
     def test_virtual_root_redundant_with_ancestors(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'virtual/gpu/fast/canvas': '2',
                 'platform/mac/fast/canvas': '2',
@@ -240,35 +243,8 @@
             },
             baseline_dirname='virtual/gpu/fast/canvas')
 
-    def test_virtual_root_redundant_with_ancestors_skip_scm_commands(self):
-        self._assertOptimization(
-            {
-                'virtual/gpu/fast/canvas': '2',
-                'platform/mac/fast/canvas': '2',
-                'platform/win/fast/canvas': '2',
-            },
-            {
-                'virtual/gpu/fast/canvas': None,
-                'fast/canvas': '2',
-            },
-            baseline_dirname='virtual/gpu/fast/canvas')
-
-    def test_virtual_root_redundant_with_ancestors_skip_scm_commands_with_file_not_in_scm(self):
-        self._assertOptimization(
-            {
-                'virtual/gpu/fast/canvas': '2',
-                'platform/mac/fast/canvas': '2',
-                'platform/win/fast/canvas': '2',
-            },
-            {
-                'virtual/gpu/fast/canvas': None,
-                'fast/canvas': '2',
-            },
-            baseline_dirname='virtual/gpu/fast/canvas',
-            host=MockHost())
-
     def test_virtual_root_not_redundant_with_ancestors(self):
-        self._assertOptimization(
+        self._assert_optimization(
             {
                 'virtual/gpu/fast/canvas': '2',
                 'platform/mac/fast/canvas': '1',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/detection_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/detection_unittest.py
index dad59e7..bab79ed 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/detection_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/detection_unittest.py
@@ -33,7 +33,7 @@
 from .detection import SCMDetector
 from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.common.system.executive_mock import MockExecutive
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 
 
 class SCMDetectorTest(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/host.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/host.py
index f2a7c0d..ca6ca95 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/host.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/host.py
@@ -34,7 +34,7 @@
 from webkitpy.common.config.builders import BUILDERS
 from webkitpy.common.net.buildbot import BuildBot
 from webkitpy.common.net import web
-from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.system.system_host import SystemHost
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.layout_tests.port.factory import PortFactory
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py
index 155e745..238fff7 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/host_mock.py
@@ -30,7 +30,7 @@
 from webkitpy.common.checkout.scm.scm_mock import MockSCM
 from webkitpy.common.net.buildbot_mock import MockBuildBot
 from webkitpy.common.net.web_mock import MockWeb
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 
 # New-style ports need to move down into webkitpy.common.
 from webkitpy.layout_tests.builder_list import BuilderList
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff.py
new file mode 100644
index 0000000..5600033
--- /dev/null
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff.py
@@ -0,0 +1,64 @@
+# Copyright 2016 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.
+
+"""Utility for outputting a HTML diff of two multi-line strings.
+
+The main purpose of this utility is to show the difference between
+text baselines (-expected.txt files) and actual text results.
+
+Note, in the standard library module difflib, there is also a HtmlDiff class,
+although it outputs a larger and more complex HTML table than we need.
+"""
+
+import difflib
+
+_TEMPLATE = """<html>
+<head>
+<style>.del { background: #faa; } .add { background: #afa; }</style>
+</head>
+<body>
+<pre>%s</pre>
+</body>
+</html>
+"""
+
+
+def html_diff(a_text, b_text):
+    """Returns a diff between two strings as HTML."""
+    # Diffs can be between multiple text files of different encodings
+    # so we always want to deal with them as byte arrays, not unicode strings.
+    assert isinstance(a_text, str)
+    assert isinstance(b_text, str)
+    a_lines = a_text.splitlines(True)
+    b_lines = b_text.splitlines(True)
+    return _TEMPLATE % html_diff_body(a_lines, b_lines)
+
+
+def html_diff_body(a_lines, b_lines):
+    matcher = difflib.SequenceMatcher(None, a_lines, b_lines)
+    output = []
+    for tag, a_start, a_end, b_start, b_end in matcher.get_opcodes():
+        a_chunk = ''.join(a_lines[a_start:a_end])
+        b_chunk = ''.join(b_lines[b_start:b_end])
+        output.append(_format_chunk(tag, a_chunk, b_chunk))
+    return ''.join(output)
+
+
+def _format_chunk(tag, a_chunk, b_chunk):
+    if tag == 'delete':
+        return _format_delete(a_chunk)
+    if tag == 'insert':
+        return _format_insert(b_chunk)
+    if tag == 'replace':
+        return _format_delete(a_chunk) + _format_insert(b_chunk)
+    assert tag == 'equal'
+    return a_chunk
+
+
+def _format_insert(chunk):
+    return '<span class="add">%s</span>' % chunk
+
+
+def _format_delete(chunk):
+    return '<span class="del">%s</span>' % chunk
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff_unittest.py
new file mode 100644
index 0000000..47bbf351
--- /dev/null
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/html_diff_unittest.py
@@ -0,0 +1,69 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from webkitpy.common.html_diff import html_diff, html_diff_body
+
+
+class TestHtmlDiff(unittest.TestCase):
+
+    def test_html_diff(self):
+        self.assertEqual(
+            html_diff('one\ntoo\nthree\n', 'one\ntwo\nthree\n'),
+            ('<html>\n'
+             '<head>\n'
+             '<style>.del { background: #faa; } .add { background: #afa; }</style>\n'
+             '</head>\n'
+             '<body>\n'
+             '<pre>one\n'
+             '<span class="del">too\n'
+             '</span><span class="add">two\n'
+             '</span>three\n'
+             '</pre>\n'
+             '</body>\n'
+             '</html>\n'))
+
+    def test_html_diff_same(self):
+        self.assertEqual(
+            html_diff_body(['one line\n'], ['one line\n']),
+            'one line\n')
+
+    def test_html_diff_delete(self):
+        self.assertEqual(
+            html_diff_body(['one line\n'], []),
+            '<span class="del">one line\n</span>')
+
+    def test_html_diff_insert(self):
+        self.assertEqual(
+            html_diff_body([], ['one line\n']),
+            '<span class="add">one line\n</span>')
+
+    def test_html_diff_ending_newline(self):
+        self.assertEqual(
+            html_diff_body(['one line'], ['one line\n']),
+            '<span class="del">one line</span><span class="add">one line\n</span>')
+
+    def test_html_diff_replace_multiple_lines(self):
+        a_lines = [
+            '1. Beautiful is better than ugly.\n',
+            '2. Explicit is better than implicit.\n',
+            '3. Simple is better than complex.\n',
+            '4. Complex is better than complicated.\n',
+        ]
+        b_lines = [
+            '1. Beautiful is better than ugly.\n',
+            '3.   Simple is better than complex.\n',
+            '4. Complicated is better than complex.\n',
+            '5. Flat is better than nested.\n',
+        ]
+        self.assertEqual(html_diff_body(a_lines, b_lines), (
+            '1. Beautiful is better than ugly.\n'
+            '<span class="del">2. Explicit is better than implicit.\n'
+            '3. Simple is better than complex.\n'
+            '4. Complex is better than complicated.\n'
+            '</span><span class="add">3.   Simple is better than complex.\n'
+            '4. Complicated is better than complex.\n'
+            '5. Flat is better than nested.\n'
+            '</span>'))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
index bc7b3b0..7a2e991 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
@@ -31,8 +31,8 @@
 import urllib2
 
 from webkitpy.common.memoized import memoized
-from webkitpy.common.net.layouttestresults import LayoutTestResults
-from webkitpy.common.net.networktransaction import NetworkTransaction
+from webkitpy.common.net.layout_test_results import LayoutTestResults
+from webkitpy.common.net.network_transaction import NetworkTransaction
 
 
 RESULTS_URL_BASE = 'https://storage.googleapis.com/chromium-layout-test-archives'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/file_uploader.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/file_uploader.py
index d12f78c..0f6264f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/file_uploader.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/file_uploader.py
@@ -29,7 +29,7 @@
 import mimetypes
 import urllib2
 
-from webkitpy.common.net.networktransaction import NetworkTransaction
+from webkitpy.common.net.network_transaction import NetworkTransaction
 
 
 def get_mime_type(filename):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layouttestresults.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layout_test_results.py
similarity index 100%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/net/layouttestresults.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/net/layout_test_results.py
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layout_test_results_unittest.py
similarity index 98%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/net/layout_test_results_unittest.py
index 056e613a..f0ad5c076 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/layout_test_results_unittest.py
@@ -28,7 +28,7 @@
 
 import unittest
 
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 
 
 class LayoutTestResultsTest(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction.py
similarity index 97%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction.py
index a0b57a2..5924e481 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction.py
@@ -41,6 +41,9 @@
 
 class NetworkTransaction(object):
 
+    # TODO(qyearsley): Rename convert_404_to_None
+    # pylint: disable=invalid-name
+
     def __init__(self, initial_backoff_seconds=10, grown_factor=1.5, timeout_seconds=(10 * 60), convert_404_to_None=False):
         self._initial_backoff_seconds = initial_backoff_seconds
         self._grown_factor = grown_factor
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction_unittest.py
similarity index 92%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction_unittest.py
index 8b696ee..62fb608 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/networktransaction_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/network_transaction_unittest.py
@@ -28,8 +28,8 @@
 
 
 from urllib2 import HTTPError
-from webkitpy.common.net.networktransaction import NetworkTransaction, NetworkTimeout
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.net.network_transaction import NetworkTransaction, NetworkTimeout
+from webkitpy.common.system.log_testing import LoggingTestCase
 
 
 class NetworkTransactionTest(LoggingTestCase):
@@ -53,9 +53,9 @@
         try:
             transaction.run(self._raise_exception)
             did_throw_exception = False
-        except Exception as e:
+        except Exception as error:  # pylint: disable=broad-except
             did_process_exception = True
-            self.assertEqual(e, self.exception)
+            self.assertEqual(error, self.exception)
         self.assertTrue(did_throw_exception)
         self.assertTrue(did_process_exception)
 
@@ -77,7 +77,7 @@
                         'WARNING: Received HTTP status 500 loading "http://example.com/".  '
                         'Retrying in 0.0 seconds...\n'])
 
-    def test_convert_404_to_None(self):
+    def test_convert_404_to_none(self):
         transaction = NetworkTransaction(convert_404_to_None=True)
         self.assertIsNone(transaction.run(self._raise_404_error))
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/rietveld_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/rietveld_unittest.py
index c4b6a73..2755169 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/rietveld_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/rietveld_unittest.py
@@ -8,7 +8,7 @@
 from webkitpy.common.net.rietveld import Rietveld
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.web_mock import MockWeb
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 
 
 class RietveldTest(LoggingTestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/web.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/web.py
index 49ab85d..167548e1 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/web.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/web.py
@@ -28,7 +28,7 @@
 
 import urllib2
 
-from webkitpy.common.net.networktransaction import NetworkTransaction
+from webkitpy.common.net.network_transaction import NetworkTransaction
 
 
 class Web(object):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs.py
similarity index 86%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs.py
index 05830846..6f57707 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs.py
@@ -49,26 +49,28 @@
         return log_directory
 
     def _find_newest_log_darwin(self, process_name, pid, include_errors, newer_than):
-        def is_crash_log(fs, dirpath, basename):
+        def is_crash_log(basename):
             return basename.startswith(process_name + "_") and basename.endswith(".crash")
 
         log_directory = self._log_directory_darwin()
-        logs = self._host.filesystem.files_under(log_directory, file_filter=is_crash_log)
+        logs = self._host.filesystem.files_under(
+            log_directory,
+            file_filter=lambda fs, dirname, basename: is_crash_log(basename))
         first_line_regex = re.compile(r'^Process:\s+(?P<process_name>.*) \[(?P<pid>\d+)\]$')
         errors = ''
         for path in reversed(sorted(logs)):
             try:
                 if not newer_than or self._host.filesystem.mtime(path) > newer_than:
-                    f = self._host.filesystem.read_text_file(path)
-                    match = first_line_regex.match(f[0:f.find('\n')])
+                    contents = self._host.filesystem.read_text_file(path)
+                    match = first_line_regex.match(contents[0:contents.find('\n')])
                     if match and match.group('process_name') == process_name and (pid is None or int(match.group('pid')) == pid):
-                        return errors + f
-            except IOError as e:
+                        return errors + contents
+            except IOError as error:
                 if include_errors:
-                    errors += "ERROR: Failed to read '%s': %s\n" % (path, str(e))
-            except OSError as e:
+                    errors += "ERROR: Failed to read '%s': %s\n" % (path, error)
+            except OSError as error:
                 if include_errors:
-                    errors += "ERROR: Failed to read '%s': %s\n" % (path, str(e))
+                    errors += "ERROR: Failed to read '%s': %s\n" % (path, error)
 
         if include_errors and errors:
             return errors
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs_unittest.py
similarity index 96%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs_unittest.py
index 9822340..b136707b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/crash_logs_unittest.py
@@ -23,10 +23,10 @@
 
 import unittest
 
-from webkitpy.common.system.crashlogs import CrashLogs
+from webkitpy.common.system.crash_logs import CrashLogs
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.systemhost import SystemHost
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host import SystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 
 
 def make_mock_crash_report_darwin(process_name, pid):
@@ -103,10 +103,10 @@
         log = crash_logs.find_newest_log("DumpRenderTree", newer_than=1.0)
         self.assertIsNone(log)
 
-        def bad_read(path):
+        def bad_read(_):
             raise IOError('IOError: No such file or directory')
 
-        def bad_mtime(path):
+        def bad_mtime(_):
             raise OSError('OSError: No such file or directory')
 
         filesystem.read_text_file = bad_read
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing.py
similarity index 98%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing.py
index 9dd82898c..a71bfe0 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing.py
@@ -33,6 +33,9 @@
 import logging
 import unittest
 
+# pylint: disable=invalid-name
+# Camel-case names are used here to match the style of the TestCase methods.
+
 
 class TestLogStream(object):
     """Represents a file-like object for unit-testing logging.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing_unittest.py
similarity index 95%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing_unittest.py
index 61c30c33a..1947377 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logtesting_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_testing_unittest.py
@@ -5,7 +5,7 @@
 import logging
 import unittest
 
-from webkitpy.common.system.logtesting import LoggingTestCase, LogTesting, TestLogStream
+from webkitpy.common.system.log_testing import LoggingTestCase, LogTesting, TestLogStream
 
 
 class TestLogStreamTest(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logutils.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py
similarity index 100%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/logutils.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils.py
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logutils_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
similarity index 97%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/logutils_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
index 5c9b937..7217ada 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/logutils_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/log_utils_unittest.py
@@ -23,8 +23,8 @@
 import logging
 import unittest
 
-from webkitpy.common.system.logtesting import TestLogStream
-from webkitpy.common.system.logutils import configure_logging
+from webkitpy.common.system.log_testing import TestLogStream
+from webkitpy.common.system.log_utils import configure_logging
 
 
 class ConfigureLoggingTestBase(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture.py
similarity index 92%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture.py
index cd4c00e..4ef5fdc 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture.py
@@ -39,10 +39,14 @@
     def __init__(self):
         self.saved_outputs = dict()
         self._log_level = logging.INFO
+        self._logs = None
+        self._logs_handler = None
+        self._logger = None
+        self._orig_log_level = None
 
     def set_log_level(self, log_level):
         self._log_level = log_level
-        if hasattr(self, '_logs_handler'):
+        if self._logs_handler is not None:
             self._logs_handler.setLevel(self._log_level)
 
     def _capture_output_with_name(self, output_name):
@@ -78,8 +82,10 @@
         delattr(self, '_logs')
         return (self._restore_output_with_name("stdout"), self._restore_output_with_name("stderr"), logs_string)
 
-    def assert_outputs(self, testcase, function, args=[], kwargs={}, expected_stdout="",
+    def assert_outputs(self, testcase, function, args=None, kwargs=None, expected_stdout="",
                        expected_stderr="", expected_exception=None, expected_logs=None):
+        args = args or []
+        kwargs = kwargs or {}
         self.capture_output()
         try:
             if expected_exception:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture_unittest.py
similarity index 90%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture_unittest.py
index c7de905..05f3e32 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/outputcapture_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/output_capture_unittest.py
@@ -23,7 +23,7 @@
 import logging
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 
 
 _log = logging.getLogger(__name__)
@@ -40,7 +40,7 @@
         _log.error('ERROR')
         _log.critical('CRITICAL')
 
-    def assertLogged(self, expected_logs):
+    def assert_logged(self, expected_logs):
         actual_stdout, actual_stderr, actual_logs = self.output.restore_output()
         self.assertEqual('', actual_stdout)
         self.assertEqual('', actual_stderr)
@@ -49,7 +49,7 @@
     def test_initial_log_level(self):
         self.output.capture_output()
         self.log_all_levels()
-        self.assertLogged('INFO\nWARN\nERROR\nCRITICAL\n')
+        self.assert_logged('INFO\nWARN\nERROR\nCRITICAL\n')
 
     def test_set_log_level(self):
         self.output.set_log_level(logging.ERROR)
@@ -57,4 +57,4 @@
         self.log_all_levels()
         self.output.set_log_level(logging.WARN)
         self.log_all_levels()
-        self.assertLogged('ERROR\nCRITICAL\nWARN\nERROR\nCRITICAL\n')
+        self.assert_logged('ERROR\nCRITICAL\nWARN\nERROR\nCRITICAL\n')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/path_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/path_unittest.py
index 38094f7..f2fe637 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/path_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/path_unittest.py
@@ -29,20 +29,20 @@
 import sys
 import unittest
 
-from webkitpy.common.system.systemhost import SystemHost
-from webkitpy.common.system.platforminfo_mock import MockPlatformInfo
+from webkitpy.common.system.system_host import SystemHost
+from webkitpy.common.system.platform_info_mock import MockPlatformInfo
 from webkitpy.common.system import path
 
 
 class AbspathTest(unittest.TestCase):
 
-    def platforminfo(self):
+    def platform_info(self):
         return SystemHost().platform
 
     def test_abspath_to_uri_cygwin(self):
         if sys.platform != 'cygwin':
             return
-        self.assertEqual(path.abspath_to_uri(self.platforminfo(), '/cygdrive/c/foo/bar.html'),
+        self.assertEqual(path.abspath_to_uri(self.platform_info(), '/cygdrive/c/foo/bar.html'),
                          'file:///C:/foo/bar.html')
 
     def test_abspath_to_uri_unixy(self):
@@ -52,7 +52,7 @@
     def test_abspath_to_uri_win(self):
         if sys.platform != 'win32':
             return
-        self.assertEqual(path.abspath_to_uri(self.platforminfo(), 'c:\\foo\\bar.html'),
+        self.assertEqual(path.abspath_to_uri(self.platform_info(), 'c:\\foo\\bar.html'),
                          'file:///c:/foo/bar.html')
 
     def test_abspath_to_uri_escaping_unixy(self):
@@ -63,7 +63,7 @@
     def test_abspath_to_uri_escaping_cygwin(self):
         if sys.platform != 'cygwin':
             return
-        self.assertEqual(path.abspath_to_uri(self.platforminfo(), '/cygdrive/c/foo/bar + baz%.html'),
+        self.assertEqual(path.abspath_to_uri(self.platform_info(), '/cygdrive/c/foo/bar + baz%.html'),
                          'file:///C:/foo/bar%20+%20baz%25.html')
 
     def test_stop_cygpath_subprocess(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info.py
similarity index 96%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info.py
index f2222f9..860fcd6 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info.py
@@ -118,7 +118,7 @@
                 packed = fcntl.ioctl(sys.stderr.fileno(), termios.TIOCGWINSZ, '\0' * 8)
                 _, columns, _, _ = struct.unpack('HHHH', packed)
                 return columns
-        except:
+        except Exception:  # pylint: disable=broad-except
             return sys.maxsize
 
     def linux_distribution(self):
@@ -171,9 +171,10 @@
             return 'vista'
         if win_version_tuple[:2] == (5, 1):
             return 'xp'
-        assert (win_version_tuple[0] > 10 or
-                win_version_tuple[0] == 10 and win_version_tuple[1] > 0), (
-            'Unrecognized Windows version tuple: "%s"' % (win_version_tuple,))
+        assert (
+            win_version_tuple[0] > 10 or
+            win_version_tuple[0] == 10 and win_version_tuple[1] > 0), (
+                'Unrecognized Windows version tuple: "%s"' % (win_version_tuple,))
         return 'future'
 
     def _win_version_tuple(self, sys_module):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info_mock.py
similarity index 100%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info_mock.py
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info_unittest.py
similarity index 98%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info_unittest.py
index 3da6a4b..a6f6fb99 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platforminfo_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/platform_info_unittest.py
@@ -34,7 +34,7 @@
 from webkitpy.common.system.executive_mock import MockExecutive2
 from webkitpy.common.system.filesystem import FileSystem
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.platforminfo import PlatformInfo
+from webkitpy.common.system.platform_info import PlatformInfo
 
 
 def fake_sys(platform_str='darwin', windows_version_tuple=None):
@@ -176,8 +176,8 @@
         self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('6.0.1234')).os_version, 'vista')
         self.assertEqual(self.make_info(fake_sys('cygwin'), executive=fake_executive('5.1.1234')).os_version, 'xp')
 
-    def _assert_file_implies_linux_distribution(self, file, distribution):
-        info = self.make_info(sys_module=fake_sys('linux2'), filesystem_module=MockFileSystem({file: ''}))
+    def _assert_file_implies_linux_distribution(self, file_path, distribution):
+        info = self.make_info(sys_module=fake_sys('linux2'), filesystem_module=MockFileSystem({file_path: ''}))
         self.assertEqual(info.linux_distribution(), distribution)
 
     def test_linux_distro_detection(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/profiler_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/profiler_unittest.py
index e48d18e2..441cd98e 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/profiler_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/profiler_unittest.py
@@ -28,8 +28,8 @@
 
 import unittest
 
-from webkitpy.common.system.platforminfo_mock import MockPlatformInfo
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.platform_info_mock import MockPlatformInfo
+from webkitpy.common.system.system_host_mock import MockSystemHost
 
 from .profiler import ProfilerFactory, GooglePProf
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host.py
similarity index 94%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host.py
index 0f92c76e..9e36c28 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host.py
@@ -31,7 +31,7 @@
 import sys
 import time
 
-from webkitpy.common.system import executive, filesystem, platforminfo, user, workspace
+from webkitpy.common.system import executive, filesystem, platform_info, user, workspace
 
 
 class SystemHost(object):
@@ -41,7 +41,7 @@
         self.executive = executive.Executive()
         self.filesystem = filesystem.FileSystem()
         self.user = user.User()
-        self.platform = platforminfo.PlatformInfo(sys, platform, self.filesystem, self.executive)
+        self.platform = platform_info.PlatformInfo(sys, platform, self.filesystem, self.executive)
         self.workspace = workspace.Workspace(self.filesystem, self.executive)
         self.stdin = sys.stdin
         self.stdout = sys.stdout
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host_mock.py
similarity index 97%
rename from third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost_mock.py
rename to third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host_mock.py
index e744eddf..1bff4c6 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/systemhost_mock.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/system_host_mock.py
@@ -30,7 +30,7 @@
 
 from webkitpy.common.system.executive_mock import MockExecutive
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.platforminfo_mock import MockPlatformInfo
+from webkitpy.common.system.platform_info_mock import MockPlatformInfo
 from webkitpy.common.system.user_mock import MockUser
 from webkitpy.common.system.workspace_mock import MockWorkspace
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user.py
index f9631e9..1aa23fd 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user.py
@@ -38,7 +38,7 @@
 
 from webkitpy.common.system.executive import Executive
 from webkitpy.common.system.filesystem import FileSystem
-from webkitpy.common.system.platforminfo import PlatformInfo
+from webkitpy.common.system.platform_info import PlatformInfo
 
 
 _log = logging.getLogger(__name__)
@@ -48,10 +48,10 @@
     DEFAULT_NO = 'n'
     DEFAULT_YES = 'y'
 
-    def __init__(self, platforminfo=None):
+    def __init__(self, platform_info=None):
         # We cannot get the PlatformInfo object from a SystemHost because
         # User is part of SystemHost itself.
-        self._platforminfo = platforminfo or PlatformInfo(sys, platform, FileSystem(), Executive())
+        self._platform_info = platform_info or PlatformInfo(sys, platform, FileSystem(), Executive())
 
     # FIXME: These are @classmethods because bugzilla.py doesn't have a Tool object (thus no User instance).
     @classmethod
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user_unittest.py
index 819a478..c984887c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/user_unittest.py
@@ -28,7 +28,7 @@
 
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.common.system.user import User
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/workspace_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/workspace_unittest.py
index 253a54e..517d12b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/workspace_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/workspace_unittest.py
@@ -29,7 +29,7 @@
 import unittest
 
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.common.system.workspace import Workspace
 from webkitpy.common.system.executive_mock import MockExecutive
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main.py b/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main.py
index 6452a9e..d0dac2d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main.py
@@ -5,7 +5,7 @@
 import argparse
 import lib2to3.refactor
 
-from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.system.system_host import SystemHost
 from webkitpy.thirdparty import autopep8
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main_unittest.py
index 963aedf..aab5128 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/formatter/main_unittest.py
@@ -5,7 +5,7 @@
 import StringIO
 import unittest
 
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.formatter.main import main
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner_unittest.py
index bdf66f6..529a23b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/layout_test_runner_unittest.py
@@ -30,7 +30,7 @@
 import unittest
 
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests import run_webkit_tests
 from webkitpy.layout_tests.controllers.layout_test_runner import LayoutTestRunner, Sharder, TestRunInterruptedException
 from webkitpy.layout_tests.models import test_expectations
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer_unittest.py
index 0edf238a9..1fdb9f1 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer_unittest.py
@@ -30,7 +30,7 @@
 import unittest
 
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.controllers.test_result_writer import baseline_name
 from webkitpy.layout_tests.controllers.test_result_writer import write_test_result
 from webkitpy.layout_tests.port.driver import DriverOutput
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
index 0b39dea6..2cf04c6 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
@@ -986,7 +986,7 @@
         return set(suffixes)
 
     @staticmethod
-    # test_result is an instance of webkitpy.common.net.layouttestresults.LayoutTestResult
+    # test_result is an instance of webkitpy.common.net.layout_test_results.LayoutTestResult
     def suffixes_for_test_result(test_result):
         suffixes = set()
         actual_results = test_result.actual_results()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
index 3d8f977..c8aea18 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
@@ -30,7 +30,7 @@
 import unittest
 
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.layout_tests.models.test_configuration import TestConfiguration, TestConfigurationConverter
 from webkitpy.layout_tests.models.test_expectations import (
     TestExpectationLine, TestExpectations, ParseError, TestExpectationParser,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
index 187890bf..f4eb155c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
@@ -35,7 +35,7 @@
 import unittest
 
 from webkitpy.common.system.executive_mock import MockExecutive2
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.port import android
 from webkitpy.layout_tests.port import driver_unittest
 from webkitpy.layout_tests.port import port_testcase
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index c508704..9dcb679 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -35,11 +35,11 @@
 from webkitpy.common.system.executive import ScriptError
 from webkitpy.common.system import executive_mock
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.platforminfo_mock import MockPlatformInfo
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.platform_info_mock import MockPlatformInfo
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.common.system.executive_mock import MockExecutive2
-from webkitpy.common.system.systemhost import SystemHost
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host import SystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 
 from webkitpy.layout_tests.port.base import Port, VirtualTestSuite
 from webkitpy.layout_tests.models.test_expectations import TestExpectations
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
index f600368..7d335b3 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
@@ -29,7 +29,7 @@
 import optparse
 import unittest
 
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.port.base import Port
 from webkitpy.layout_tests.port.driver import Driver
 from webkitpy.layout_tests.port.server_process_mock import MockServerProcess
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
index 9a29394c..27af7b5 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
@@ -29,7 +29,7 @@
 import optparse
 
 from webkitpy.common.system import executive_mock
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.port import linux
 from webkitpy.layout_tests.port import port_testcase
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
index d618483..b668097 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py
@@ -48,7 +48,7 @@
     sys.path.append(script_dir)
 
 from webkitpy.common import read_checksum_from_png
-from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.system.system_host import SystemHost
 from webkitpy.layout_tests.models import test_run_results
 from webkitpy.layout_tests.port.driver import DriverInput, DriverOutput
 from webkitpy.layout_tests.port.factory import PortFactory
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
index 225c577..bc144f0 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
@@ -32,7 +32,7 @@
 import optparse
 import unittest
 
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.port import mock_drt
 from webkitpy.layout_tests.port import port_testcase
 from webkitpy.layout_tests.port import test
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
index 5cbd3e1..cab72ad7 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -35,9 +35,9 @@
 import unittest
 
 from webkitpy.common.system.executive_mock import MockExecutive, MockExecutive2
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.common.system.systemhost import SystemHost
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.output_capture import OutputCapture
+from webkitpy.common.system.system_host import SystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.models import test_run_results
 from webkitpy.layout_tests.port.base import Port
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
index 9e4ca78..9767eb1 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process.py
@@ -95,7 +95,7 @@
         self._reset()
 
         # See comment in imports for why we need the win32 APIs and can't just use select.
-        # FIXME: there should be a way to get win32 vs. cygwin from platforminfo.
+        # FIXME: there should be a way to get win32 vs. cygwin from platform_info.
         self._use_win32_apis = sys.platform == 'win32'
 
     def name(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
index a6e0041..3e69c34 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
@@ -30,8 +30,8 @@
 import time
 import unittest
 
-from webkitpy.common.system.systemhost import SystemHost
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host import SystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.layout_tests.port import server_process
 from webkitpy.layout_tests.port.factory import PortFactory
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py
index b8926cc..4eecdab 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/test.py
@@ -29,7 +29,7 @@
 import base64
 import time
 
-from webkitpy.common.system.crashlogs import CrashLogs
+from webkitpy.common.system.crash_logs import CrashLogs
 from webkitpy.layout_tests.models import test_run_results
 from webkitpy.layout_tests.models.test_configuration import TestConfiguration
 from webkitpy.layout_tests.port.base import Port, VirtualTestSuite
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
index 081ef3f..bbd8205 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
@@ -28,7 +28,7 @@
 
 import optparse
 
-from webkitpy.common.system import outputcapture
+from webkitpy.common.system import output_capture
 from webkitpy.common.system.executive_mock import MockExecutive
 from webkitpy.layout_tests.port import port_testcase
 from webkitpy.layout_tests.port import win
@@ -44,7 +44,7 @@
     def test_setup_environ_for_server(self):
         port = self.make_port()
         port._executive = MockExecutive(should_log=True)
-        output = outputcapture.OutputCapture()
+        output = output_capture.OutputCapture()
         orig_environ = port.host.environ.copy()
         env = output.assert_outputs(self, port.setup_environ_for_server)
         self.assertEqual(orig_environ["PATH"], port.host.environ.get("PATH"))
@@ -59,7 +59,7 @@
         port = self.make_port(options=optparse.Values({'register_cygwin': True, 'results_directory': '/'}))
         port._executive = MockExecutive(should_log=True)
         expected_logs = "MOCK run_command: ['/mock-checkout/third_party/cygwin/setup_mount.bat'], cwd=None\n"
-        output = outputcapture.OutputCapture()
+        output = output_capture.OutputCapture()
         output.assert_outputs(self, port.setup_environ_for_server, expected_logs=expected_logs)
 
     def assert_name(self, port_name, os_version_string, expected):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
index 6d1008b0..db7cde5 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -36,8 +36,8 @@
 
 from webkitpy.common.host import Host
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system import outputcapture, path
-from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.system import output_capture, path
+from webkitpy.common.system.system_host import SystemHost
 
 from webkitpy.layout_tests import run_webkit_tests
 from webkitpy.layout_tests.models import test_expectations
@@ -97,7 +97,7 @@
 def run_and_capture(port_obj, options, parsed_args, shared_port=True):
     if shared_port:
         port_obj.host.port_factory.get = lambda *args, **kwargs: port_obj
-    oc = outputcapture.OutputCapture()
+    oc = output_capture.OutputCapture()
     try:
         oc.capture_output()
         logging_stream = StringIO.StringIO()
@@ -135,7 +135,7 @@
     host = host or MockHost()
     port_obj = port_obj or host.port_factory.get(port_name=options.platform, options=options)
 
-    oc = outputcapture.OutputCapture()
+    oc = output_capture.OutputCapture()
     oc.capture_output()
     logging_stream = StringIO.StringIO()
     stdout = StringIO.StringIO()
@@ -999,7 +999,7 @@
         # When we actually run multiple processes, we may have to reconfigure logging in the
         # child process (e.g., on win32) and we need to make sure that works and we still
         # see the verbose log output. However, we can't use logging_run() because using
-        # outputcapture to capture stdout and stderr latter results in a nonpicklable host.
+        # output_capture to capture stdout and stderr latter results in a nonpicklable host.
 
         # Test is flaky on Windows: https://bugs.webkit.org/show_bug.cgi?id=98559
         if not self.should_test_processes:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_unittest.py
index 18e58fb..2422a83 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http_unittest.py
@@ -30,7 +30,7 @@
 import unittest
 
 from webkitpy.common.system.executive_mock import MockExecutive
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.common.host_mock import MockHost
 from webkitpy.layout_tests.port import test
 from webkitpy.layout_tests.servers.apache_http import ApacheHTTP
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
index 2575359..58559780 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/update_test_expectations_unittest.py
@@ -8,7 +8,7 @@
 
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.logtesting import LoggingTestCase, LogTesting
+from webkitpy.common.system.log_testing import LoggingTestCase, LogTesting
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.layout_tests.port.factory import PortFactory
 from webkitpy.layout_tests.port.test import LAYOUT_TEST_DIR
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py
index 068eed30..9f7c398 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/views/buildbot_results.py
@@ -30,7 +30,7 @@
 from webkitpy.layout_tests.models import test_expectations
 from webkitpy.layout_tests.models.test_expectations import TestExpectations, TestExpectationLine
 
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 
 
 class BuildBotPrinter(object):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest_unittest.py
index ec5db3d1..d02afcb 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest_unittest.py
@@ -29,7 +29,7 @@
 import unittest
 
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.layout_tests.port.driver import DriverOutput
 from webkitpy.layout_tests.port.test import TestPort
 from webkitpy.performance_tests.perftest import ChromiumStylePerfTest
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
index ec629b8..cd3a649 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py
@@ -35,7 +35,7 @@
 import unittest
 
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.layout_tests.port.driver import DriverOutput
 from webkitpy.layout_tests.port.test import TestPort
 from webkitpy.performance_tests.perftest import ChromiumStylePerfTest
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
index 4c70db5..7be0a5a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
@@ -49,7 +49,7 @@
 from filter import FilterConfiguration
 from optparser import ArgumentParser
 from optparser import DefaultCommandOptionValues
-from webkitpy.common.system.logutils import configure_logging as _configure_logging
+from webkitpy.common.system.log_utils import configure_logging as _configure_logging
 
 
 _log = logging.getLogger(__name__)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker_unittest.py
index aed5803..44b2d3b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker_unittest.py
@@ -37,8 +37,8 @@
 import os
 import unittest
 
-from webkitpy.common.system.logtesting import LoggingTestCase
-from webkitpy.common.system.logtesting import TestLogStream
+from webkitpy.common.system.log_testing import LoggingTestCase
+from webkitpy.common.system.log_testing import TestLogStream
 from webkitpy.style import checker as style
 from webkitpy.style.checker import _all_categories
 from webkitpy.style.checker import _BASE_FILTER_RULES
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
index 9b9d624..dc254766 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/jsonchecker.py
@@ -31,15 +31,15 @@
 
     categories = set(('json/syntax',))
 
-    def __init__(self, file_path, handle_style_error):
+    def __init__(self, _, handle_style_error):
         self._handle_style_error = handle_style_error
         self._handle_style_error.turn_off_line_filtering()
 
     def check(self, lines):
         try:
             json.loads('\n'.join(lines) + '\n')
-        except ValueError as e:
-            self._handle_style_error(self.line_number_from_json_exception(e), 'json/syntax', 5, str(e))
+        except ValueError as error:
+            self._handle_style_error(self.line_number_from_json_exception(error), 'json/syntax', 5, str(error))
 
     @staticmethod
     def line_number_from_json_exception(error):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png.py
index 04424b3..4a27d33a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png.py
@@ -24,7 +24,7 @@
 """Supports checking WebKit style in png files."""
 
 from webkitpy.common import read_checksum_from_png
-from webkitpy.common.system.systemhost import SystemHost
+from webkitpy.common.system.system_host import SystemHost
 
 
 class PNGChecker(object):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png_unittest.py
index 89f78c3d..636df7d7 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/png_unittest.py
@@ -27,7 +27,7 @@
 
 from png import PNGChecker
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 
 
 class PNGCheckerTest(unittest.TestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/filereader_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/filereader_unittest.py
index 025ea70..800ee1ec 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/filereader_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/filereader_unittest.py
@@ -22,7 +22,7 @@
 
 
 from webkitpy.common.system.filesystem import FileSystem
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 from webkitpy.style.checker import ProcessorBase
 from webkitpy.style.filereader import TextFileReader
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/main_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/main_unittest.py
index a57e845..84a4a90 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/main_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/main_unittest.py
@@ -22,7 +22,7 @@
 
 from main import change_directory
 from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 
 
 class ChangeDirectoryTest(LoggingTestCase):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/optparser_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/optparser_unittest.py
index c457ae5..79798c4 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/optparser_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/optparser_unittest.py
@@ -24,7 +24,7 @@
 
 import unittest
 
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 from webkitpy.style.optparser import ArgumentParser
 from webkitpy.style.optparser import ArgumentPrinter
 from webkitpy.style.optparser import CommandOptionValues as ProcessorOptions
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines.py
index bd1a505..eac4877 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines.py
@@ -29,7 +29,7 @@
 import logging
 import optparse
 
-from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer
+from webkitpy.common.checkout.baseline_optimizer import BaselineOptimizer
 from webkitpy.layout_tests.controllers.test_result_writer import baseline_name
 from webkitpy.tool.commands.rebaseline import AbstractRebaseliningCommand
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
index 16487fd..e88ca14 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
@@ -4,7 +4,7 @@
 
 import optparse
 
-from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer
+from webkitpy.common.checkout.baseline_optimizer import BaselineOptimizer
 from webkitpy.tool.commands.analyze_baselines import AnalyzeBaselines
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
index ebcb694..ef4dcda0 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
@@ -5,7 +5,7 @@
 import optparse
 
 from webkitpy.common.net.buildbot import Build
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 from webkitpy.common.system.executive_mock import MockExecutive
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.tool.commands.auto_rebaseline import AutoRebaseline
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
index c608dac..134aa40 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
@@ -29,7 +29,7 @@
 import optparse
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.tool.mock_tool import MockWebKitPatch
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_unittest.py
index 1445210e..21d0731 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_unittest.py
@@ -29,7 +29,7 @@
 import optparse
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.tool.commands.command import Command
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines.py
index 249ac7b..04884f2 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines.py
@@ -4,7 +4,7 @@
 
 import logging
 
-from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer
+from webkitpy.common.checkout.baseline_optimizer import BaselineOptimizer
 from webkitpy.layout_tests.controllers.test_result_writer import baseline_name
 from webkitpy.tool.commands.rebaseline import AbstractRebaseliningCommand
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
index b1a443e..5fcdf8cd 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
@@ -4,7 +4,7 @@
 
 import optparse
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.tool.commands.optimize_baselines import OptimizeBaselines
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries.py
index 2983295..7b7fc87 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries.py
@@ -33,7 +33,7 @@
 
 from optparse import make_option
 
-from webkitpy.common.system.crashlogs import CrashLogs
+from webkitpy.common.system.crash_logs import CrashLogs
 from webkitpy.tool.commands.command import Command
 from webkitpy.layout_tests.models.test_expectations import TestExpectations
 from webkitpy.layout_tests.port.factory import platform_options
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
index d651a562..d60a56e 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
@@ -30,7 +30,7 @@
 import optparse
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.tool.commands.queries import PrintBaselines, PrintExpectations
 from webkitpy.tool.mock_tool import MockWebKitPatch
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py
index afb61286..a748e370 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl_unittest.py
@@ -7,10 +7,10 @@
 
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.git_cl import GitCL
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 from webkitpy.common.net.rietveld import Rietveld
 from webkitpy.common.net.web_mock import MockWeb
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.tool.commands.rebaseline_cl import RebaselineCL
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_server.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_server.py
index 177b87b..dd29430c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_server.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_server.py
@@ -32,7 +32,7 @@
 """
 
 from webkitpy.common.host import Host
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 from webkitpy.layout_tests.layout_package import json_results_generator
 from webkitpy.tool.commands.abstract_local_server_command import AbstractLocalServerCommand
 from webkitpy.tool.servers.rebaseline_server import get_test_baselines, RebaselineHTTPServer, STATE_NEEDS_REBASELINE
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
index 31830f7..496ab1d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -6,9 +6,9 @@
 import unittest
 
 from webkitpy.common.net.buildbot import Build
-from webkitpy.common.net.layouttestresults import LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResults
 from webkitpy.common.system.executive_mock import MockExecutive, MockExecutive2
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.tool.commands.rebaseline import (
     AbstractParallelRebaselineCommand, CopyExistingBaselinesInternal,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/servers/rebaseline_server_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/servers/rebaseline_server_unittest.py
index 2d92c00..d574ea8 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/servers/rebaseline_server_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/servers/rebaseline_server_unittest.py
@@ -29,7 +29,7 @@
 import json
 import unittest
 
-from webkitpy.common.net import layouttestresults_unittest
+from webkitpy.common.net import layout_test_results_unittest
 from webkitpy.common.host_mock import MockHost
 from webkitpy.layout_tests.layout_package.json_results_generator import strip_json_wrapper
 from webkitpy.layout_tests.port.base import Port
@@ -206,7 +206,7 @@
             ])
 
     def test_gather_baselines(self):
-        example_json = layouttestresults_unittest.LayoutTestResultsTest.example_full_results_json
+        example_json = layout_test_results_unittest.LayoutTestResultsTest.example_full_results_json
         results_json = json.loads(strip_json_wrapper(example_json))
         server = RebaselineServer()
         server._test_config = get_test_config()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/webkit_patch_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/webkit_patch_unittest.py
index b6c8db9e..ec891f5 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/webkit_patch_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/webkit_patch_unittest.py
@@ -4,7 +4,7 @@
 
 import unittest
 
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.tool.webkit_patch import WebKitPatch
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_converter_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_converter_unittest.py
index ee52fd6..eab8350 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_converter_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_converter_unittest.py
@@ -29,10 +29,10 @@
 import unittest
 
 from webkitpy.common.host import Host
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.common.webkit_finder import WebKitFinder
 from webkitpy.w3c.test_converter import _W3CTestConverter, convert_for_webkit
-from webkitpy.common.system.systemhost_mock import MockSystemHost
+from webkitpy.common.system.system_host_mock import MockSystemHost
 from webkitpy.common.system.filesystem_mock import MockFileSystem
 
 DUMMY_FILENAME = 'dummy.html'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_parser_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_parser_unittest.py
index 04d9654..6f2e618 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_parser_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_parser_unittest.py
@@ -29,7 +29,7 @@
 import unittest
 
 from webkitpy.common.host_mock import MockHost
-from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.output_capture import OutputCapture
 from webkitpy.w3c.test_parser import TestParser
 
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
index 4d794cf..0d7ccc3 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
@@ -8,9 +8,9 @@
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.buildbot_mock import MockBuildBot
-from webkitpy.common.net.layouttestresults import LayoutTestResult, LayoutTestResults
+from webkitpy.common.net.layout_test_results import LayoutTestResult, LayoutTestResults
 from webkitpy.common.net.web_mock import MockWeb
-from webkitpy.common.system.logtesting import LoggingTestCase
+from webkitpy.common.system.log_testing import LoggingTestCase
 from webkitpy.common.system.executive_mock import MockExecutive2
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.w3c.update_w3c_test_expectations import W3CExpectationsLineAdder, MARKER_COMMENT
diff --git a/third_party/WebKit/public/platform/WebAudioDevice.h b/third_party/WebKit/public/platform/WebAudioDevice.h
index 6680cfb..1de0eba2 100644
--- a/third_party/WebKit/public/platform/WebAudioDevice.h
+++ b/third_party/WebKit/public/platform/WebAudioDevice.h
@@ -35,14 +35,21 @@
 namespace blink {
 
 // Abstract interface to the Chromium audio system.
-
 class WebAudioDevice {
  public:
   class BLINK_PLATFORM_EXPORT RenderCallback {
    public:
+    // Note: |delay| and |delayTimestamp| arguments are high-precision
+    // measurements of the state of the system in the recent past. To be clear,
+    // |delay| does *not* represent the point-in-time at which the first
+    // rendered sample will be played out.
     virtual void render(const WebVector<float*>& sourceData,
                         const WebVector<float*>& destinationData,
-                        size_t numberOfFrames);
+                        size_t numberOfFrames,
+                        double delay,           // Output delay in seconds.
+                        double delayTimestamp,  // System timestamp in seconds
+                                                // when |delay| was obtained.
+                        size_t priorFramesSkipped);
 
    protected:
     virtual ~RenderCallback();
diff --git a/third_party/WebKit/public/platform/WebInputEvent.h b/third_party/WebKit/public/platform/WebInputEvent.h
index 5074bed..9a732a8d 100644
--- a/third_party/WebKit/public/platform/WebInputEvent.h
+++ b/third_party/WebKit/public/platform/WebInputEvent.h
@@ -424,65 +424,6 @@
         clickCount(0) {}
 };
 
-// WebMouseWheelEvent ---------------------------------------------------------
-
-class WebMouseWheelEvent : public WebMouseEvent {
- public:
-  enum Phase {
-    PhaseNone = 0,
-    PhaseBegan = 1 << 0,
-    PhaseStationary = 1 << 1,
-    PhaseChanged = 1 << 2,
-    PhaseEnded = 1 << 3,
-    PhaseCancelled = 1 << 4,
-    PhaseMayBegin = 1 << 5,
-  };
-
-  float deltaX;
-  float deltaY;
-  float wheelTicksX;
-  float wheelTicksY;
-
-  float accelerationRatioX;
-  float accelerationRatioY;
-
-  // This field exists to allow BrowserPlugin to mark MouseWheel events as
-  // 'resent' to handle the case where an event is not consumed when first
-  // encountered; it should be handled differently by the plugin when it is
-  // sent for thesecond time. No code within Blink touches this, other than to
-  // plumb it through event conversions.
-  int resendingPluginId;
-
-  Phase phase;
-  Phase momentumPhase;
-
-  bool scrollByPage;
-  bool hasPreciseScrollingDeltas;
-
-  RailsMode railsMode;
-
-  // Whether the event is blocking, non-blocking, all event
-  // listeners were passive or was forced to be non-blocking.
-  DispatchType dispatchType;
-
-  WebMouseWheelEvent()
-      : WebMouseEvent(sizeof(WebMouseWheelEvent)),
-        deltaX(0.0f),
-        deltaY(0.0f),
-        wheelTicksX(0.0f),
-        wheelTicksY(0.0f),
-        accelerationRatioX(1.0f),
-        accelerationRatioY(1.0f),
-        resendingPluginId(-1),
-        phase(PhaseNone),
-        momentumPhase(PhaseNone),
-        scrollByPage(false),
-        hasPreciseScrollingDeltas(false),
-        railsMode(RailsModeFree),
-        dispatchType(Blocking) {}
-};
-
-
 // WebTouchEvent --------------------------------------------------------------
 
 // TODO(e_hakkinen): Replace with WebPointerEvent. crbug.com/508283
diff --git a/third_party/WebKit/public/platform/WebMouseWheelEvent.h b/third_party/WebKit/public/platform/WebMouseWheelEvent.h
new file mode 100644
index 0000000..da654f7d62
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebMouseWheelEvent.h
@@ -0,0 +1,76 @@
+// Copyright 2016 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 WebMouseWheelEvent_h
+#define WebMouseWheelEvent_h
+
+#include "WebInputEvent.h"
+
+namespace blink {
+
+// See WebInputEvent.h for details why this pack is here.
+#pragma pack(push, 4)
+
+// WebMouseWheelEvent ---------------------------------------------------------
+
+class WebMouseWheelEvent : public WebMouseEvent {
+ public:
+  enum Phase {
+    PhaseNone = 0,
+    PhaseBegan = 1 << 0,
+    PhaseStationary = 1 << 1,
+    PhaseChanged = 1 << 2,
+    PhaseEnded = 1 << 3,
+    PhaseCancelled = 1 << 4,
+    PhaseMayBegin = 1 << 5,
+  };
+
+  float deltaX;
+  float deltaY;
+  float wheelTicksX;
+  float wheelTicksY;
+
+  float accelerationRatioX;
+  float accelerationRatioY;
+
+  // This field exists to allow BrowserPlugin to mark MouseWheel events as
+  // 'resent' to handle the case where an event is not consumed when first
+  // encountered; it should be handled differently by the plugin when it is
+  // sent for thesecond time. No code within Blink touches this, other than to
+  // plumb it through event conversions.
+  int resendingPluginId;
+
+  Phase phase;
+  Phase momentumPhase;
+
+  bool scrollByPage;
+  bool hasPreciseScrollingDeltas;
+
+  RailsMode railsMode;
+
+  // Whether the event is blocking, non-blocking, all event
+  // listeners were passive or was forced to be non-blocking.
+  DispatchType dispatchType;
+
+  WebMouseWheelEvent()
+      : WebMouseEvent(sizeof(WebMouseWheelEvent)),
+        deltaX(0.0f),
+        deltaY(0.0f),
+        wheelTicksX(0.0f),
+        wheelTicksY(0.0f),
+        accelerationRatioX(1.0f),
+        accelerationRatioY(1.0f),
+        resendingPluginId(-1),
+        phase(PhaseNone),
+        momentumPhase(PhaseNone),
+        scrollByPage(false),
+        hasPreciseScrollingDeltas(false),
+        railsMode(RailsModeFree),
+        dispatchType(Blocking) {}
+};
+#pragma pack(pop)
+
+}  // namespace blink
+
+#endif  // WebMouseWheelEvent_h
diff --git a/tools/gn/action_values.cc b/tools/gn/action_values.cc
index a7ce83d..28c4a11e 100644
--- a/tools/gn/action_values.cc
+++ b/tools/gn/action_values.cc
@@ -22,7 +22,7 @@
       target->output_type() == Target::ACTION_FOREACH) {
     // Copy and foreach applies the outputs to the sources.
     SubstitutionWriter::ApplyListToSources(
-        target->settings(), outputs_, target->sources(), result);
+        target, target->settings(), outputs_, target->sources(), result);
   } else {
     // Actions (and anything else that happens to specify an output) just use
     // the output list with no substitution.
diff --git a/tools/gn/bundle_file_rule.cc b/tools/gn/bundle_file_rule.cc
index e23361fb..5c4fc27 100644
--- a/tools/gn/bundle_file_rule.cc
+++ b/tools/gn/bundle_file_rule.cc
@@ -46,7 +46,7 @@
         break;
       default:
         output_path.append(SubstitutionWriter::GetSourceSubstitution(
-            settings, source_file, subrange.type,
+            target_, target_->settings(), source_file, subrange.type,
             SubstitutionWriter::OUTPUT_ABSOLUTE, SourceDir()));
         break;
     }
diff --git a/tools/gn/desc_builder.cc b/tools/gn/desc_builder.cc
index 3e2aaa08..a1a5710 100644
--- a/tools/gn/desc_builder.cc
+++ b/tools/gn/desc_builder.cc
@@ -616,8 +616,9 @@
         res->SetWithoutPathExpansion("output_patterns", std::move(patterns));
       }
       std::vector<SourceFile> output_files;
-      SubstitutionWriter::ApplyListToSources(target_->settings(), outputs,
-                                             target_->sources(), &output_files);
+      SubstitutionWriter::ApplyListToSources(target_, target_->settings(),
+                                             outputs, target_->sources(),
+                                             &output_files);
       res->SetWithoutPathExpansion(variables::kOutputs,
                                    RenderValue(output_files));
     } else {
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index 1aa56f1d..26ba5c6 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -6584,6 +6584,13 @@
       build.gn file.
         "//foo/bar/baz.txt" => "obj/foo/bar"
 
+  {{source_target_relative}}\n"
+      The path to the source file relative to the target's directory. This will
+      generally be used for replicating the source directory layout in the
+      output directory. This can only be used in actions and it is an error to
+      use in process_file_template where there is no "target".
+        "//foo/bar/baz.txt" => "baz.txt"
+
 ```
 
 ### **(*) Note on directories**
diff --git a/tools/gn/function_process_file_template.cc b/tools/gn/function_process_file_template.cc
index 78889c98..28e3e46 100644
--- a/tools/gn/function_process_file_template.cc
+++ b/tools/gn/function_process_file_template.cc
@@ -93,8 +93,15 @@
     return Value();
   }
 
+  auto& types = subst.required_types();
+  if (std::find(types.begin(), types.end(),
+                SUBSTITUTION_SOURCE_TARGET_RELATIVE) != types.end()) {
+    *err = Err(template_arg, "Not a valid substitution type for the function.");
+    return Value();
+  }
+
   SubstitutionWriter::ApplyListToSourcesAsString(
-      scope->settings(), subst, input_files, &result_files);
+      nullptr, scope->settings(), subst, input_files, &result_files);
 
   // Convert the list of strings to the return Value.
   Value ret(function, Value::LIST);
diff --git a/tools/gn/ninja_action_target_writer.cc b/tools/gn/ninja_action_target_writer.cc
index 1743632..77ee2b4 100644
--- a/tools/gn/ninja_action_target_writer.cc
+++ b/tools/gn/ninja_action_target_writer.cc
@@ -184,11 +184,11 @@
     // very unusual (normally the substitutions will go in one place or the
     // other) and the redundant assignment won't bother Ninja.
     SubstitutionWriter::WriteNinjaVariablesForSource(
-        settings_, sources[i],
+        target_, settings_, sources[i],
         target_->action_values().args().required_types(),
         args_escape_options, out_);
     SubstitutionWriter::WriteNinjaVariablesForSource(
-        settings_, sources[i],
+        target_, settings_, sources[i],
         target_->action_values().rsp_file_contents().required_types(),
         args_escape_options, out_);
 
@@ -206,7 +206,8 @@
   size_t first_output_index = output_files->size();
 
   SubstitutionWriter::ApplyListToSourceAsOutputFile(
-      settings_, target_->action_values().outputs(), source, output_files);
+      target_, settings_, target_->action_values().outputs(), source,
+      output_files);
 
   for (size_t i = first_output_index; i < output_files->size(); i++) {
     out_ << " ";
@@ -217,5 +218,5 @@
 void NinjaActionTargetWriter::WriteDepfile(const SourceFile& source) {
   path_output_.WriteFile(out_,
       SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
-          settings_, target_->action_values().depfile(), source));
+          target_, settings_, target_->action_values().depfile(), source));
 }
diff --git a/tools/gn/ninja_copy_target_writer.cc b/tools/gn/ninja_copy_target_writer.cc
index b0313be..9ffd0fc 100644
--- a/tools/gn/ninja_copy_target_writer.cc
+++ b/tools/gn/ninja_copy_target_writer.cc
@@ -103,7 +103,7 @@
   for (const auto& input_file : target_->sources()) {
     OutputFile output_file =
         SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
-            target_->settings(), output_subst, input_file);
+            target_, target_->settings(), output_subst, input_file);
     output_files->push_back(output_file);
 
     out_ << "build ";
diff --git a/tools/gn/substitution_type.cc b/tools/gn/substitution_type.cc
index 7730070..c6ea3859 100644
--- a/tools/gn/substitution_type.cc
+++ b/tools/gn/substitution_type.cc
@@ -21,6 +21,7 @@
   "{{source_root_relative_dir}}",  // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
   "{{source_gen_dir}}",  // SUBSTITUTION_SOURCE_GEN_DIR
   "{{source_out_dir}}",  // SUBSTITUTION_SOURCE_OUT_DIR
+  "{{source_target_relative}}",  // SUBSTITUTION_SOURCE_TARGET_RELATIVE
 
   "{{label}}",  // SUBSTITUTION_LABEL
   "{{label_name}}",  // SUBSTITUTION_LABEL_NAME
@@ -70,6 +71,7 @@
     "source_root_relative_dir",  // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
     "source_gen_dir",            // SUBSTITUTION_SOURCE_GEN_DIR
     "source_out_dir",            // SUBSTITUTION_SOURCE_OUT_DIR
+    "source_target_relative",    // SUBSTITUTION_SOURCE_TARGET_RELATIVE
 
     "label",               // SUBSTITUTION_LABEL
     "label_name",          // SUBSTITUTION_LABEL_NAME
@@ -160,7 +162,8 @@
          type == SUBSTITUTION_SOURCE_DIR ||
          type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR ||
          type == SUBSTITUTION_SOURCE_GEN_DIR ||
-         type == SUBSTITUTION_SOURCE_OUT_DIR;
+         type == SUBSTITUTION_SOURCE_OUT_DIR ||
+         type == SUBSTITUTION_SOURCE_TARGET_RELATIVE;
 }
 
 bool IsValidToolSubstitution(SubstitutionType type) {
diff --git a/tools/gn/substitution_type.h b/tools/gn/substitution_type.h
index 84524fb..74ab507 100644
--- a/tools/gn/substitution_type.h
+++ b/tools/gn/substitution_type.h
@@ -30,6 +30,7 @@
   SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR,  // {{root_relative_dir}}
   SUBSTITUTION_SOURCE_GEN_DIR,  // {{source_gen_dir}}
   SUBSTITUTION_SOURCE_OUT_DIR,  // {{source_out_dir}}
+  SUBSTITUTION_SOURCE_TARGET_RELATIVE,  // {{source_target_relative}}
 
   // Valid for all compiler and linker tools. These depend on the target and
   // do not vary on a per-file basis.
diff --git a/tools/gn/substitution_writer.cc b/tools/gn/substitution_writer.cc
index 4d818cd..7a3534e 100644
--- a/tools/gn/substitution_writer.cc
+++ b/tools/gn/substitution_writer.cc
@@ -98,6 +98,13 @@
       build.gn file.
         "//foo/bar/baz.txt" => "obj/foo/bar"
 
+  {{source_target_relative}}\n"
+      The path to the source file relative to the target's directory. This will
+      generally be used for replicating the source directory layout in the
+      output directory. This can only be used in actions and it is an error to
+      use in process_file_template where there is no "target".
+        "//foo/bar/baz.txt" => "baz.txt"
+
 (*) Note on directories
 
   Paths containing directories (except the source_root_relative_dir) will be
@@ -196,11 +203,12 @@
 
 // static
 SourceFile SubstitutionWriter::ApplyPatternToSource(
+      const Target* target,
       const Settings* settings,
       const SubstitutionPattern& pattern,
       const SourceFile& source) {
   std::string result_value = ApplyPatternToSourceAsString(
-      settings, pattern, source);
+      target, settings, pattern, source);
   CHECK(!result_value.empty() && result_value[0] == '/')
       << "The result of the pattern \""
       << pattern.AsString()
@@ -210,6 +218,7 @@
 
 // static
 std::string SubstitutionWriter::ApplyPatternToSourceAsString(
+    const Target* target,
     const Settings* settings,
     const SubstitutionPattern& pattern,
     const SourceFile& source) {
@@ -219,7 +228,7 @@
       result_value.append(subrange.literal);
     } else {
       result_value.append(
-          GetSourceSubstitution(settings, source, subrange.type,
+          GetSourceSubstitution(target, settings, source, subrange.type,
                                 OUTPUT_ABSOLUTE, SourceDir()));
     }
   }
@@ -228,78 +237,89 @@
 
 // static
 OutputFile SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
+    const Target* target,
     const Settings* settings,
     const SubstitutionPattern& pattern,
     const SourceFile& source) {
-  SourceFile result_as_source = ApplyPatternToSource(settings, pattern, source);
+  SourceFile result_as_source = ApplyPatternToSource(
+      target, settings, pattern, source);
   return OutputFile(settings->build_settings(), result_as_source);
 }
 
 // static
 void SubstitutionWriter::ApplyListToSource(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const SourceFile& source,
     std::vector<SourceFile>* output) {
   for (const auto& item : list.list())
-    output->push_back(ApplyPatternToSource(settings, item, source));
+    output->push_back(ApplyPatternToSource(target, settings, item, source));
 }
 
 // static
 void SubstitutionWriter::ApplyListToSourceAsString(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const SourceFile& source,
     std::vector<std::string>* output) {
   for (const auto& item : list.list())
-    output->push_back(ApplyPatternToSourceAsString(settings, item, source));
+    output->push_back(ApplyPatternToSourceAsString(
+        target, settings, item, source));
 }
 
 // static
 void SubstitutionWriter::ApplyListToSourceAsOutputFile(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const SourceFile& source,
     std::vector<OutputFile>* output) {
   for (const auto& item : list.list())
-    output->push_back(ApplyPatternToSourceAsOutputFile(settings, item, source));
+    output->push_back(ApplyPatternToSourceAsOutputFile(
+        target, settings, item, source));
 }
 
 // static
 void SubstitutionWriter::ApplyListToSources(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const std::vector<SourceFile>& sources,
     std::vector<SourceFile>* output) {
   output->clear();
   for (const auto& source : sources)
-    ApplyListToSource(settings, list, source, output);
+    ApplyListToSource(target, settings, list, source, output);
 }
 
 // static
 void SubstitutionWriter::ApplyListToSourcesAsString(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const std::vector<SourceFile>& sources,
     std::vector<std::string>* output) {
   output->clear();
   for (const auto& source : sources)
-    ApplyListToSourceAsString(settings, list, source, output);
+    ApplyListToSourceAsString(target, settings, list, source, output);
 }
 
 // static
 void SubstitutionWriter::ApplyListToSourcesAsOutputFile(
+    const Target* target,
     const Settings* settings,
     const SubstitutionList& list,
     const std::vector<SourceFile>& sources,
     std::vector<OutputFile>* output) {
   output->clear();
   for (const auto& source : sources)
-    ApplyListToSourceAsOutputFile(settings, list, source, output);
+    ApplyListToSourceAsOutputFile(target, settings, list, source, output);
 }
 
 // static
 void SubstitutionWriter::WriteNinjaVariablesForSource(
+    const Target* target,
     const Settings* settings,
     const SourceFile& source,
     const std::vector<SubstitutionType>& types,
@@ -314,7 +334,8 @@
       out << "  " << kSubstitutionNinjaNames[type] << " = ";
         EscapeStringToStream(
             out,
-            GetSourceSubstitution(settings, source, type, OUTPUT_RELATIVE,
+            GetSourceSubstitution(target, settings, source, type,
+                                  OUTPUT_RELATIVE,
                                   settings->build_settings()->build_dir()),
             escape_options);
       out << std::endl;
@@ -324,6 +345,7 @@
 
 // static
 std::string SubstitutionWriter::GetSourceSubstitution(
+    const Target* target,
     const Settings* settings,
     const SourceFile& source,
     SubstitutionType type,
@@ -366,6 +388,16 @@
           BuildDirContext(settings), source.GetDir(), BuildDirType::OBJ));
       break;
 
+    case SUBSTITUTION_SOURCE_TARGET_RELATIVE:
+      if (target) {
+        return RebasePath(source.value(), target->label().dir(),
+            settings->build_settings()->root_path_utf8());
+      }
+      NOTREACHED()
+          << "Cannot use substitution " << kSubstitutionNames[type]
+          << " without target";
+      return std::string();
+
     default:
       NOTREACHED()
           << "Unsupported substitution for this function: "
@@ -502,7 +534,7 @@
 
   // Fall-through to the source ones.
   return GetSourceSubstitution(
-      target->settings(), source, type, OUTPUT_RELATIVE,
+      target, target->settings(), source, type, OUTPUT_RELATIVE,
       target->settings()->build_settings()->build_dir());
 }
 
diff --git a/tools/gn/substitution_writer.h b/tools/gn/substitution_writer.h
index a450bbb..92f09c4 100644
--- a/tools/gn/substitution_writer.h
+++ b/tools/gn/substitution_writer.h
@@ -46,6 +46,10 @@
 // The compiler and linker specific substitutions do NOT include the various
 // cflags, ldflags, libraries, etc. These are written by the ninja target
 // writer since they depend on traversing the dependency tree.
+//
+// The methods which take a target as an argument can accept null target
+// pointer if there is no target context, in which case the substitutions
+// requiring target context will not work.
 class SubstitutionWriter {
  public:
   enum OutputStyle {
@@ -81,15 +85,20 @@
   // expected to be a SourceFile or an OutputFile, this will CHECK if the
   // result isn't in the correct directory. The caller should validate this
   // first (see for example IsFileInOuputDir).
+  //
+  // The target can be null (see class comment above).
   static SourceFile ApplyPatternToSource(
+      const Target* target,
       const Settings* settings,
       const SubstitutionPattern& pattern,
       const SourceFile& source);
   static std::string ApplyPatternToSourceAsString(
+      const Target* target,
       const Settings* settings,
       const SubstitutionPattern& pattern,
       const SourceFile& source);
   static OutputFile ApplyPatternToSourceAsOutputFile(
+      const Target* target,
       const Settings* settings,
       const SubstitutionPattern& pattern,
       const SourceFile& source);
@@ -98,17 +107,22 @@
   // given output vector. It works this way so one can call multiple times to
   // apply to multiple files and create a list. The result can either be
   // SourceFiles or OutputFiles.
+  //
+  // The target can be null (see class comment above).
   static void ApplyListToSource(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const SourceFile& source,
       std::vector<SourceFile>* output);
   static void ApplyListToSourceAsString(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const SourceFile& source,
       std::vector<std::string>* output);
   static void ApplyListToSourceAsOutputFile(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const SourceFile& source,
@@ -116,17 +130,22 @@
 
   // Like ApplyListToSource but applies the list to all sources and replaces
   // rather than appends the output (this produces the complete output).
+  //
+  // The target can be null (see class comment above).
   static void ApplyListToSources(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const std::vector<SourceFile>& sources,
       std::vector<SourceFile>* output);
   static void ApplyListToSourcesAsString(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const std::vector<SourceFile>& sources,
       std::vector<std::string>* output);
   static void ApplyListToSourcesAsOutputFile(
+      const Target* target,
       const Settings* settings,
       const SubstitutionList& list,
       const std::vector<SourceFile>& sources,
@@ -138,7 +157,10 @@
   // Ninja files, paths will be relative to the build dir, and no definition
   // for {{source}} will be written since that maps to Ninja's implicit $in
   // variable.
+  //
+  // The target can be null (see class comment above).
   static void WriteNinjaVariablesForSource(
+      const Target* target,
       const Settings* settings,
       const SourceFile& source,
       const std::vector<SubstitutionType>& types,
@@ -149,7 +171,10 @@
   // given source file. If output_style is OUTPUT_RELATIVE, relative_to
   // indicates the directory that the relative directories should be relative
   // to, otherwise it is ignored.
+  //
+  // The target can be null (see class comment above).
   static std::string GetSourceSubstitution(
+      const Target* target,
       const Settings* settings,
       const SourceFile& source,
       SubstitutionType type,
diff --git a/tools/gn/substitution_writer_unittest.cc b/tools/gn/substitution_writer_unittest.cc
index d252c79f..d98d4cee 100644
--- a/tools/gn/substitution_writer_unittest.cc
+++ b/tools/gn/substitution_writer_unittest.cc
@@ -43,7 +43,7 @@
                             nullptr, &err));
 
   SourceFile result = SubstitutionWriter::ApplyPatternToSource(
-      setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
+      nullptr, setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
   ASSERT_EQ("//out/Debug/gen/foo/bar/myfile.tmp", result.value());
 }
 
@@ -56,7 +56,7 @@
                             nullptr, &err));
 
   OutputFile result = SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
-      setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
+      nullptr, setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
   ASSERT_EQ("gen/foo/bar/myfile.tmp", result.value());
 }
 
@@ -73,7 +73,8 @@
 
   std::ostringstream out;
   SubstitutionWriter::WriteNinjaVariablesForSource(
-      setup.settings(), SourceFile("//foo/bar/baz.txt"), types, options, out);
+      nullptr, setup.settings(), SourceFile("//foo/bar/baz.txt"), types,
+      options, out);
 
   // The "source" should be skipped since that will expand to $in which is
   // implicit.
@@ -103,10 +104,17 @@
 
 TEST(SubstitutionWriter, SourceSubstitutions) {
   TestWithScope setup;
+  Err err;
+
+  Target target(setup.settings(), Label(SourceDir("//foo/bar/"), "baz"));
+  target.set_output_type(Target::STATIC_LIBRARY);
+  target.SetToolchain(setup.toolchain());
+  ASSERT_TRUE(target.OnResolved(&err));
 
   // Call to get substitutions relative to the build dir.
   #define GetRelSubst(str, what) \
       SubstitutionWriter::GetSourceSubstitution( \
+          &target, \
           setup.settings(), \
           SourceFile(str), \
           what, \
@@ -116,6 +124,7 @@
   // Call to get absolute directory substitutions.
   #define GetAbsSubst(str, what) \
       SubstitutionWriter::GetSourceSubstitution( \
+          &target, \
           setup.settings(), \
           SourceFile(str), \
           what, \
@@ -175,6 +184,11 @@
   EXPECT_EQ(".",
             GetRelSubst("//baz.txt", SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR));
 
+  EXPECT_EQ("baz.txt",
+      GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_TARGET_RELATIVE));
+  EXPECT_EQ("baz.txt",
+      GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_TARGET_RELATIVE));
+
   #undef GetAbsSubst
   #undef GetRelSubst
 }
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 59b820ad..edbb434 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -1060,14 +1060,14 @@
 
     android = 'target_os="android"' in vals['gn_args']
     ozone = 'use_ozone=true' in vals['gn_args']
-    ozone_x11 = (ozone and 'args' in isolate_map[target] and
-                 '--ozone-platform=x11' in isolate_map[target]['args'])
+    chromeos = 'target_os="chromeos"' in vals['gn_args']
 
-    # This needs to mirror the settings in //build/config/ui.gni:
-    # use_x11 = is_linux && !use_ozone || use_ozone && --ozone-platform=x11
-    use_x11 = (self.platform == 'linux2' and
+    # This should be true if tests with type='windowed_test_launcher' are
+    # expected to run using xvfb. For example, Linux Desktop, X11 CrOS and
+    # Ozone CrOS builds.
+    use_xvfb = (self.platform == 'linux2' and
                not android and
-               (ozone_x11 or not ozone))
+               ((not ozone) or (ozone and chromeos)))
 
     asan = 'is_asan=true' in vals['gn_args']
     msan = 'is_msan=true' in vals['gn_args']
@@ -1103,7 +1103,7 @@
       ]
       cmdline = (['./../../build/android/test_wrapper/logdog_wrapper.py']
                  + logdog_command + test_cmdline)
-    elif use_x11 and test_type == 'windowed_test_launcher':
+    elif use_xvfb and test_type == 'windowed_test_launcher':
       extra_files = [
           '../../testing/test_env.py',
           '../../testing/xvfb.py',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 13986b5..b531867 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -494,8 +494,11 @@
       # shared library loading is fixed.
       'android_cronet_tester': 'android_cronet_debug_static_bot_arm_no_neon',
 
+      'android_n5x_swarming_dbg': 'android_debug_trybot_arm64',
       'android_n5x_swarming_rel': 'android_release_trybot_arm64',
       'android_optional_gpu_tests_rel': 'gpu_tests_deqp_android_release_trybot_arm64',
+      'android_unswarmed_n5_rel': 'android_release_trybot',
+      'android_unswarmed_n5x_rel': 'android_release_trybot_arm64',
       'cast_shell_android': 'android_cast_debug_static_bot',
       'linux_android_dbg_ng': 'android_debug_trybot',
       'linux_android_rel_ng': 'android_release_trybot',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index cb45ed01d..ce86f478 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1373,6 +1373,16 @@
   <summary>Arc OptIn cancelation reason.</summary>
 </histogram>
 
+<histogram name="Arc.OptInSilentAuthCode" enum="ArcOptInSilentAuthCode">
+  <owner>elijahtaylor@google.com</owner>
+  <summary>
+    Arc Silent Auth Code status. This status is set during the ARC OptIn flow.
+    Retrieving Auth Code silently is optional feature. If it is not activated,
+    Disabled state is reported. Once it active, Auth code is retrieved silently.
+    In no error occurs, Success is reported. Otherwise specific error is sent.
+  </summary>
+</histogram>
+
 <histogram name="Arc.Provisioning.Result" enum="ArcProvisioningResult">
   <obsolete>
     Deprecated on 2016-09-15 and replaced by Arc.Provisioning.Result.Managed and
@@ -76280,6 +76290,19 @@
   <int value="7" label="Android Management required"/>
 </enum>
 
+<enum name="ArcOptInSilentAuthCode" type="int">
+  <summary>Defines Arc OptIn Silent Auth code state</summary>
+  <int value="0" label="Disabled"/>
+  <int value="1" label="Success"/>
+  <int value="2" label="HTTP Context cannot be prepared"/>
+  <int value="3" label="No LST token is available"/>
+  <int value="4" label="Failed due sever HTTP error"/>
+  <int value="5" label="Failed due client HTTP error"/>
+  <int value="6" label="Failed due unknown HTTP error"/>
+  <int value="7" label="Cannot parse HTTP response"/>
+  <int value="8" label="No Auth code in response"/>
+</enum>
+
 <enum name="ArcProvisioningResult" type="int">
   <summary>Defines Arc Provisioning success and failure reasons</summary>
   <int value="0" label="Success"/>
@@ -76777,6 +76800,8 @@
   <int value="18"
       label="About to be submitted with masked server card suggestion filled
              (once)"/>
+  <int value="19" label="Submitted with suggestion shown (once)"/>
+  <int value="20" label="About to be submitted with suggestion shown (once)"/>
 </enum>
 
 <enum name="AutofillFormSubmittedState" type="int">
@@ -93663,6 +93688,7 @@
   <int value="-13918890" label="disable-download-notification"/>
   <int value="-11260186" label="enable-offline-pages-as-saved-pages"/>
   <int value="-5052940" label="enable-simplified-fullscreen"/>
+  <int value="-2953333" label="AndroidHistoryManager:disabled"/>
   <int value="-2371418" label="disable-display-list-2d-canvas"/>
   <int value="0" label="BAD_FLAG_FORMAT">
     Command-line flag doesn't start with two dashes.
@@ -93820,6 +93846,7 @@
   <int value="773919225" label="disable-office-editing-component-extension"/>
   <int value="779086132" label="enable-data-reduction-proxy-alt"/>
   <int value="782167080" label="enable-new-qp-input-view"/>
+  <int value="783270752" label="AndroidHistoryManager:enabled"/>
   <int value="803282885" label="PreferHtmlOverPlugins:disabled"/>
   <int value="805567148"
       label="enable-canvas-2d-dynamic-rendering-mode-switching"/>
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 0ba6220..2d2a535 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -169,11 +169,19 @@
 
       AXTreeDelegate::ChangeType change = AXTreeDelegate::NODE_CHANGED;
       if (is_new_node) {
-        bool is_subtree = new_nodes.find(node->parent()) == new_nodes.end();
         if (is_reparented_node) {
+          // A reparented subtree is any new node whose parent either doesn't
+          // exist, or is not new.
+          bool is_subtree = !node->parent() ||
+                            new_nodes.find(node->parent()) == new_nodes.end();
           change = is_subtree ? AXTreeDelegate::SUBTREE_REPARENTED
                               : AXTreeDelegate::NODE_REPARENTED;
         } else {
+          // A new subtree is any new node whose parent is either not new, or
+          // whose parent happens to be new only because it has been reparented.
+          bool is_subtree = !node->parent() ||
+                            new_nodes.find(node->parent()) == new_nodes.end() ||
+                            update_state.HasRemovedNode(node->parent());
           change = is_subtree ? AXTreeDelegate::SUBTREE_CREATED
                               : AXTreeDelegate::NODE_CREATED;
         }
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index dda88e6..59ea6303 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -469,10 +469,14 @@
   ASSERT_EQ(1U, fake_delegate.created_ids().size());
   EXPECT_EQ(4, fake_delegate.created_ids()[0]);
 
-  ASSERT_EQ(0U, fake_delegate.subtree_creation_finished_ids().size());
+  ASSERT_EQ(1U, fake_delegate.subtree_creation_finished_ids().size());
+  EXPECT_EQ(4, fake_delegate.subtree_creation_finished_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.node_creation_finished_ids().size());
-  EXPECT_EQ(4, fake_delegate.node_creation_finished_ids()[0]);
+  ASSERT_EQ(1U, fake_delegate.subtree_reparented_finished_ids().size());
+  EXPECT_EQ(2, fake_delegate.subtree_reparented_finished_ids()[0]);
+
+  EXPECT_EQ(0U, fake_delegate.node_creation_finished_ids().size());
+  EXPECT_EQ(0U, fake_delegate.node_reparented_finished_ids().size());
 
   ASSERT_EQ(true, fake_delegate.root_changed());
 
diff --git a/ui/events/blink/DEPS b/ui/events/blink/DEPS
index a04f3df8..eacfdb9 100644
--- a/ui/events/blink/DEPS
+++ b/ui/events/blink/DEPS
@@ -10,6 +10,7 @@
   "+third_party/WebKit/public/platform/WebFloatSize.h",
   "+third_party/WebKit/public/platform/WebGestureEvent.h",
   "+third_party/WebKit/public/platform/WebInputEvent.h",
+  "+third_party/WebKit/public/platform/WebMouseWheelEvent.h",
   "+third_party/WebKit/public/platform/WebPoint.h",
   "+third_party/WebKit/public/web/WebActiveWheelFlingParameters.h",
 
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc
index 939a1c4..52cc8f6 100644
--- a/ui/events/blink/blink_event_util.cc
+++ b/ui/events/blink/blink_event_util.cc
@@ -17,6 +17,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/gesture_detection/gesture_event_data.h"
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 0bc9e4691e..e37d499 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -20,6 +20,7 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/compositor_thread_event_queue.h"
 #include "ui/events/blink/did_overscroll_params.h"
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h
index a24ceb9..d73ff9c 100644
--- a/ui/events/blink/input_handler_proxy.h
+++ b/ui/events/blink/input_handler_proxy.h
@@ -24,6 +24,10 @@
 class TickClock;
 }
 
+namespace blink {
+class WebMouseWheelEvent;
+}
+
 namespace ui {
 
 namespace test {
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index deac383..d39f664 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -20,6 +20,7 @@
 #include "third_party/WebKit/public/platform/WebFloatSize.h"
 #include "third_party/WebKit/public/platform/WebGestureCurve.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 #include "third_party/WebKit/public/platform/WebPoint.h"
 #include "ui/events/blink/blink_event_util.h"
 #include "ui/events/blink/compositor_thread_event_queue.h"
diff --git a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
index 18dc760..6349947 100644
--- a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
+++ b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include "cc/input/input_handler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace ui {
 namespace {
diff --git a/ui/events/blink/web_input_event.h b/ui/events/blink/web_input_event.h
index caac517c..3333b29 100644
--- a/ui/events/blink/web_input_event.h
+++ b/ui/events/blink/web_input_event.h
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace gfx {
 class Point;
diff --git a/ui/events/blink/web_input_event_builders_win.h b/ui/events/blink/web_input_event_builders_win.h
index e23ce9c..74dc176 100644
--- a/ui/events/blink/web_input_event_builders_win.h
+++ b/ui/events/blink/web_input_event_builders_win.h
@@ -8,6 +8,7 @@
 #include <windows.h>
 
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 namespace ui {
 
diff --git a/ui/events/blink/web_input_event_traits.cc b/ui/events/blink/web_input_event_traits.cc
index 58d95c9..dddf7659 100644
--- a/ui/events/blink/web_input_event_traits.cc
+++ b/ui/events/blink/web_input_event_traits.cc
@@ -6,6 +6,8 @@
 
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 using base::StringAppendF;
 using base::SStringPrintf;
@@ -254,7 +256,7 @@
 
 // static
 LatencyInfo WebInputEventTraits::CreateLatencyInfoForWebGestureEvent(
-    WebGestureEvent event) {
+    const WebGestureEvent& event) {
   SourceEventType source_event_type = SourceEventType::UNKNOWN;
   if (event.sourceDevice == blink::WebGestureDevice::WebGestureDeviceTouchpad) {
     source_event_type = SourceEventType::WHEEL;
diff --git a/ui/events/blink/web_input_event_traits.h b/ui/events/blink/web_input_event_traits.h
index 88ab04f..fdcef0a 100644
--- a/ui/events/blink/web_input_event_traits.h
+++ b/ui/events/blink/web_input_event_traits.h
@@ -5,11 +5,15 @@
 #ifndef UI_EVENTS_BLINK_WEB_INPUT_EVENT_TRAITS_H_
 #define UI_EVENTS_BLINK_WEB_INPUT_EVENT_TRAITS_H_
 
-#include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
 #include "ui/events/blink/scoped_web_input_event.h"
 #include "ui/events/latency_info.h"
 
+namespace blink {
+class WebGestureEvent;
+class WebMouseWheelEvent;
+}
+
 namespace ui {
 
 // Utility class for performing operations on and with WebInputEvents.
@@ -26,7 +30,7 @@
   // Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
   static uint32_t GetUniqueTouchEventId(const blink::WebInputEvent& event);
   static LatencyInfo CreateLatencyInfoForWebGestureEvent(
-      blink::WebGestureEvent event);
+      const blink::WebGestureEvent& event);
 };
 
 }  // namespace ui
diff --git a/ui/events/blink/web_input_event_traits_unittest.cc b/ui/events/blink/web_input_event_traits_unittest.cc
index 8837525..4b347f14 100644
--- a/ui/events/blink/web_input_event_traits_unittest.cc
+++ b/ui/events/blink/web_input_event_traits_unittest.cc
@@ -5,7 +5,9 @@
 #include "ui/events/blink/web_input_event_traits.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
+#include "third_party/WebKit/public/platform/WebMouseWheelEvent.h"
 
 using blink::WebGestureEvent;
 using blink::WebInputEvent;
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index a1f9c69..073f687 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -408,26 +408,6 @@
   ]
 }
 
-# Non-Ozone trybots end up trying to build this when building "all" and failing
-# when X11 isn't there.
-if (ozone_platform_x11) {
-  group("gl_unittests_ozonex") {
-    testonly = true
-    data_deps = [
-      ":gl_unittests",
-    ]
-  }
-
-  # TODO(GYP_GONE): Delete this after we've converted everything to GN.
-  # The _run targets exist only for compatibility w/ GYP.
-  group("gl_unittests_ozonex_run") {
-    testonly = true
-    deps = [
-      ":gl_unittests_ozonex",
-    ]
-  }
-}
-
 if (is_android) {
   generate_jar_jni("surface_jni_headers") {
     jni_package = "ui/gl"
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
index 5c4cd8d..b806cb8 100644
--- a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
+++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -15,8 +15,7 @@
       }
 
       paper-icon-button {
-        @apply(--cr-icon-size);
-        padding: 0;
+        @apply(--cr-paper-icon-button-margin);
       }
     </style>
     <content></content>
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
index 63ee45fb..79020dd 100644
--- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
+++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -38,7 +38,7 @@
       }
 
       paper-spinner-lite {
-        @apply(--cr-icon-size);
+        @apply(--cr-icon-height-width);
         --paper-spinner-color: white;
         margin: 0 6px;
         opacity: 0;
diff --git a/ui/webui/resources/cr_elements/network/cr_network_list_item.html b/ui/webui/resources/cr_elements/network/cr_network_list_item.html
index 5b93941..616385f 100644
--- a/ui/webui/resources/cr_elements/network/cr_network_list_item.html
+++ b/ui/webui/resources/cr_elements/network/cr_network_list_item.html
@@ -17,12 +17,6 @@
         outline: none;
       }
 
-      #divButtons {
-        align-items: center;
-        display: flex;
-        flex-direction: row;
-      }
-
       #divDetail {
         display: flex;
         flex: 1 0 auto;
@@ -42,9 +36,8 @@
         border-style: none;
         display: flex;
         flex-direction: row;
-        margin: 0;
         height: 32px;
-        padding: 4px;
+        margin: 4px 12px;
       }
 
       #divOuter[first-custom-item] {
@@ -117,11 +110,9 @@
       </template>
       <template is="dom-if"
           if="[[isSubpageButtonVisible_(networkState, showButtons)]]">
-        <div id="divButtons">
-          <button class="subpage-arrow" is="paper-icon-button-light"
-              on-tap="fireShowDetails_" tabindex$="[[tabindex]]">
-          </button>
-        </div>
+        <button class="subpage-arrow" is="paper-icon-button-light"
+            on-tap="fireShowDetails_" tabindex$="[[tabindex]]">
+        </button>
       </template>
     </div>
   </template>
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html b/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html
index 73ca337..e896203 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html
@@ -2,7 +2,7 @@
 <style is="custom-style">
   :root {
     --cr-policy-indicator: {
-      @apply(--cr-icon-size);
+      @apply(--cr-icon-height-width);
       display: block;
     };
 
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html
index fc389774..e34ab9a 100644
--- a/ui/webui/resources/cr_elements/shared_style_css.html
+++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -41,6 +41,16 @@
         @apply(--cr-actionable);
       }
 
+      button[is='paper-icon-button-light'] {
+        @apply(--cr-paper-icon-button-margin);
+        background-position: center;
+        background-repeat: no-repeat;
+        background-size: var(--cr-icon-size);
+        flex-shrink: 0;
+        height: var(--cr-icon-ripple-size);
+        width: var(--cr-icon-ripple-size);
+      }
+
       button[is='paper-icon-button-light'].subpage-arrow {
         background-image: url(../images/arrow_right.svg);
       }
@@ -54,6 +64,10 @@
         display: none;
       }
 
+      paper-icon-button.subpage-arrow {
+        background-image: url(../images/arrow_right.svg);
+      }
+
       [actionable] :-webkit-any(.subpage-arrow, .icon-external),
       [actionable]:-webkit-any(.subpage-arrow, .icon-external) {
         display: block;
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html
index b823816..21d27d1 100644
--- a/ui/webui/resources/cr_elements/shared_vars_css.html
+++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -9,10 +9,21 @@
     --cr-focused-item-color: var(--google-grey-300);
     /* Same padding as paper-icon-button. */
     --cr-icon-padding: 8px;
-    --cr-icon-size: {
-      height: 20px;
-      width: 20px;
+
+    /* The inner icon is 20px in size. paper-icon-button has 8px padding. */
+    --cr-icon-ripple-size: 36px;
+    --cr-icon-size: 20px;
+
+    --cr-icon-height-width: {
+      height: var(--cr-icon-size);
+      width: var(--cr-icon-size);
     }
+
+    --cr-paper-icon-button-margin: {
+      -webkit-margin-end: -8px;  /* Allow ripple to overlap the end. */
+      -webkit-margin-start: 16px;
+    }
+
     --cr-selectable-focus: {
       background-color: var(--cr-focused-item-color);
       outline: none;